Merge lt/revlist,jc/diff,jc/revparse,jc/abbrev
authorJunio C Hamano <junkio@cox.net>
Sat, 28 Jan 2006 08:16:09 +0000 (00:16 -0800)
committerJunio C Hamano <junkio@cox.net>
Sat, 28 Jan 2006 08:16:09 +0000 (00:16 -0800)
1  2  3  4  5 
diff-tree.c
diff.h
rev-list.c
rev-parse.c
diff --combined diff-tree.c
index efa2b9476eae679b7f98a4605b07b6637e49de5a,efa2b9476eae679b7f98a4605b07b6637e49de5a,99c580cf75ee15d6bbd65c588360309cc94e9dc4,efa2b9476eae679b7f98a4605b07b6637e49de5a,44bc2381c9cd4ab6e10e8bd8b519b564a1b9014b..6593a6920adcdb81fafad94ba2cf96431e6ceec9
@@@@@@ -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);
        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] "
     "[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\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 ";
        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 5696f2aff0644f331507679e0a58d7fcdc3501ec,5696f2aff0644f331507679e0a58d7fcdc3501ec,539bd2f5ce98b779885b9a3fdc2e838b5b293d6b,5696f2aff0644f331507679e0a58d7fcdc3501ec,122c8143a3b9274380f1a66785b3d7952e8609dd..9a0169c03ceb82b5cc2c246fa9f70e2f8399ec33
--- 1/diff.h
--- 2/diff.h
--- 3/diff.h
--- 4/diff.h
--- 5/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 e00e6fc76df8236c925e904fa270a2293099d6cf,5bc38fea6607feb14e2f36a839a921ce44df8f53,e00e6fc76df8236c925e904fa270a2293099d6cf,e00e6fc76df8236c925e904fa270a2293099d6cf,334713ab66371c7ad239b28eec321d016352e943..0b142c1a6f79bf12901da71ca4e336cc32488171
@@@@@@ -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)
     {
     
        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,
                 const unsigned char *new_sha1,
                 const char *base, const char *path)
     {
- ---   is_different = 1;
+ +++   tree_difference = TREE_DIFFERENT;
     }
     
     static struct diff_options diff_opt = {
        .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)
        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)
        }
     
        /*
- ---    * 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;
     
        }
     }
     
- ---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;
        }
        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 7abad35de90b190c5d5e5456661853cf8167954a,7abad35de90b190c5d5e5456661853cf8167954a,7abad35de90b190c5d5e5456661853cf8167954a,9567b0f5b919c76700ea9899ba807425953bf87c,a1aa86398a62559b8d04cde2a542edaee7290cf1..d2f086432b0b709c9c8c5f2b8c6c15a9ddb59e29
@@@@@@ -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;
                }
                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);