X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=diff-tree.c;h=9d94e0cc58be314017d570f75fc3169197f46a9e;hb=dc26bd890d0a8571c38397e2ab33c0f3963c01a7;hp=acd15243435742fdeb3bbdc29c1ff7ffa27cbb2f;hpb=73848892adeaa421825672bce929b9cc16043fa9;p=git.git diff --git a/diff-tree.c b/diff-tree.c index acd15243..9d94e0cc 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -3,12 +3,14 @@ #include "diff.h" static int silent = 0; +static int show_root_diff = 0; static int verbose_header = 0; static int ignore_merges = 1; static int recursive = 0; static int read_stdin = 0; static int line_termination = '\n'; static int generate_patch = 0; +static int detect_rename = 0; static const char *header = NULL; static const char *header_prefix = ""; @@ -54,15 +56,7 @@ static char *malloc_base(const char *base, const char *path, int pathlen) } static void show_file(const char *prefix, void *tree, unsigned long size, const char *base); - -/* A whole sub-tree went away or appeared */ -static void show_tree(const char *prefix, void *tree, unsigned long size, const char *base) -{ - while (size) { - show_file(prefix, tree, size, base); - update_tree_entry(&tree, &size); - } -} +static void show_tree(const char *prefix, void *tree, unsigned long size, const char *base); /* A file entry went away or appeared */ static void show_file(const char *prefix, void *tree, unsigned long size, const char *base) @@ -209,6 +203,13 @@ static int interesting(void *tree, unsigned long size, const char *base) if (pathlen > matchlen) continue; + if (matchlen > pathlen) { + if (match[pathlen] != '/') + continue; + if (!S_ISDIR(mode)) + continue; + } + if (strncmp(path, match, pathlen)) continue; @@ -217,6 +218,16 @@ static int interesting(void *tree, unsigned long size, const char *base) return 0; /* No matches */ } +/* A whole sub-tree went away or appeared */ +static void show_tree(const char *prefix, void *tree, unsigned long size, const char *base) +{ + while (size) { + if (interesting(tree, size, base)) + show_file(prefix, tree, size, base); + update_tree_entry(&tree, &size); + } +} + static int diff_tree(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base) { while (size1 | size2) { @@ -249,7 +260,7 @@ static int diff_tree(void *tree1, unsigned long size1, void *tree2, unsigned lon update_tree_entry(&tree2, &size2); continue; } - die("diff-tree: internal error"); + die("git-diff-tree: internal error"); } return 0; } @@ -272,6 +283,36 @@ static int diff_tree_sha1(const unsigned char *old, const unsigned char *new, co return retval; } +static int diff_tree_sha1_top(const unsigned char *old, + const unsigned char *new, const char *base) +{ + int ret; + if (generate_patch) + diff_setup(detect_rename, 0, 0, 0, 0); + ret = diff_tree_sha1(old, new, base); + if (generate_patch) + diff_flush(); + return ret; +} + +static int diff_root_tree(const unsigned char *new, const char *base) +{ + int retval; + void *tree; + unsigned long size; + + if (generate_patch) + diff_setup(detect_rename, 0, 0, 0, 0); + tree = read_object_with_reference(new, "tree", &size, 0); + if (!tree) + die("unable to read root tree (%s)", sha1_to_hex(new)); + retval = diff_tree("", 0, tree, size, base); + free(tree); + if (generate_patch) + diff_flush(); + return retval; +} + static int get_one_line(const char *msg, unsigned long len) { int ret = 0; @@ -350,25 +391,31 @@ static int diff_tree_commit(const unsigned char *commit, const char *name) if (!buf) return -1; - /* More than one parent? */ - if (ignore_merges) { - if (!memcmp(buf + 46 + 48, "parent ", 7)) - return 0; - } - if (!name) { static char commit_name[60]; strcpy(commit_name, sha1_to_hex(commit)); name = commit_name; } + /* Root commit? */ + if (show_root_diff && memcmp(buf + 46, "parent ", 7)) { + header = generate_header(name, "root", buf, size); + diff_root_tree(commit, ""); + } + + /* More than one parent? */ + if (ignore_merges) { + if (!memcmp(buf + 46 + 48, "parent ", 7)) + return 0; + } + offset = 46; while (offset + 48 < size && !memcmp(buf + offset, "parent ", 7)) { unsigned char parent[20]; if (get_sha1_hex(buf + offset + 7, parent)) return -1; header = generate_header(name, sha1_to_hex(parent), buf, size); - diff_tree_sha1(parent, commit, ""); + diff_tree_sha1_top(parent, commit, ""); if (!header && verbose_header) header_prefix = "\ndiff-tree "; offset += 48; @@ -392,14 +439,14 @@ static int diff_tree_stdin(char *line) line[81] = 0; sprintf(this_header, "%s (from %s)\n", line, line+41); header = this_header; - return diff_tree_sha1(parent, commit, ""); + return diff_tree_sha1_top(parent, commit, ""); } line[40] = 0; return diff_tree_commit(commit, line); } static char *diff_tree_usage = -"diff-tree [-p] [-r] [-z] [--stdin] [-m] [-s] [-v] "; +"git-diff-tree [-p] [-r] [-z] [--stdin] [-M] [-m] [-s] [-v] "; int main(int argc, char **argv) { @@ -438,6 +485,10 @@ int main(int argc, char **argv) recursive = generate_patch = 1; continue; } + if (!strcmp(arg, "-M")) { + detect_rename = recursive = generate_patch = 1; + continue; + } if (!strcmp(arg, "-z")) { line_termination = '\0'; continue; @@ -459,6 +510,10 @@ int main(int argc, char **argv) read_stdin = 1; continue; } + if (!strcmp(arg, "--root")) { + show_root_diff = 1; + continue; + } usage(diff_tree_usage); } @@ -481,7 +536,7 @@ int main(int argc, char **argv) diff_tree_commit(sha1[0], NULL); break; case 2: - diff_tree_sha1(sha1[0], sha1[1], ""); + diff_tree_sha1_top(sha1[0], sha1[1], ""); break; }