Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Helper functions for tree diff generation |
| 3 | */ |
| 4 | #include "cache.h" |
| 5 | #include "diff.h" |
Peter Eriksen | 8e44025 | 2006-04-02 14:44:09 +0200 | [diff] [blame] | 6 | #include "tree.h" |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 7 | |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 8 | static char *malloc_base(const char *base, int baselen, const char *path, int pathlen) |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 9 | { |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 10 | char *newbase = xmalloc(baselen + pathlen + 2); |
| 11 | memcpy(newbase, base, baselen); |
| 12 | memcpy(newbase + baselen, path, pathlen); |
| 13 | memcpy(newbase + baselen + pathlen, "/", 2); |
| 14 | return newbase; |
| 15 | } |
| 16 | |
David Rientjes | cf995ed | 2006-08-14 13:39:27 -0700 | [diff] [blame] | 17 | static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 18 | const char *base, int baselen); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 19 | |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 20 | static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, int baselen, struct diff_options *opt) |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 21 | { |
| 22 | unsigned mode1, mode2; |
| 23 | const char *path1, *path2; |
| 24 | const unsigned char *sha1, *sha2; |
| 25 | int cmp, pathlen1, pathlen2; |
| 26 | |
Linus Torvalds | 50f9a85 | 2006-01-31 14:10:56 -0800 | [diff] [blame] | 27 | sha1 = tree_entry_extract(t1, &path1, &mode1); |
| 28 | sha2 = tree_entry_extract(t2, &path2, &mode2); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 29 | |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 30 | pathlen1 = tree_entry_len(path1, sha1); |
| 31 | pathlen2 = tree_entry_len(path2, sha2); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 32 | cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2); |
| 33 | if (cmp < 0) { |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 34 | show_entry(opt, "-", t1, base, baselen); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 35 | return -1; |
| 36 | } |
| 37 | if (cmp > 0) { |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 38 | show_entry(opt, "+", t2, base, baselen); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 39 | return 1; |
| 40 | } |
David Rientjes | a89fccd | 2006-08-17 11:54:57 -0700 | [diff] [blame] | 41 | if (!opt->find_copies_harder && !hashcmp(sha1, sha2) && mode1 == mode2) |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 42 | return 0; |
| 43 | |
| 44 | /* |
| 45 | * If the filemode has changed to/from a directory from/to a regular |
| 46 | * file, we need to consider it a remove and an add. |
| 47 | */ |
| 48 | if (S_ISDIR(mode1) != S_ISDIR(mode2)) { |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 49 | show_entry(opt, "-", t1, base, baselen); |
| 50 | show_entry(opt, "+", t2, base, baselen); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 51 | return 0; |
| 52 | } |
| 53 | |
| 54 | if (opt->recursive && S_ISDIR(mode1)) { |
| 55 | int retval; |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 56 | char *newbase = malloc_base(base, baselen, path1, pathlen1); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 57 | if (opt->tree_in_recursive) |
| 58 | opt->change(opt, mode1, mode2, |
| 59 | sha1, sha2, base, path1); |
| 60 | retval = diff_tree_sha1(sha1, sha2, newbase, opt); |
| 61 | free(newbase); |
| 62 | return retval; |
| 63 | } |
| 64 | |
| 65 | opt->change(opt, mode1, mode2, sha1, sha2, base, path1); |
| 66 | return 0; |
| 67 | } |
| 68 | |
Linus Torvalds | 5d86501 | 2007-03-18 15:18:30 -0700 | [diff] [blame] | 69 | /* |
| 70 | * Is a tree entry interesting given the pathspec we have? |
| 71 | * |
| 72 | * Return: |
| 73 | * - positive for yes |
| 74 | * - zero for no |
| 75 | * - negative for "no, and no subsequent entries will be either" |
| 76 | */ |
| 77 | static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt) |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 78 | { |
| 79 | const char *path; |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 80 | const unsigned char *sha1; |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 81 | unsigned mode; |
| 82 | int i; |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 83 | int pathlen; |
Junio C Hamano | 7d2f667 | 2007-03-21 09:51:47 -0700 | [diff] [blame] | 84 | int never_interesting = -1; |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 85 | |
Junio C Hamano | a8baa7b | 2006-04-10 16:39:11 -0700 | [diff] [blame] | 86 | if (!opt->nr_paths) |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 87 | return 1; |
| 88 | |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 89 | sha1 = tree_entry_extract(desc, &path, &mode); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 90 | |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 91 | pathlen = tree_entry_len(path, sha1); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 92 | |
Junio C Hamano | 7d2f667 | 2007-03-21 09:51:47 -0700 | [diff] [blame] | 93 | for (i = 0; i < opt->nr_paths; i++) { |
Junio C Hamano | a8baa7b | 2006-04-10 16:39:11 -0700 | [diff] [blame] | 94 | const char *match = opt->paths[i]; |
| 95 | int matchlen = opt->pathlens[i]; |
Junio C Hamano | ccc744a | 2007-03-21 12:34:46 -0700 | [diff] [blame^] | 96 | int m = -1; /* signals that we haven't called strncmp() */ |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 97 | |
| 98 | if (baselen >= matchlen) { |
| 99 | /* If it doesn't match, move along... */ |
| 100 | if (strncmp(base, match, matchlen)) |
| 101 | continue; |
| 102 | |
| 103 | /* The base is a subdirectory of a path which was specified. */ |
| 104 | return 1; |
| 105 | } |
| 106 | |
| 107 | /* Does the base match? */ |
| 108 | if (strncmp(base, match, baselen)) |
| 109 | continue; |
| 110 | |
| 111 | match += baselen; |
| 112 | matchlen -= baselen; |
| 113 | |
Junio C Hamano | ccc744a | 2007-03-21 12:34:46 -0700 | [diff] [blame^] | 114 | if (never_interesting) { |
| 115 | /* |
| 116 | * We have not seen any match that sorts later |
| 117 | * than the current path. |
| 118 | */ |
Junio C Hamano | 7d2f667 | 2007-03-21 09:51:47 -0700 | [diff] [blame] | 119 | |
Junio C Hamano | ccc744a | 2007-03-21 12:34:46 -0700 | [diff] [blame^] | 120 | /* |
| 121 | * Does match sort strictly earlier than path |
| 122 | * with their common parts? |
| 123 | */ |
| 124 | m = strncmp(match, path, |
| 125 | (matchlen < pathlen) ? matchlen : pathlen); |
| 126 | if (m < 0) |
| 127 | continue; |
| 128 | |
| 129 | /* |
| 130 | * If we come here even once, that means there is at |
| 131 | * least one pathspec that would sort equal to or |
| 132 | * later than the path we are currently looking at. |
| 133 | * In other words, if we have never reached this point |
| 134 | * after iterating all pathspecs, it means all |
| 135 | * pathspecs are either outside of base, or inside the |
| 136 | * base but sorts strictly earlier than the current |
| 137 | * one. In either case, they will never match the |
| 138 | * subsequent entries. In such a case, we initialized |
| 139 | * the variable to -1 and that is what will be |
| 140 | * returned, allowing the caller to terminate early. |
| 141 | */ |
| 142 | never_interesting = 0; |
| 143 | } |
Junio C Hamano | 7d2f667 | 2007-03-21 09:51:47 -0700 | [diff] [blame] | 144 | |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 145 | if (pathlen > matchlen) |
| 146 | continue; |
| 147 | |
| 148 | if (matchlen > pathlen) { |
| 149 | if (match[pathlen] != '/') |
| 150 | continue; |
| 151 | if (!S_ISDIR(mode)) |
| 152 | continue; |
| 153 | } |
| 154 | |
Junio C Hamano | ccc744a | 2007-03-21 12:34:46 -0700 | [diff] [blame^] | 155 | if (m == -1) |
| 156 | /* |
| 157 | * we cheated and did not do strncmp(), so we do |
| 158 | * that here. |
| 159 | */ |
| 160 | m = strncmp(match, path, pathlen); |
| 161 | |
Junio C Hamano | 7d2f667 | 2007-03-21 09:51:47 -0700 | [diff] [blame] | 162 | /* |
| 163 | * If common part matched earlier then it is a hit, |
| 164 | * because we rejected the case where path is not a |
| 165 | * leading directory and is shorter than match. |
| 166 | */ |
| 167 | if (!m) |
| 168 | return 1; |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 169 | } |
Junio C Hamano | 7d2f667 | 2007-03-21 09:51:47 -0700 | [diff] [blame] | 170 | return never_interesting; /* No matches */ |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 171 | } |
| 172 | |
| 173 | /* A whole sub-tree went away or appeared */ |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 174 | static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen) |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 175 | { |
| 176 | while (desc->size) { |
Linus Torvalds | 5d86501 | 2007-03-18 15:18:30 -0700 | [diff] [blame] | 177 | int show = tree_entry_interesting(desc, base, baselen, opt); |
| 178 | if (show < 0) |
| 179 | break; |
| 180 | if (show) |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 181 | show_entry(opt, prefix, desc, base, baselen); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 182 | update_tree_entry(desc); |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | /* A file entry went away or appeared */ |
David Rientjes | cf995ed | 2006-08-14 13:39:27 -0700 | [diff] [blame] | 187 | static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 188 | const char *base, int baselen) |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 189 | { |
| 190 | unsigned mode; |
| 191 | const char *path; |
Linus Torvalds | 50f9a85 | 2006-01-31 14:10:56 -0800 | [diff] [blame] | 192 | const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 193 | |
| 194 | if (opt->recursive && S_ISDIR(mode)) { |
Nicolas Pitre | 21666f1 | 2007-02-26 14:55:59 -0500 | [diff] [blame] | 195 | enum object_type type; |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 196 | int pathlen = tree_entry_len(path, sha1); |
| 197 | char *newbase = malloc_base(base, baselen, path, pathlen); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 198 | struct tree_desc inner; |
| 199 | void *tree; |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 200 | unsigned long size; |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 201 | |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 202 | tree = read_sha1_file(sha1, &type, &size); |
Nicolas Pitre | 21666f1 | 2007-02-26 14:55:59 -0500 | [diff] [blame] | 203 | if (!tree || type != OBJ_TREE) |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 204 | die("corrupt tree sha %s", sha1_to_hex(sha1)); |
| 205 | |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 206 | init_tree_desc(&inner, tree, size); |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 207 | show_tree(opt, prefix, &inner, newbase, baselen + 1 + pathlen); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 208 | |
| 209 | free(tree); |
| 210 | free(newbase); |
David Rientjes | cf995ed | 2006-08-14 13:39:27 -0700 | [diff] [blame] | 211 | } else { |
| 212 | opt->add_remove(opt, prefix[0], mode, sha1, base, path); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 213 | } |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 214 | } |
| 215 | |
Linus Torvalds | 5d86501 | 2007-03-18 15:18:30 -0700 | [diff] [blame] | 216 | static void skip_uninteresting(struct tree_desc *t, const char *base, int baselen, struct diff_options *opt) |
| 217 | { |
| 218 | while (t->size) { |
| 219 | int show = tree_entry_interesting(t, base, baselen, opt); |
| 220 | if (!show) { |
| 221 | update_tree_entry(t); |
| 222 | continue; |
| 223 | } |
| 224 | /* Skip it all? */ |
| 225 | if (show < 0) |
| 226 | t->size = 0; |
| 227 | return; |
| 228 | } |
| 229 | } |
| 230 | |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 231 | int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt) |
| 232 | { |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 233 | int baselen = strlen(base); |
| 234 | |
Linus Torvalds | 5d86501 | 2007-03-18 15:18:30 -0700 | [diff] [blame] | 235 | for (;;) { |
Junio C Hamano | 822cac0 | 2007-03-14 11:12:51 -0700 | [diff] [blame] | 236 | if (opt->quiet && opt->has_changes) |
| 237 | break; |
Linus Torvalds | 5d86501 | 2007-03-18 15:18:30 -0700 | [diff] [blame] | 238 | if (opt->nr_paths) { |
| 239 | skip_uninteresting(t1, base, baselen, opt); |
| 240 | skip_uninteresting(t2, base, baselen, opt); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 241 | } |
| 242 | if (!t1->size) { |
Linus Torvalds | 5d86501 | 2007-03-18 15:18:30 -0700 | [diff] [blame] | 243 | if (!t2->size) |
| 244 | break; |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 245 | show_entry(opt, "+", t2, base, baselen); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 246 | update_tree_entry(t2); |
| 247 | continue; |
| 248 | } |
| 249 | if (!t2->size) { |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 250 | show_entry(opt, "-", t1, base, baselen); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 251 | update_tree_entry(t1); |
| 252 | continue; |
| 253 | } |
Linus Torvalds | 304de2d | 2007-03-17 20:06:24 -0700 | [diff] [blame] | 254 | switch (compare_tree_entry(t1, t2, base, baselen, opt)) { |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 255 | case -1: |
| 256 | update_tree_entry(t1); |
| 257 | continue; |
| 258 | case 0: |
| 259 | update_tree_entry(t1); |
| 260 | /* Fallthrough */ |
| 261 | case 1: |
| 262 | update_tree_entry(t2); |
| 263 | continue; |
| 264 | } |
| 265 | die("git-diff-tree: internal error"); |
| 266 | } |
| 267 | return 0; |
| 268 | } |
| 269 | |
| 270 | int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt) |
| 271 | { |
| 272 | void *tree1, *tree2; |
| 273 | struct tree_desc t1, t2; |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 274 | unsigned long size1, size2; |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 275 | int retval; |
| 276 | |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 277 | tree1 = read_object_with_reference(old, tree_type, &size1, NULL); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 278 | if (!tree1) |
| 279 | die("unable to read source tree (%s)", sha1_to_hex(old)); |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 280 | tree2 = read_object_with_reference(new, tree_type, &size2, NULL); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 281 | if (!tree2) |
| 282 | die("unable to read destination tree (%s)", sha1_to_hex(new)); |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 283 | init_tree_desc(&t1, tree1, size1); |
| 284 | init_tree_desc(&t2, tree2, size2); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 285 | retval = diff_tree(&t1, &t2, base, opt); |
| 286 | free(tree1); |
| 287 | free(tree2); |
| 288 | return retval; |
| 289 | } |
| 290 | |
Rene Scharfe | 2b60356 | 2006-10-26 18:52:39 +0200 | [diff] [blame] | 291 | int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt) |
| 292 | { |
| 293 | int retval; |
| 294 | void *tree; |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 295 | unsigned long size; |
Rene Scharfe | 2b60356 | 2006-10-26 18:52:39 +0200 | [diff] [blame] | 296 | struct tree_desc empty, real; |
| 297 | |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 298 | tree = read_object_with_reference(new, tree_type, &size, NULL); |
Rene Scharfe | 2b60356 | 2006-10-26 18:52:39 +0200 | [diff] [blame] | 299 | if (!tree) |
| 300 | die("unable to read root tree (%s)", sha1_to_hex(new)); |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 301 | init_tree_desc(&real, tree, size); |
Rene Scharfe | 2b60356 | 2006-10-26 18:52:39 +0200 | [diff] [blame] | 302 | |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 303 | init_tree_desc(&empty, "", 0); |
Rene Scharfe | 2b60356 | 2006-10-26 18:52:39 +0200 | [diff] [blame] | 304 | retval = diff_tree(&empty, &real, base, opt); |
| 305 | free(tree); |
| 306 | return retval; |
| 307 | } |
| 308 | |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 309 | static int count_paths(const char **paths) |
| 310 | { |
| 311 | int i = 0; |
| 312 | while (*paths++) |
| 313 | i++; |
| 314 | return i; |
| 315 | } |
| 316 | |
Junio C Hamano | a8baa7b | 2006-04-10 16:39:11 -0700 | [diff] [blame] | 317 | void diff_tree_release_paths(struct diff_options *opt) |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 318 | { |
Junio C Hamano | a8baa7b | 2006-04-10 16:39:11 -0700 | [diff] [blame] | 319 | free(opt->pathlens); |
| 320 | } |
| 321 | |
| 322 | void diff_tree_setup_paths(const char **p, struct diff_options *opt) |
| 323 | { |
| 324 | opt->nr_paths = 0; |
| 325 | opt->pathlens = NULL; |
| 326 | opt->paths = NULL; |
| 327 | |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 328 | if (p) { |
| 329 | int i; |
| 330 | |
Junio C Hamano | a8baa7b | 2006-04-10 16:39:11 -0700 | [diff] [blame] | 331 | opt->paths = p; |
| 332 | opt->nr_paths = count_paths(p); |
| 333 | if (opt->nr_paths == 0) { |
| 334 | opt->pathlens = NULL; |
Junio C Hamano | 7e4a2a8 | 2005-12-26 12:34:56 -0800 | [diff] [blame] | 335 | return; |
| 336 | } |
Junio C Hamano | a8baa7b | 2006-04-10 16:39:11 -0700 | [diff] [blame] | 337 | opt->pathlens = xmalloc(opt->nr_paths * sizeof(int)); |
| 338 | for (i=0; i < opt->nr_paths; i++) |
| 339 | opt->pathlens[i] = strlen(p[i]); |
Linus Torvalds | ac1b3d1 | 2005-10-20 21:05:05 -0700 | [diff] [blame] | 340 | } |
| 341 | } |