commit - 45202a8f5e7659326a88147e7eecbef20545add2
commit + c35a7943488e43a4fc6c48a00cf858ba8f410947
blob - 1dcf38b4c06596714780a7ea6b58464c1ad509ec
blob + 34624017c79b7a30d72aa532073224e79b3fcf78
--- got/Makefile
+++ got/Makefile
.PATH:${.CURDIR}/../lib
PROG= got
-SRCS= got.c blame.c commit_graph.c delta.c diff.c diffreg.c error.c \
- fileindex.c object.c object_idcache.c object_idset.c opentemp.c \
- path.c pack.c privsep.c reference.c repository.c sha1.c \
- worktree.c inflate.c
+SRCS= got.c blame.c commit_graph.c delta.c diff.c diffoffset.c \
+ diffreg.c error.c fileindex.c object.c object_idcache.c \
+ object_idset.c opentemp.c path.c pack.c privsep.c reference.c \
+ repository.c sha1.c worktree.c inflate.c
CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib
LDADD = -lutil -lz
blob - e5c55ef07aa6ac499be912c4de1fc41b0874dc2b
blob + 67a5c59587fdedd7aeaa91e2d271ef19d02b018c
--- lib/blame.c
+++ lib/blame.c
#include "got_lib_delta.h"
#include "got_lib_object.h"
#include "got_lib_diff.h"
+#include "got_lib_diffoffset.h"
struct got_blame_line {
int annotated;
struct got_object_id id;
};
+struct got_blame_diff_offsets {
+ struct got_diffoffset_chunks *chunks;
+ struct got_object_id *commit_id;
+ SLIST_ENTRY(got_blame_diff_offsets) entry;
+};
+
+SLIST_HEAD(got_blame_diff_offsets_list, got_blame_diff_offsets);
+
struct got_blame {
FILE *f;
size_t nlines;
struct got_blame_line *lines; /* one per line */
+ int ncommits;
+ struct got_blame_diff_offsets_list diff_offsets_list;
};
+static void
+free_diff_offsets(struct got_blame_diff_offsets *diff_offsets)
+{
+ if (diff_offsets->chunks)
+ got_diffoffset_free(diff_offsets->chunks);
+ free(diff_offsets->commit_id);
+ free(diff_offsets);
+}
+
static const struct got_error *
+alloc_diff_offsets(struct got_blame_diff_offsets **diff_offsets,
+ struct got_object_id *commit_id)
+{
+ const struct got_error *err = NULL;
+
+ *diff_offsets = calloc(1, sizeof(**diff_offsets));
+ if (*diff_offsets == NULL)
+ return got_error_from_errno();
+
+ (*diff_offsets)->commit_id = got_object_id_dup(commit_id);
+ if ((*diff_offsets)->commit_id == NULL) {
+ err = got_error_from_errno();
+ free_diff_offsets(*diff_offsets);
+ *diff_offsets = NULL;
+ return err;
+ }
+
+ err = got_diffoffset_alloc(&(*diff_offsets)->chunks);
+ if (err) {
+ free_diff_offsets(*diff_offsets);
+ return err;
+ }
+
+ return NULL;
+}
+
+static const struct got_error *
annotate_line(struct got_blame *blame, int lineno, struct got_object_id *id,
const struct got_error *(*cb)(void *, int, int, struct got_object_id *),
void *arg)
return err;
}
+static int
+get_blamed_line(struct got_blame_diff_offsets_list *diff_offsets_list,
+ int lineno)
+{
+ struct got_blame_diff_offsets *diff_offsets;
+
+ SLIST_FOREACH(diff_offsets, diff_offsets_list, entry)
+ lineno = got_diffoffset_get(diff_offsets->chunks, lineno);
+
+ return lineno;
+}
+
static const struct got_error *
+blame_changes(struct got_blame *blame, struct got_diff_changes *changes,
+ struct got_object_id *commit_id,
+ const struct got_error *(*cb)(void *, int, int, struct got_object_id *),
+ void *arg)
+{
+ const struct got_error *err = NULL;
+ struct got_diff_change *change;
+ struct got_blame_diff_offsets *diff_offsets;
+
+ SIMPLEQ_FOREACH(change, &changes->entries, entry) {
+ int c = change->cv.c;
+ int d = change->cv.d;
+ int new_lineno = c;
+ int new_length = (c < d ? d - c + 1 : (c == d ? 1 : 0));
+ int ln;
+
+ for (ln = new_lineno; ln < new_lineno + new_length; ln++) {
+ err = annotate_line(blame,
+ get_blamed_line(&blame->diff_offsets_list, ln),
+ commit_id, cb, arg);
+ if (err)
+ return err;
+ }
+ }
+
+ err = alloc_diff_offsets(&diff_offsets, commit_id);
+ if (err)
+ return err;
+ SIMPLEQ_FOREACH(change, &changes->entries, entry) {
+ int a = change->cv.a;
+ int b = change->cv.b;
+ int c = change->cv.c;
+ int d = change->cv.d;
+ int old_lineno = a;
+ int old_length = (a < b ? b - a + 1 : (a == b ? 1 : 0));
+ int new_lineno = c;
+ int new_length = (c < d ? d - c + 1 : (c == d ? 1 : 0));
+
+ err = got_diffoffset_add(diff_offsets->chunks,
+ old_lineno, old_length, new_lineno, new_length);
+ if (err)
+ return err;
+ }
+ SLIST_INSERT_HEAD(&blame->diff_offsets_list, diff_offsets, entry);
+
+ return NULL;
+}
+
+static const struct got_error *
blame_commit(struct got_blame *blame, struct got_object_id *id,
struct got_object_id *pid, const char *path, struct got_repository *repo,
const struct got_error *(*cb)(void *, int, int, struct got_object_id *),
if (err)
goto done;
- err = got_diff_blob_lines_changed(&changes, blob, pblob);
+ err = got_diff_blob_lines_changed(&changes, pblob, blob);
if (err)
goto done;
if (changes) {
- struct got_diff_change *change;
- SIMPLEQ_FOREACH(change, &changes->entries, entry) {
- int a = change->cv.a;
- int b = change->cv.b;
- int lineno;
- for (lineno = a; lineno <= b; lineno++) {
- err = annotate_line(blame, lineno, id, cb, arg);
- if (err)
- goto done;
- }
- }
+ err = blame_changes(blame, changes, id, cb, arg);
} else if (cb)
err = cb(arg, blame->nlines, -1, id);
done:
static void
blame_close(struct got_blame *blame)
{
+ struct got_blame_diff_offsets *diff_offsets;
+
if (blame->f)
fclose(blame->f);
free(blame->lines);
+ while (!SLIST_EMPTY(&blame->diff_offsets_list)) {
+ diff_offsets = SLIST_FIRST(&blame->diff_offsets_list);
+ SLIST_REMOVE_HEAD(&blame->diff_offsets_list, entry);
+ free_diff_offsets(diff_offsets);
+ }
free(blame);
}
blob - /dev/null
blob + 6d1af1ad443cf2c9732c10f711a9708c952f4a0e (mode 644)
--- /dev/null
+++ lib/diffoffset.c
+/*
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sha1.h>
+#include <zlib.h>
+
+#include "got_object.h"
+
+#include "got_error.h"
+#include "got_lib_delta.h"
+#include "got_lib_inflate.h"
+#include "got_lib_object.h"
+#include "got_lib_diffoffset.h"
+
+/*
+ * A line offset between an old file and a new file, derived from diff chunk
+ * header info @@ -old_lineno,old_length +new_lineno,new_length @@ in a diff
+ * with zero context lines (as in diff -U0 old-file new-file).
+ */
+struct got_diffoffset_chunk {
+ int lineno; /* first line which has shifted */
+ int offset; /* applies to subsequent lines until next chunk */
+ SIMPLEQ_ENTRY(got_diffoffset_chunk) entry;
+};
+
+static struct got_diffoffset_chunk *
+alloc_chunk(int lineno, int offset)
+{
+ struct got_diffoffset_chunk *chunk;
+
+ chunk = calloc(1, sizeof(*chunk));
+ if (chunk == NULL)
+ return NULL;
+
+ chunk->lineno = lineno;
+ chunk->offset = offset;
+
+ return chunk;
+}
+
+const struct got_error *
+got_diffoffset_alloc(struct got_diffoffset_chunks **chunks)
+{
+ const struct got_error *err = NULL;
+ struct got_diffoffset_chunk *first;
+
+ first = alloc_chunk(0, 0);
+ if (first == NULL)
+ return got_error_from_errno();
+
+ *chunks = calloc(1, sizeof(**chunks));
+ if (*chunks == NULL) {
+ err = got_error_from_errno();
+ free(first);
+ return err;
+ }
+
+ SIMPLEQ_INIT(*chunks);
+ SIMPLEQ_INSERT_HEAD(*chunks, first, entry);
+
+ return NULL;
+}
+
+void
+got_diffoffset_free(struct got_diffoffset_chunks *chunks)
+{
+ struct got_diffoffset_chunk *chunk;
+
+ while (!SIMPLEQ_EMPTY(chunks)) {
+ chunk = SIMPLEQ_FIRST(chunks);
+ SIMPLEQ_REMOVE_HEAD(chunks, entry);
+ free(chunk);
+ }
+ free(chunks);
+}
+
+const struct got_error *
+got_diffoffset_add(struct got_diffoffset_chunks *chunks,
+ int old_lineno, int old_length, int new_lineno, int new_length)
+{
+ struct got_diffoffset_chunk *chunk1, *chunk2;
+
+ chunk1 = alloc_chunk(old_lineno, new_lineno - old_lineno);
+ if (chunk1 == NULL)
+ return got_error_from_errno();
+
+ chunk2 = alloc_chunk(old_lineno + old_length,
+ new_lineno - old_lineno + new_length - old_length);
+ if (chunk2 == NULL) {
+ const struct got_error *err = got_error_from_errno();
+ free(chunk1);
+ return err;
+ }
+
+ SIMPLEQ_INSERT_TAIL(chunks, chunk1, entry);
+ SIMPLEQ_INSERT_TAIL(chunks, chunk2, entry);
+ return NULL;
+}
+
+int
+got_diffoffset_get(struct got_diffoffset_chunks *chunks, int lineno)
+{
+ struct got_diffoffset_chunk *chunk, *prev;
+
+ prev = SIMPLEQ_FIRST(chunks);
+ SIMPLEQ_FOREACH(chunk, chunks, entry) {
+ if (chunk->lineno > lineno)
+ break;
+ prev = chunk;
+ }
+
+ return lineno + prev->offset;
+}
blob - /dev/null
blob + 705d33a582f9bfabcaf7d4aac05826d8123084bd (mode 644)
--- /dev/null
+++ lib/got_lib_diffoffset.h
+/*
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+SIMPLEQ_HEAD(got_diffoffset_chunks, got_diffoffset_chunk);
+
+const struct got_error *got_diffoffset_alloc(struct got_diffoffset_chunks **);
+void got_diffoffset_free(struct got_diffoffset_chunks *);
+const struct got_error *got_diffoffset_add(struct got_diffoffset_chunks *,
+ int, int, int, int);
+int got_diffoffset_get(struct got_diffoffset_chunks *, int);
blob - 06bda662dc489c32771945b9cdb976211c884a6e
blob + dbaa942edff0f3aeff645f149e86fb18cc6d4ab8
--- tog/Makefile
+++ tog/Makefile
.PATH:${.CURDIR}/../lib
PROG= tog
-SRCS= tog.c blame.c commit_graph.c delta.c diff.c diffreg.c error.c \
- fileindex.c object.c object_idcache.c object_idset.c \
- opentemp.c path.c pack.c privsep.c reference.c repository.c \
- sha1.c worktree.c utf8.c inflate.c
+SRCS= tog.c blame.c commit_graph.c delta.c diff.c diffoffset.c \
+ diffreg.c error.c fileindex.c object.c object_idcache.c \
+ object_idset.c opentemp.c path.c pack.c privsep.c \
+ reference.c repository.c sha1.c worktree.c utf8.c inflate.c
CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib
LDADD = -lpanel -lncursesw -lutil -lz -lpthread