Diff options
Diffstat (limited to '')
-rw-r--r--source/ui-diff.c126
1 file changed, 34 insertions, 92 deletions
diff --git a/source/ui-diff.c b/source/ui-diff.c
index 91ad860..315a8f0 100644
--- a/source/ui-diff.c
+++ b/source/ui-diff.c
@@ -54,7 +54,6 @@ static int bodies_usable;
static linediff_fn render_line_fn;
static int render_suppressed;
-static struct diff_filepair *current_filepair;
static const char *current_prefix;
static int use_ssdiff;
@@ -187,15 +186,9 @@ static int show_filepair(struct diff_filepair *pair)
starts_with(pair->two->path, current_prefix);
}
-/*
- * The line xdiff produces ends in its newline, which is swapped for a
- * terminator while the text is escaped and then put back, because the line
- * points into a buffer xdiff still owns.
- */
static void print_line(char *line, int len)
{
const char *class = "ctx";
- char c = line[len - 1];
if (line[0] == '+')
class = "add";
@@ -205,31 +198,26 @@ static void print_line(char *line, int len)
class = "hunk";
htmlf("<div class='%s'>", class);
- line[len - 1] = '\0';
- html_txt(line);
+ html_ntxt(line, len - 1);
html("</div>");
- line[len - 1] = c;
}
/*
- * The buffer repo_find_unique_abbrev returns is reused, so a caller printing
- * two abbreviated names together keeps a copy of each.
+ * Opens the group end_file closes, in whichever view the page uses, and writes
+ * the header of the pair's diff into it.
*/
-static char *abbrev_oid(const struct object_id *oid)
-{
- return xstrdup(repo_find_unique_abbrev(the_repository, oid, DEFAULT_ABBREV));
-}
-
-static void print_file_header(const struct object_id *old_oid, const char *old_path, unsigned old_mode,
- const struct object_id *new_oid, const char *new_path, unsigned new_mode)
+static void print_file_header(struct diff_filepair *pair)
{
- char *old_abbrev, *new_abbrev;
+ const struct object_id *old_oid = &pair->one->oid, *new_oid = &pair->two->oid;
+ const char *old_path = pair->one->path, *new_path = pair->two->path;
+ unsigned old_mode = pair->one->mode, new_mode = pair->two->mode;
+ char old_abbrev[GIT_MAX_HEXSZ + 1], new_abbrev[GIT_MAX_HEXSZ + 1];
int subproject;
subproject = (S_ISGITLINK(old_mode) || S_ISGITLINK(new_mode));
- // The side by side view opens its file group before the header row,
- // so only the unified view opens one here.
- if (!use_ssdiff) {
+ if (use_ssdiff) {
+ cgit_ssdiff_header_begin(pair);
+ } else {
html("<div class='file' data-path='");
html_attr(new_path);
html("'>");
@@ -247,11 +235,9 @@ static void print_file_header(const struct object_id *old_oid, const char *old_p
htmlf("<br>deleted file mode %.6o", old_mode);
if (!subproject) {
- old_abbrev = abbrev_oid(old_oid);
- new_abbrev = abbrev_oid(new_oid);
+ repo_find_unique_abbrev_r(the_repository, old_abbrev, old_oid, DEFAULT_ABBREV);
+ repo_find_unique_abbrev_r(the_repository, new_abbrev, new_oid, DEFAULT_ABBREV);
htmlf("<br>index %s..%s", old_abbrev, new_abbrev);
- free(old_abbrev);
- free(new_abbrev);
if (old_mode != 0 && new_mode != 0) {
htmlf(" %.6o", old_mode);
if (new_mode != old_mode)
@@ -279,12 +265,13 @@ static void print_file_header(const struct object_id *old_oid, const char *old_p
html_txt(new_path);
}
html("</div>");
+ if (use_ssdiff)
+ cgit_ssdiff_header_end();
}
/*
- * Closes the group print_file_header or cgit_ssdiff_header_begin opened. The
- * side by side footer closes its own, so the unified view is the only one with
- * work to do here.
+ * Closes the group print_file_header opened. The side by side footer closes its
+ * own, so the unified view is the only one with work to do here.
*/
static void end_file(void)
{
@@ -338,17 +325,13 @@ static void print_truncated(const char *path)
static struct fileinfo *reserve_item(void)
{
- files++;
- if (files >= slots) {
- if (slots == 0)
- slots = 4;
- else
- slots = slots * 2;
- items = xrealloc(items, slots * sizeof(struct fileinfo));
- }
- memset(&items[files - 1], 0, sizeof(items[files - 1]));
- strbuf_init(&items[files - 1].body, 0);
- return &items[files - 1];
+ struct fileinfo *item;
+
+ ALLOC_GROW(items, files + 1, slots);
+ item = &items[files++];
+ memset(item, 0, sizeof(*item));
+ strbuf_init(&item->body, 0);
+ return item;
}
/*
@@ -362,15 +345,8 @@ static void collect_body(struct diff_filepair *pair, struct fileinfo *item, int
linediff_fn line_fn = use_ssdiff ? cgit_ssdiff_line_cb : print_line;
size_t header_len;
- current_filepair = pair;
-
html_capture_begin(body);
- if (use_ssdiff)
- cgit_ssdiff_header_begin(pair->two->path);
- print_file_header(&pair->one->oid, pair->one->path, pair->one->mode,
- &pair->two->oid, pair->two->path, pair->two->mode);
- if (use_ssdiff)
- cgit_ssdiff_header_end();
+ print_file_header(pair);
header_len = body->len;
// Cleared for the whole file rather than in the branch below, because
@@ -468,7 +444,6 @@ static void print_diffstat(const struct object_id *old_oid, const struct object_
html("')");
}
html("</div>\n");
- max_changes = 0;
cgit_diff_tree(old_oid, new_oid, inspect_filepair, prefix, ctx.qry.ignorews);
// A change to no files would leave the table an empty frame.
if (files) {
@@ -498,21 +473,13 @@ static void filepair_cb(struct diff_filepair *pair)
size_t new_size = 0;
int binary = 0;
int idx;
- linediff_fn line_fn = print_line;
+ linediff_fn line_fn = use_ssdiff ? cgit_ssdiff_line_cb : print_line;
if (!show_filepair(pair))
return;
idx = item_idx++;
- current_filepair = pair;
- if (use_ssdiff) {
- cgit_ssdiff_header_begin(pair->two->path);
- line_fn = cgit_ssdiff_line_cb;
- }
- print_file_header(&pair->one->oid, pair->one->path, pair->one->mode,
- &pair->two->oid, pair->two->path, pair->two->mode);
- if (use_ssdiff)
- cgit_ssdiff_header_end();
+ print_file_header(pair);
if (over_line_cap(idx)) {
print_truncated(items[idx].new_path);
@@ -557,16 +524,6 @@ static void print_raw_patch(const struct object_id *old_tree_oid, const struct o
diff_flush(&diffopt);
}
-struct diff_filespec *cgit_get_current_old_file(void)
-{
- return current_filepair->one;
-}
-
-struct diff_filespec *cgit_get_current_new_file(void)
-{
- return current_filepair->two;
-}
-
void cgit_print_diff_ctrls(void)
{
int i, selected;
@@ -574,7 +531,7 @@ void cgit_print_diff_ctrls(void)
html("<div class='cgit-panel'>\n");
html("<strong>Diff options</strong>");
html("<form method='get' aria-label='Diff options'>");
- cgit_add_hidden_formfields(1, 0, ctx.qry.page);
+ cgit_add_hidden_formfields(1, 0);
html("<div class='fields'>");
html("<label for='diff-context'>context</label>");
html("<select id='diff-context' name='context'>");
@@ -647,31 +604,17 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefi
if (!new_rev)
new_rev = ctx.qry.head;
- if (repo_get_oid(the_repository, new_rev, new_rev_oid)) {
- cgit_print_error_page(404, "Not Found", "Bad object id: %s", new_rev);
- return;
- }
- new_commit = lookup_commit_reference(the_repository, new_rev_oid);
- if (!new_commit || repo_parse_commit(the_repository, new_commit)) {
- cgit_print_error_page(404, "Not Found", "Not a commit: %s", oid_to_hex(new_rev_oid));
+ new_commit = cgit_get_commit(new_rev, new_rev_oid);
+ if (!new_commit || cgit_get_old_oid(old_rev, new_commit, old_rev_oid))
return;
- }
new_tree_oid = get_commit_tree_oid(new_commit);
- if (old_rev) {
- if (repo_get_oid(the_repository, old_rev, old_rev_oid)) {
- cgit_print_error_page(404, "Not Found", "Bad object id: %s", old_rev);
- return;
- }
- } else if (new_commit->parents && new_commit->parents->item) {
- oidcpy(old_rev_oid, &new_commit->parents->item->object.oid);
- } else {
- oidclr(old_rev_oid, the_repository->hash_algo);
- }
-
if (!is_null_oid(old_rev_oid)) {
+ // A named old side is a commit already, so only a first parent
+ // missing from the repository fails here, and it has no name
+ // but its id.
old_commit = lookup_commit_reference(the_repository, old_rev_oid);
- if (!old_commit || repo_parse_commit(the_repository, old_commit)) {
+ if (!old_commit) {
cgit_print_error_page(404, "Not Found", "Not a commit: %s", oid_to_hex(old_rev_oid));
return;
}
@@ -742,7 +685,6 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefi
html_raw(items[i].body.buf, items[i].body.len);
release_bodies();
} else {
- item_idx = 0;
cgit_diff_tree(old_rev_oid, new_rev_oid, filepair_cb, prefix, ctx.qry.ignorews);
}
if (!use_ssdiff)