author | Lars Hjemli <hjemli@gmail.com> | 2007-05-16 02:21:06 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2007-05-16 02:21:06 (UTC) |
commit | f4f1339fe62fb1a28c147567195a86dd99485e25 (patch) (unidiff) | |
tree | 948b58f6bc18ec87f81f84221510eec85c41e16d /ui-diff.c | |
parent | d82c08a0446aa712a7d825e07f3d51796421b3a2 (diff) | |
download | cgit-f4f1339fe62fb1a28c147567195a86dd99485e25.zip cgit-f4f1339fe62fb1a28c147567195a86dd99485e25.tar.gz cgit-f4f1339fe62fb1a28c147567195a86dd99485e25.tar.bz2 |
Don't die when diffing trees with subprojects
The subprojects needs special handling, since they refer to objects
which normally won't exist in the refering repository.
Fix some extended header bugs and missing features while at it.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | ui-diff.c | 62 |
1 files changed, 43 insertions, 19 deletions
@@ -1,117 +1,141 @@ | |||
1 | /* ui-diff.c: show diff between two blobs | 1 | /* ui-diff.c: show diff between two blobs |
2 | * | 2 | * |
3 | * Copyright (C) 2006 Lars Hjemli | 3 | * Copyright (C) 2006 Lars Hjemli |
4 | * | 4 | * |
5 | * Licensed under GNU General Public License v2 | 5 | * Licensed under GNU General Public License v2 |
6 | * (see COPYING for full license text) | 6 | * (see COPYING for full license text) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "cgit.h" | 9 | #include "cgit.h" |
10 | 10 | ||
11 | 11 | ||
12 | /* | 12 | /* |
13 | * print a single line returned from xdiff | 13 | * print a single line returned from xdiff |
14 | */ | 14 | */ |
15 | static void print_line(char *line, int len) | 15 | static void print_line(char *line, int len) |
16 | { | 16 | { |
17 | char *class = "ctx"; | 17 | char *class = "ctx"; |
18 | char c = line[len-1]; | 18 | char c = line[len-1]; |
19 | 19 | ||
20 | if (line[0] == '+') | 20 | if (line[0] == '+') |
21 | class = "add"; | 21 | class = "add"; |
22 | else if (line[0] == '-') | 22 | else if (line[0] == '-') |
23 | class = "del"; | 23 | class = "del"; |
24 | else if (line[0] == '@') | 24 | else if (line[0] == '@') |
25 | class = "hunk"; | 25 | class = "hunk"; |
26 | 26 | ||
27 | htmlf("<div class='%s'>", class); | 27 | htmlf("<div class='%s'>", class); |
28 | line[len-1] = '\0'; | 28 | line[len-1] = '\0'; |
29 | html_txt(line); | 29 | html_txt(line); |
30 | html("</div>"); | 30 | html("</div>"); |
31 | line[len-1] = c; | 31 | line[len-1] = c; |
32 | } | 32 | } |
33 | 33 | ||
34 | static void header(unsigned char *sha1, char *path1, | 34 | static void header(unsigned char *sha1, char *path1, int mode1, |
35 | unsigned char *sha2, char *path2) | 35 | unsigned char *sha2, char *path2, int mode2) |
36 | { | 36 | { |
37 | char *abbrev1, *abbrev2; | 37 | char *abbrev1, *abbrev2; |
38 | if (is_null_sha1(sha1)) | 38 | int subproject; |
39 | path1 = "dev/null"; | 39 | |
40 | if (is_null_sha1(sha2)) | 40 | subproject = (S_ISDIRLNK(mode1) || S_ISDIRLNK(mode2)); |
41 | path2 = "dev/null"; | ||
42 | html("<tr><td>"); | 41 | html("<tr><td>"); |
43 | html("<div class='head'>"); | 42 | html("<div class='head'>"); |
44 | html("diff --git a/"); | 43 | html("diff --git a/"); |
45 | html_txt(path1); | 44 | html_txt(path1); |
46 | html(" b/"); | 45 | html(" b/"); |
47 | html_txt(path2); | 46 | html_txt(path2); |
48 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); | 47 | |
49 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); | 48 | if (is_null_sha1(sha1)) |
50 | htmlf("\nindex %s..%s", abbrev1, abbrev2); | 49 | path1 = "dev/null"; |
51 | free(abbrev1); | 50 | if (is_null_sha1(sha2)) |
52 | free(abbrev2); | 51 | path2 = "dev/null"; |
53 | html("\n--- a/"); | 52 | |
54 | html_txt(path1); | 53 | if (mode1 == 0) |
55 | html("\n+++ b/"); | 54 | htmlf("<br/>new file mode %.6o", mode2); |
56 | html_txt(path2); | 55 | |
56 | if (mode2 == 0) | ||
57 | htmlf("<br/>deleted file mode %.6o", mode1); | ||
58 | |||
59 | if (!subproject) { | ||
60 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); | ||
61 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); | ||
62 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); | ||
63 | free(abbrev1); | ||
64 | free(abbrev2); | ||
65 | if (mode1 != 0 && mode2 != 0) { | ||
66 | htmlf(" %.6o", mode1); | ||
67 | if (mode2 != mode1) | ||
68 | htmlf("..%.6o", mode2); | ||
69 | } | ||
70 | html("<br/>--- a/"); | ||
71 | html_txt(path1); | ||
72 | html("<br/>+++ b/"); | ||
73 | html_txt(path2); | ||
74 | } | ||
57 | html("</div>"); | 75 | html("</div>"); |
58 | } | 76 | } |
59 | 77 | ||
60 | static void filepair_cb(struct diff_filepair *pair) | 78 | static void filepair_cb(struct diff_filepair *pair) |
61 | { | 79 | { |
62 | header(pair->one->sha1, pair->one->path, | 80 | header(pair->one->sha1, pair->one->path, pair->one->mode, |
63 | pair->two->sha1, pair->two->path); | 81 | pair->two->sha1, pair->two->path, pair->two->mode); |
82 | if (S_ISDIRLNK(pair->one->mode) || S_ISDIRLNK(pair->two->mode)) { | ||
83 | if (S_ISDIRLNK(pair->one->mode)) | ||
84 | print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); | ||
85 | if (S_ISDIRLNK(pair->two->mode)) | ||
86 | print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); | ||
87 | return; | ||
88 | } | ||
64 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line)) | 89 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line)) |
65 | cgit_print_error("Error running diff"); | 90 | cgit_print_error("Error running diff"); |
66 | html("</tr></td>"); | ||
67 | } | 91 | } |
68 | 92 | ||
69 | void cgit_print_diff(const char *head, const char *old_hex, const char *new_hex, char *path) | 93 | void cgit_print_diff(const char *head, const char *old_hex, const char *new_hex, char *path) |
70 | { | 94 | { |
71 | unsigned char sha1[20], sha2[20]; | 95 | unsigned char sha1[20], sha2[20]; |
72 | enum object_type type; | 96 | enum object_type type; |
73 | unsigned long size; | 97 | unsigned long size; |
74 | struct commit *commit; | 98 | struct commit *commit; |
75 | 99 | ||
76 | if (head && !old_hex && !new_hex) { | 100 | if (head && !old_hex && !new_hex) { |
77 | get_sha1(head, sha1); | 101 | get_sha1(head, sha1); |
78 | commit = lookup_commit_reference(sha1); | 102 | commit = lookup_commit_reference(sha1); |
79 | if (commit && !parse_commit(commit)) { | 103 | if (commit && !parse_commit(commit)) { |
80 | html("<table class='diff'>"); | 104 | html("<table class='diff'>"); |
81 | cgit_diff_commit(commit, filepair_cb); | 105 | cgit_diff_commit(commit, filepair_cb); |
82 | html("</td></tr></table>"); | 106 | html("</td></tr></table>"); |
83 | } | 107 | } |
84 | return; | 108 | return; |
85 | } | 109 | } |
86 | 110 | ||
87 | get_sha1(old_hex, sha1); | 111 | get_sha1(old_hex, sha1); |
88 | get_sha1(new_hex, sha2); | 112 | get_sha1(new_hex, sha2); |
89 | 113 | ||
90 | type = sha1_object_info(sha1, &size); | 114 | type = sha1_object_info(sha1, &size); |
91 | if (type == OBJ_BAD) { | 115 | if (type == OBJ_BAD) { |
92 | type = sha1_object_info(sha2, &size); | 116 | type = sha1_object_info(sha2, &size); |
93 | if (type == OBJ_BAD) { | 117 | if (type == OBJ_BAD) { |
94 | cgit_print_error(fmt("Bad object names: %s, %s", old_hex, new_hex)); | 118 | cgit_print_error(fmt("Bad object names: %s, %s", old_hex, new_hex)); |
95 | return; | 119 | return; |
96 | } | 120 | } |
97 | } | 121 | } |
98 | 122 | ||
99 | html("<table class='diff'>"); | 123 | html("<table class='diff'>"); |
100 | switch(type) { | 124 | switch(type) { |
101 | case OBJ_BLOB: | 125 | case OBJ_BLOB: |
102 | html("<tr><td>"); | 126 | html("<tr><td>"); |
103 | header(sha1, path, sha2, path); | 127 | header(sha1, path, 0644, sha2, path, 0644); |
104 | if (cgit_diff_files(sha1, sha2, print_line)) | 128 | if (cgit_diff_files(sha1, sha2, print_line)) |
105 | cgit_print_error("Error running diff"); | 129 | cgit_print_error("Error running diff"); |
106 | html("</tr></td>"); | 130 | html("</tr></td>"); |
107 | break; | 131 | break; |
108 | case OBJ_TREE: | 132 | case OBJ_TREE: |
109 | cgit_diff_tree(sha1, sha2, filepair_cb); | 133 | cgit_diff_tree(sha1, sha2, filepair_cb); |
110 | break; | 134 | break; |
111 | default: | 135 | default: |
112 | cgit_print_error(fmt("Unhandled object type: %s", | 136 | cgit_print_error(fmt("Unhandled object type: %s", |
113 | typename(type))); | 137 | typename(type))); |
114 | break; | 138 | break; |
115 | } | 139 | } |
116 | html("</td></tr></table>"); | 140 | html("</td></tr></table>"); |
117 | } | 141 | } |