From: Junio C Hamano Date: Sat, 28 Jan 2006 08:16:09 +0000 (-0800) Subject: Merge lt/revlist,jc/diff,jc/revparse,jc/abbrev X-Git-Tag: v1.2.0~100 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/addafaf92eeb86033da91323d0d3ad7a496dae83?ds=inline;hp=-c Merge lt/revlist,jc/diff,jc/revparse,jc/abbrev --- addafaf92eeb86033da91323d0d3ad7a496dae83 diff --combined diff-tree.c index efa2b9476e,efa2b9476e,99c580cf75,efa2b9476e,44bc2381c9..6593a6920a --- a/diff-tree.c +++ b/diff-tree.c @@@@@@ -6,6 -6,6 -6,9 -6,6 -6,6 +6,9 @@@@@@ static int show_root_diff = 0 static int no_commit_id = 0; static int verbose_header = 0; static int ignore_merges = 1; ++ ++static int show_empty_combined = 0; ++ ++static int combine_merges = 0; ++ ++static int dense_combined_merges = 0; static int read_stdin = 0; static const char *header = NULL; @@@@@@ -64,12 -64,12 -67,12 -64,12 -64,13 +67,13 @@@@@@ static int diff_root_tree(const unsigne static const char *generate_header(const unsigned char *commit_sha1, const unsigned char *parent_sha1, ---- const char *msg) ++++ const struct commit *commit) { static char this_header[16384]; int offset; unsigned long len; int abbrev = diff_options.abbrev; ++++ const char *msg = commit->buffer; if (!verbose_header) return sha1_to_hex(commit_sha1); @@@@@@ -79,12 -79,12 -82,16 -79,12 -80,12 +83,16 @@@@@@ offset = sprintf(this_header, "%s%s ", header_prefix, diff_unique_abbrev(commit_sha1, abbrev)); -- -- offset += sprintf(this_header + offset, "(from %s)\n", -- -- parent_sha1 ? -- -- diff_unique_abbrev(parent_sha1, abbrev) : "root"); -- - offset += pretty_print_commit(commit_format, msg, len, ++ ++ if (commit_sha1 != parent_sha1) ++ ++ offset += sprintf(this_header + offset, "(from %s)\n", ++ ++ parent_sha1 ++ ++ ? diff_unique_abbrev(parent_sha1, abbrev) ++ ++ : "root"); ++ ++ else ++ ++ offset += sprintf(this_header + offset, "(from parents)\n"); - offset += pretty_print_commit(commit_format, msg, len, ++++ offset += pretty_print_commit(commit_format, commit, len, this_header + offset, ---- sizeof(this_header) - offset); ++++ sizeof(this_header) - offset, abbrev); return this_header; } @@@@@@ -103,19 -103,19 -110,28 -103,19 -104,17 +111,25 @@@@@@ static int diff_tree_commit(const unsig /* Root commit? */ if (show_root_diff && !commit->parents) { ---- header = generate_header(sha1, NULL, commit->buffer); ++++ header = generate_header(sha1, NULL, commit); diff_root_tree(commit_sha1, ""); } /* More than one parent? */ -- -- if (ignore_merges && commit->parents && commit->parents->next) -- -- return 0; ++ ++ if (commit->parents && commit->parents->next) { ++ ++ if (ignore_merges) ++ ++ return 0; ++ ++ else if (combine_merges) { - header = generate_header(sha1, sha1, - commit->buffer); +++++ header = generate_header(sha1, sha1, commit); ++ ++ return diff_tree_combined_merge(sha1, header, ++ ++ show_empty_combined, ++ ++ dense_combined_merges); ++ ++ } ++ ++ } for (parents = commit->parents; parents; parents = parents->next) { struct commit *parent = parents->item; ---- header = generate_header(sha1, ---- parent->object.sha1, ---- commit->buffer); ++++ header = generate_header(sha1, parent->object.sha1, commit); diff_tree_sha1_top(parent->object.sha1, commit_sha1, ""); if (!header && verbose_header) { header_prefix = "\ndiff-tree "; @@@@@@ -154,7 -154,7 -170,7 -154,7 -153,7 +168,7 @@@@@@ static int diff_tree_stdin(char *line } static const char diff_tree_usage[] = -- --"git-diff-tree [--stdin] [-m] [-s] [-v] [--pretty] [-t] [-r] [--root] " ++ ++"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] " "[] [] [...]\n" " -r diff recursively\n" " --root include the initial commit as diff against /dev/null\n" @@@@@@ -217,6 -217,6 -233,14 -217,6 -216,6 +231,14 @@@@@@ int main(int argc, const char **argv ignore_merges = 0; continue; } ++ ++ if (!strcmp(arg, "-c")) { ++ ++ combine_merges = 1; ++ ++ continue; ++ ++ } ++ ++ if (!strcmp(arg, "--cc")) { ++ ++ dense_combined_merges = combine_merges = 1; ++ ++ continue; ++ ++ } if (!strcmp(arg, "-v")) { verbose_header = 1; header_prefix = "diff-tree "; @@@@@@ -245,6 -245,6 -269,12 -245,6 -244,6 +267,12 @@@@@@ if (diff_options.output_format == DIFF_FORMAT_PATCH) diff_options.recursive = 1; ++ ++ if (combine_merges) { ++ ++ diff_options.output_format = DIFF_FORMAT_PATCH; ++ ++ show_empty_combined = !ignore_merges; ++ ++ ignore_merges = 0; ++ ++ } ++ ++ diff_tree_setup_paths(get_pathspec(prefix, argv)); diff_setup_done(&diff_options); diff --combined diff.h index 5696f2aff0,5696f2aff0,539bd2f5ce,5696f2aff0,122c8143a3..9a0169c03c --- a/diff.h +++ b/diff.h @@@@@@ -56,6 -56,6 -56,19 -56,6 -56,6 +56,19 @@@@@@ extern int diff_tree(struct tree_desc * extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt); ++ ++struct combine_diff_path { ++ ++ struct combine_diff_path *next; ++ ++ int len; ++ ++ char *path; ++ ++ unsigned char sha1[20]; ++ ++ unsigned char parent_sha1[FLEX_ARRAY][20]; ++ ++}; ++ ++ ++ ++int show_combined_diff(struct combine_diff_path *elem, int num_parent, ++ ++ int dense, const char *header, int show_empty); ++ ++ ++ ++extern int diff_tree_combined_merge(const unsigned char *sha1, const char *, int, int); ++ ++ extern void diff_addremove(struct diff_options *, int addremove, unsigned mode, @@@@@@ -88,9 -88,9 -101,9 -88,9 -88,6 +101,6 @@@@@@ extern int diff_setup_done(struct diff_ #define DIFF_PICKAXE_ALL 1 ---- #define DIFF_DEFAULT_INDEX_ABBREV 7 /* hex digits */ ---- #define DIFF_DEFAULT_ABBREV 7 /* hex digits */ ---- extern void diffcore_std(struct diff_options *); extern void diffcore_std_no_resolve(struct diff_options *); diff --combined rev-list.c index e00e6fc76d,5bc38fea66,e00e6fc76d,e00e6fc76d,334713ab66..0b142c1a6f --- a/rev-list.c +++ b/rev-list.c @@@@@@ -21,6 -21,7 -21,6 -21,6 -21,6 +21,7 @@@@@@ static const char rev_list_usage[] " --min-age=epoch\n" " --sparse\n" " --no-merges\n" + +++" --remove-empty\n" " --all\n" " ordering output:\n" " --merge-order [ --show-breaks ]\n" @@@@@@ -54,6 -55,7 -54,6 -54,6 -54,6 +55,7 @@@@@@ static int stop_traversal = 0 static int topo_order = 0; static int no_merges = 0; static const char **paths = NULL; + +++static int remove_empty_trees = 0; static void show_commit(struct commit *commit) { @@@@@@ -81,7 -83,7 -81,7 -81,7 -81,7 +83,7 @@@@@@ if (verbose_header) { static char pretty_header[16384]; ---- pretty_print_commit(commit_format, commit->buffer, ~0, pretty_header, sizeof(pretty_header)); ++++ pretty_print_commit(commit_format, commit, ~0, pretty_header, sizeof(pretty_header), 0); printf("%s%c", pretty_header, hdr_termination); } fflush(stdout); @@@@@@ -424,14 -426,33 -424,14 -424,14 -424,14 +426,33 @@@@@@ static void mark_edges_uninteresting(st } } - ---static int is_different = 0; + +++#define TREE_SAME 0 + +++#define TREE_NEW 1 + +++#define TREE_DIFFERENT 2 + +++static int tree_difference = TREE_SAME; static void file_add_remove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, const char *base, const char *path) { - --- is_different = 1; + +++ int diff = TREE_DIFFERENT; + +++ + +++ /* + +++ * Is it an add of a new file? It means that + +++ * the old tree didn't have it at all, so we + +++ * will turn "TREE_SAME" -> "TREE_NEW", but + +++ * leave any "TREE_DIFFERENT" alone (and if + +++ * it already was "TREE_NEW", we'll keep it + +++ * "TREE_NEW" of course). + +++ */ + +++ if (addremove == '+') { + +++ diff = tree_difference; + +++ if (diff != TREE_SAME) + +++ return; + +++ diff = TREE_NEW; + +++ } + +++ tree_difference = diff; } static void file_change(struct diff_options *options, @@@@@@ -440,7 -461,7 -440,7 -440,7 -440,7 +461,7 @@@@@@ const unsigned char *new_sha1, const char *base, const char *path) { - --- is_different = 1; + +++ tree_difference = TREE_DIFFERENT; } static struct diff_options diff_opt = { @@@@@@ -449,12 -470,16 -449,12 -449,12 -449,12 +470,16 @@@@@@ .change = file_change, }; - ---static int same_tree(struct tree *t1, struct tree *t2) + +++static int compare_tree(struct tree *t1, struct tree *t2) { - --- is_different = 0; + +++ if (!t1) + +++ return TREE_NEW; + +++ if (!t2) + +++ return TREE_DIFFERENT; + +++ tree_difference = TREE_SAME; if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "", &diff_opt) < 0) - --- return 0; - --- return !is_different; + +++ return TREE_DIFFERENT; + +++ return tree_difference; } static int same_tree_as_empty(struct tree *t1) @@@@@@ -474,28 -499,55 -474,28 -474,28 -474,28 +499,55 @@@@@@ empty.buf = ""; empty.size = 0; - --- is_different = 0; + +++ tree_difference = 0; retval = diff_tree(&empty, &real, "", &diff_opt); free(tree); - --- return retval >= 0 && !is_different; + +++ return retval >= 0 && !tree_difference; } - ---static struct commit *try_to_simplify_merge(struct commit *commit, struct commit_list *parent) + +++static void try_to_simplify_commit(struct commit *commit) { + +++ struct commit_list **pp, *parent; + +++ if (!commit->tree) - --- return NULL; + +++ return; - --- while (parent) { + +++ if (!commit->parents) { + +++ if (!same_tree_as_empty(commit->tree)) + +++ commit->object.flags |= TREECHANGE; + +++ return; + +++ } + +++ + +++ pp = &commit->parents; + +++ while ((parent = *pp) != NULL) { struct commit *p = parent->item; - --- parent = parent->next; + +++ + +++ if (p->object.flags & UNINTERESTING) { + +++ pp = &parent->next; + +++ continue; + +++ } + +++ parse_commit(p); - --- if (!p->tree) + +++ switch (compare_tree(p->tree, commit->tree)) { + +++ case TREE_SAME: + +++ parent->next = NULL; + +++ commit->parents = parent; + +++ return; + +++ + +++ case TREE_NEW: + +++ if (remove_empty_trees && same_tree_as_empty(p->tree)) { + +++ *pp = parent->next; + +++ continue; + +++ } + +++ /* fallthrough */ + +++ case TREE_DIFFERENT: + +++ pp = &parent->next; continue; - --- if (same_tree(commit->tree, p->tree)) - --- return p; + +++ } + +++ die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1)); } - --- return NULL; + +++ commit->object.flags |= TREECHANGE; } static void add_parents_to_list(struct commit *commit, struct commit_list **list) @@@@@@ -531,20 -583,14 -531,20 -531,20 -531,20 +583,14 @@@@@@ } /* - --- * Ok, the commit wasn't uninteresting. If it - --- * is a merge, try to find the parent that has - --- * no differences in the path set if one exists. + +++ * Ok, the commit wasn't uninteresting. Try to + +++ * simplify the commit history and find the parent + +++ * that has no differences in the path set if one exists. */ - --- if (paths && parent && parent->next) { - --- struct commit *preferred; - --- - --- preferred = try_to_simplify_merge(commit, parent); - --- if (preferred) { - --- parent->item = preferred; - --- parent->next = NULL; - --- } - --- } + +++ if (paths) + +++ try_to_simplify_commit(commit); + +++ parent = commit->parents; while (parent) { struct commit *p = parent->item; @@@@@@ -558,33 -604,6 -558,33 -558,33 -558,33 +604,6 @@@@@@ } } - ---static void compress_list(struct commit_list *list) - ---{ - --- while (list) { - --- struct commit *commit = list->item; - --- struct commit_list *parent = commit->parents; - --- list = list->next; - --- - --- if (!parent) { - --- if (!same_tree_as_empty(commit->tree)) - --- commit->object.flags |= TREECHANGE; - --- continue; - --- } - --- - --- /* - --- * Exactly one parent? Check if it leaves the tree - --- * unchanged - --- */ - --- if (!parent->next) { - --- struct tree *t1 = commit->tree; - --- struct tree *t2 = parent->item->tree; - --- if (!t1 || !t2 || same_tree(t1, t2)) - --- continue; - --- } - --- commit->object.flags |= TREECHANGE; - --- } - ---} - --- static struct commit_list *limit_list(struct commit_list *list) { struct commit_list *newlist = NULL; @@@@@@ -614,8 -633,6 -614,8 -614,8 -614,8 +633,6 @@@@@@ } if (tree_objects) mark_edges_uninteresting(newlist); - --- if (paths && dense) - --- compress_list(newlist); if (bisect_list) newlist = find_bisection(newlist); return newlist; @@@@@@ -808,6 -825,10 -808,6 -808,6 -808,6 +825,10 @@@@@@ int main(int argc, const char **argv dense = 0; continue; } + +++ if (!strcmp(arg, "--remove-empty")) { + +++ remove_empty_trees = 1; + +++ continue; + +++ } if (!strcmp(arg, "--")) { i++; break; diff --combined rev-parse.c index 7abad35de9,7abad35de9,7abad35de9,9567b0f5b9,a1aa86398a..d2f086432b --- a/rev-parse.c +++ b/rev-parse.c @@@@@@ -20,6 -20,6 -20,6 -20,6 -20,7 +20,7 @@@@@@ static char *def = NULL #define REVERSED 1 static int show_type = NORMAL; static int symbolic = 0; ++++ static int abbrev = 0; static int output_sq = 0; static int revs_count = 0; @@@@@@ -95,6 -95,6 -95,6 -95,6 -96,8 +96,8 @@@@@@ static void show_rev(int type, const un putchar('^'); if (symbolic && name) show(name); ++++ else if (abbrev) ++++ show(find_unique_abbrev(sha1, abbrev)); else show(sha1_to_hex(sha1)); } @@@@@@ -196,6 -196,6 -196,6 -196,6 -199,19 +199,19 @@@@@@ int main(int argc, char **argv verify = 1; continue; } ++++ if (!strcmp(arg, "--short") || ++++ !strncmp(arg, "--short=", 9)) { ++++ filter &= ~(DO_FLAGS|DO_NOREV); ++++ verify = 1; ++++ abbrev = DEFAULT_ABBREV; ++++ if (arg[8] == '=') ++++ abbrev = strtoul(arg + 9, NULL, 10); ++++ if (abbrev < MINIMUM_ABBREV) ++++ abbrev = MINIMUM_ABBREV; ++++ else if (40 <= abbrev) ++++ abbrev = 40; ++++ continue; ++++ } if (!strcmp(arg, "--sq")) { output_sq = 1; continue; @@@@@@ -294,7 -294,7 -294,7 -294,9 -310,7 +310,9 @@@@@@ } if (verify) die("Needed a single revision"); --- - if (lstat(arg, &st) < 0) +++ + if ((filter & DO_REVS) && +++ + (filter & DO_NONFLAGS) && /* !def && */ +++ + lstat(arg, &st) < 0) die("'%s': %s", arg, strerror(errno)); as_is = 1; show_file(arg);