Merge branch 'jc/cherry'
authorJunio C Hamano <junkio@cox.net>
Fri, 13 Apr 2007 04:04:27 +0000 (21:04 -0700)
committerJunio C Hamano <junkio@cox.net>
Fri, 13 Apr 2007 04:04:27 +0000 (21:04 -0700)
* jc/cherry:
Documentation: --cherry-pick
git-log --cherry-pick A...B
Refactor patch-id filtering out of git-cherry and git-format-patch.
Add %m to '--pretty=format:'

1  2 
Makefile
builtin-log.c
revision.c
diff --combined Makefile
index d6c5d596b82d0af46539eb069d1633e19c64221d,f956c3d9ba0c4bc24eacb5193cc123e20325976c..b8e603094050377fb8ca2988c2558c76fe113e70
+++ b/Makefile
@@@ -283,7 -283,7 +283,7 @@@ LIB_H = 
        diff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.h \
        run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
        tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
-       utf8.h reflog-walk.h
+       utf8.h reflog-walk.h patch-ids.h
  
  DIFF_OBJS = \
        diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@@ -295,6 -295,7 +295,7 @@@ LIB_OBJS = 
        date.o diff-delta.o entry.o exec_cmd.o ident.o \
        interpolate.o \
        lockfile.o \
+       patch-ids.o \
        object.o pack-check.o patch-delta.o path.o pkt-line.o sideband.o \
        reachable.o reflog-walk.o \
        quote.o read-cache.o refs.o run-command.o dir.o object-refs.o \
@@@ -728,7 -729,7 +729,7 @@@ git$X: git.c common-cmds.h $(BUILTIN_OB
  help.o: common-cmds.h
  
  git-merge-subtree$X: git-merge-recursive$X
 -      rm -f $@ && ln git-merge-recursive$X $@
 +      $(QUIET_BUILT_IN)rm -f $@ && ln git-merge-recursive$X $@
  
  $(BUILT_INS): git$X
        $(QUIET_BUILT_IN)rm -f $@ && ln git$X $@
diff --combined builtin-log.c
index ffc269a1225b5ee51e75416a5d501a541342b46f,eea96901b9dc339aa2b60ba35c8ce6a5ee369125..469949457f61eee95f6ba801c4f81328a06cffda
@@@ -12,6 -12,7 +12,7 @@@
  #include "builtin.h"
  #include "tag.h"
  #include "reflog-walk.h"
+ #include "patch-ids.h"
  
  static int default_show_root = 1;
  
@@@ -333,25 -334,12 +334,12 @@@ static int reopen_stdout(struct commit 
  
  }
  
- static int get_patch_id(struct commit *commit, struct diff_options *options,
-               unsigned char *sha1)
- {
-       if (commit->parents)
-               diff_tree_sha1(commit->parents->item->object.sha1,
-                              commit->object.sha1, "", options);
-       else
-               diff_root_tree_sha1(commit->object.sha1, "", options);
-       diffcore_std(options);
-       return diff_flush_patch_id(options, sha1);
- }
- static void get_patch_ids(struct rev_info *rev, struct diff_options *options, const char *prefix)
+ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const char *prefix)
  {
        struct rev_info check_rev;
        struct commit *commit;
        struct object *o1, *o2;
        unsigned flags1, flags2;
-       unsigned char sha1[20];
  
        if (rev->pending.nr != 2)
                die("Need exactly one range.");
        if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
                die("Not a range.");
  
-       diff_setup(options);
-       options->recursive = 1;
-       if (diff_setup_done(options) < 0)
-               die("diff_setup_done failed");
+       init_patch_ids(ids);
  
        /* given a range a..b get all patch ids for b..a */
        init_revisions(&check_rev, prefix);
                if (commit->parents && commit->parents->next)
                        continue;
  
-               if (!get_patch_id(commit, options, sha1))
-                       created_object(sha1, xcalloc(1, sizeof(struct object)));
+               add_commit_patch_id(commit, ids);
        }
  
        /* reset for next revision walk */
@@@ -421,7 -405,7 +405,7 @@@ int cmd_format_patch(int argc, const ch
        int ignore_if_in_upstream = 0;
        int thread = 0;
        const char *in_reply_to = NULL;
-       struct diff_options patch_id_opts;
+       struct patch_ids ids;
        char *add_signoff = NULL;
        char message_id[1024];
        char ref_message_id[1024];
        rev.ignore_merges = 1;
        rev.diffopt.msg_sep = "";
        rev.diffopt.recursive = 1;
 -      rev.subject_prefix = "PATCH";
  
        rev.extra_headers = extra_headers;
  
        }
  
        if (ignore_if_in_upstream)
-               get_patch_ids(&rev, &patch_id_opts, prefix);
+               get_patch_ids(&rev, &ids, prefix);
  
        if (!use_stdout)
                realstdout = fdopen(dup(1), "w");
  
        prepare_revision_walk(&rev);
        while ((commit = get_revision(&rev)) != NULL) {
-               unsigned char sha1[20];
                /* ignore merges */
                if (commit->parents && commit->parents->next)
                        continue;
  
                if (ignore_if_in_upstream &&
-                               !get_patch_id(commit, &patch_id_opts, sha1) &&
-                               lookup_object(sha1))
+                               has_commit_patch_id(commit, &ids))
                        continue;
  
                nr++;
                        fclose(stdout);
        }
        free(list);
+       if (ignore_if_in_upstream)
+               free_patch_ids(&ids);
        return 0;
  }
  
@@@ -651,7 -635,7 +634,7 @@@ static const char cherry_usage[] 
  int cmd_cherry(int argc, const char **argv, const char *prefix)
  {
        struct rev_info revs;
-       struct diff_options patch_id_opts;
+       struct patch_ids ids;
        struct commit *commit;
        struct commit_list *list = NULL;
        const char *upstream;
                        return 0;
        }
  
-       get_patch_ids(&revs, &patch_id_opts, prefix);
+       get_patch_ids(&revs, &ids, prefix);
  
        if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
                die("Unknown commit %s", limit);
        }
  
        while (list) {
-               unsigned char sha1[20];
                char sign = '+';
  
                commit = list->item;
-               if (!get_patch_id(commit, &patch_id_opts, sha1) &&
-                   lookup_object(sha1))
+               if (has_commit_patch_id(commit, &ids))
                        sign = '-';
  
                if (verbose) {
                list = list->next;
        }
  
+       free_patch_ids(&ids);
        return 0;
  }
diff --combined revision.c
index 37f1eab9e56ee6e725dfd2a29c95f2a4f1f15621,e9de8650d37398b5d46256eced053f3b7dd4e25a..ce70f48ce0880e8b43c3f62cd13bc185bfee8c4b
@@@ -8,6 -8,7 +8,7 @@@
  #include "revision.h"
  #include "grep.h"
  #include "reflog-walk.h"
+ #include "patch-ids.h"
  
  static char *path_name(struct name_path *path, const char *name)
  {
@@@ -422,6 -423,86 +423,86 @@@ static void add_parents_to_list(struct 
        }
  }
  
+ static void cherry_pick_list(struct commit_list *list)
+ {
+       struct commit_list *p;
+       int left_count = 0, right_count = 0;
+       int left_first;
+       struct patch_ids ids;
+       /* First count the commits on the left and on the right */
+       for (p = list; p; p = p->next) {
+               struct commit *commit = p->item;
+               unsigned flags = commit->object.flags;
+               if (flags & BOUNDARY)
+                       ;
+               else if (flags & SYMMETRIC_LEFT)
+                       left_count++;
+               else
+                       right_count++;
+       }
+       left_first = left_count < right_count;
+       init_patch_ids(&ids);
+       /* Compute patch-ids for one side */
+       for (p = list; p; p = p->next) {
+               struct commit *commit = p->item;
+               unsigned flags = commit->object.flags;
+               if (flags & BOUNDARY)
+                       continue;
+               /*
+                * If we have fewer left, left_first is set and we omit
+                * commits on the right branch in this loop.  If we have
+                * fewer right, we skip the left ones.
+                */
+               if (left_first != !!(flags & SYMMETRIC_LEFT))
+                       continue;
+               commit->util = add_commit_patch_id(commit, &ids);
+       }
+       /* Check the other side */
+       for (p = list; p; p = p->next) {
+               struct commit *commit = p->item;
+               struct patch_id *id;
+               unsigned flags = commit->object.flags;
+               if (flags & BOUNDARY)
+                       continue;
+               /*
+                * If we have fewer left, left_first is set and we omit
+                * commits on the left branch in this loop.
+                */
+               if (left_first == !!(flags & SYMMETRIC_LEFT))
+                       continue;
+               /*
+                * Have we seen the same patch id?
+                */
+               id = has_commit_patch_id(commit, &ids);
+               if (!id)
+                       continue;
+               id->seen = 1;
+               commit->object.flags |= SHOWN;
+       }
+       /* Now check the original side for seen ones */
+       for (p = list; p; p = p->next) {
+               struct commit *commit = p->item;
+               struct patch_id *ent;
+               ent = commit->util;
+               if (!ent)
+                       continue;
+               if (ent->seen)
+                       commit->object.flags |= SHOWN;
+               commit->util = NULL;
+       }
+       free_patch_ids(&ids);
+ }
  static void limit_list(struct rev_info *revs)
  {
        struct commit_list *list = revs->commits;
                        continue;
                p = &commit_list_insert(commit, p)->next;
        }
+       if (revs->cherry_pick)
+               cherry_pick_list(newlist);
        revs->commits = newlist;
  }
  
@@@ -567,7 -651,6 +651,7 @@@ void init_revisions(struct rev_info *re
        revs->min_age = -1;
        revs->skip_count = -1;
        revs->max_count = -1;
 +      revs->subject_prefix = "PATCH";
  
        revs->prune_fn = NULL;
        revs->prune_data = NULL;
@@@ -914,6 -997,10 +998,10 @@@ int setup_revisions(int argc, const cha
                                revs->left_right = 1;
                                continue;
                        }
+                       if (!strcmp(arg, "--cherry-pick")) {
+                               revs->cherry_pick = 1;
+                               continue;
+                       }
                        if (!strcmp(arg, "--objects")) {
                                revs->tag_objects = 1;
                                revs->tree_objects = 1;