Diffstat (limited to 'ui-patch.c')
| -rw-r--r-- | ui-patch.c | 173 |
1 files changed, 102 insertions, 71 deletions
@@ -1,100 +1,131 @@ /* ui-patch.c: generate patch view * - * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com> + * Copyright (C) 2007 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ -#define USE_THE_REPOSITORY_VARIABLE - #include "cgit.h" -#include "ui-patch.h" #include "html.h" #include "ui-shared.h" -/* two commit hashes with two dots in between and termination */ -#define REV_RANGE_LEN 2 * GIT_MAX_HEXSZ + 3 +static void print_line(char *line, int len) +{ + char c = line[len-1]; + + line[len-1] = '\0'; + htmlf("%s\n", line); + line[len-1] = c; +} + +static void header(unsigned char *sha1, char *path1, int mode1, + unsigned char *sha2, char *path2, int mode2) +{ + char *abbrev1, *abbrev2; + int subproject; + + subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); + htmlf("diff --git a/%s b/%s\n", path1, path2); + + if (is_null_sha1(sha1)) + path1 = "dev/null"; + if (is_null_sha1(sha2)) + path2 = "dev/null"; -void cgit_print_patch(const char *new_rev, const char *old_rev, - const char *prefix) + if (mode1 == 0) + htmlf("new file mode %.6o\n", mode2); + + if (mode2 == 0) + htmlf("deleted file mode %.6o\n", mode1); + + if (!subproject) { + abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); + abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); + htmlf("index %s..%s", abbrev1, abbrev2); + free(abbrev1); + free(abbrev2); + if (mode1 != 0 && mode2 != 0) { + htmlf(" %.6o", mode1); + if (mode2 != mode1) + htmlf("..%.6o", mode2); + } + htmlf("\n--- a/%s\n", path1); + htmlf("+++ b/%s\n", path2); + } +} + +static void filepair_cb(struct diff_filepair *pair) +{ + unsigned long old_size = 0; + unsigned long new_size = 0; + int binary = 0; + + header(pair->one->sha1, pair->one->path, pair->one->mode, + pair->two->sha1, pair->two->path, pair->two->mode); + if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { + if (S_ISGITLINK(pair->one->mode)) + print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); + if (S_ISGITLINK(pair->two->mode)) + print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); + return; + } + if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, + &new_size, &binary, 0, print_line)) + html("Error running diff"); + if (binary) + html("Binary files differ\n"); +} + +void cgit_print_patch(char *hex, const char *prefix) { - struct rev_info rev; struct commit *commit; - struct object_id new_rev_oid, old_rev_oid; - char rev_range[REV_RANGE_LEN]; - const char *rev_argv[] = { NULL, "--reverse", "--format=email", rev_range, "--", prefix, NULL }; - int rev_argc = ARRAY_SIZE(rev_argv) - 1; + struct commitinfo *info; + unsigned char sha1[20], old_sha1[20]; char *patchname; - if (!prefix) - rev_argc--; + if (!hex) + hex = ctx.qry.head; - 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); + if (get_sha1(hex, sha1)) { + cgit_print_error(fmt("Bad object id: %s", hex)); return; } - commit = lookup_commit_reference(the_repository, &new_rev_oid); + commit = lookup_commit_reference(sha1); if (!commit) { - cgit_print_error_page(404, "Not found", - "Bad commit reference: %s", new_rev); + cgit_print_error(fmt("Bad commit reference: %s", hex)); return; } + info = cgit_parse_commit(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; - } - if (!lookup_commit_reference(the_repository, &old_rev_oid)) { - cgit_print_error_page(404, "Not found", - "Bad commit reference: %s", old_rev); - return; - } - } else if (commit->parents && commit->parents->item) { - oidcpy(&old_rev_oid, &commit->parents->item->object.oid); - } else { - oidclr(&old_rev_oid, the_repository->hash_algo); - } + if (commit->parents && commit->parents->item) + hashcpy(old_sha1, commit->parents->item->object.sha1); + else + hashclr(old_sha1); - if (is_null_oid(&old_rev_oid)) { - memcpy(rev_range, oid_to_hex(&new_rev_oid), the_hash_algo->hexsz + 1); - } else { - xsnprintf(rev_range, REV_RANGE_LEN, "%s..%s", oid_to_hex(&old_rev_oid), - oid_to_hex(&new_rev_oid)); - } - - patchname = fmt("%s.patch", rev_range); + patchname = fmt("%s.patch", sha1_to_hex(sha1)); ctx.page.mimetype = "text/plain"; ctx.page.filename = patchname; - cgit_print_http_headers(); - - if (ctx.cfg.noplainemail) { - rev_argv[2] = "--format=format:From %H Mon Sep 17 00:00:00 " - "2001%nFrom: %an%nDate: %aD%n%w(78,0,1)Subject: " - "%s%n%n%w(0)%b"; + cgit_print_http_headers(&ctx); + htmlf("From %s Mon Sep 17 00:00:00 2001\n", sha1_to_hex(sha1)); + htmlf("From: %s", info->author); + if (!ctx.cfg.noplainemail) { + htmlf(" %s", info->author_email); } - - repo_init_revisions(the_repository, &rev, NULL); - rev.abbrev = DEFAULT_ABBREV; - rev.verbose_header = 1; - rev.diff = 1; - rev.show_root_diff = 1; - rev.max_parents = 1; - rev.diffopt.output_format |= DIFF_FORMAT_DIFFSTAT | - DIFF_FORMAT_PATCH | DIFF_FORMAT_SUMMARY; - if (prefix) - rev.diffopt.stat_sep = fmt("(limited to '%s')\n\n", prefix); - setup_revisions(rev_argc, rev_argv, &rev, NULL); - prepare_revision_walk(&rev); - - while ((commit = get_revision(&rev)) != NULL) { - log_tree_commit(&rev, commit); - printf("-- \ncgit %s\n\n", cgit_version); + html("\n"); + html("Date: "); + cgit_print_date(info->author_date, "%a, %d %b %Y %H:%M:%S %z%n", ctx.cfg.local_time); + htmlf("Subject: %s\n\n", info->subject); + if (info->msg && *info->msg) { + htmlf("%s", info->msg); + if (info->msg[strlen(info->msg) - 1] != '\n') + html("\n"); } + html("---\n"); + if (prefix) + htmlf("(limited to '%s')\n\n", prefix); + cgit_diff_tree(old_sha1, sha1, filepair_cb, prefix); + html("--\n"); + htmlf("cgit %s\n", CGIT_VERSION); + cgit_free_commitinfo(info); } |