Merge branch 'nh/empty-rebase'
authorJunio C Hamano <gitster@pobox.com>
Fri, 1 Jun 2012 20:28:19 +0000 (13:28 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 1 Jun 2012 20:28:19 +0000 (13:28 -0700)
* nh/empty-rebase:
cherry-pick: regression fix for empty commits

1  2 
sequencer.c
diff --combined sequencer.c
index 3c384b94d24e3099cb149c66347386d1430fadef,1b2168c1c2593a739c15acea42063a089d78ac77..bf078f274bfe23997fcd1bc8c2a1c958f39ac9fe
@@@ -165,7 -165,7 +165,7 @@@ static void write_message(struct strbu
  
  static struct tree *empty_tree(void)
  {
 -      return lookup_tree((const unsigned char *)EMPTY_TREE_SHA1_BIN);
 +      return lookup_tree(EMPTY_TREE_SHA1_BIN);
  }
  
  static int error_dirty_index(struct replay_opts *opts)
@@@ -235,7 -235,7 +235,7 @@@ static int do_recursive_merge(struct co
  
        if (!clean) {
                int i;
 -              strbuf_addstr(msgbuf, "\nConflicts:\n\n");
 +              strbuf_addstr(msgbuf, "\nConflicts:\n");
                for (i = 0; i < active_nr;) {
                        struct cache_entry *ce = active_cache[i++];
                        if (ce_stage(ce)) {
@@@ -291,7 -291,8 +291,8 @@@ static int is_index_unchanged(void
   * If we are revert, or if our cherry-pick results in a hand merge,
   * we had better say that the current user is responsible for that.
   */
- static int run_git_commit(const char *defmsg, struct replay_opts *opts)
+ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
+                         int allow_empty)
  {
        struct argv_array array;
        int rc;
                argv_array_push(&array, defmsg);
        }
  
-       if (opts->allow_empty)
+       if (allow_empty)
                argv_array_push(&array, "--allow-empty");
  
        rc = run_command_v_opt(array.argv, RUN_GIT_CMD);
@@@ -335,6 -336,44 +336,44 @@@ static int is_original_commit_empty(str
        return !hashcmp(ptree_sha1, commit->tree->object.sha1);
  }
  
+ /*
+  * Do we run "git commit" with "--allow-empty"?
+  */
+ static int allow_empty(struct replay_opts *opts, struct commit *commit)
+ {
+       int index_unchanged, empty_commit;
+       /*
+        * Three cases:
+        *
+        * (1) we do not allow empty at all and error out.
+        *
+        * (2) we allow ones that were initially empty, but
+        * forbid the ones that become empty;
+        *
+        * (3) we allow both.
+        */
+       if (!opts->allow_empty)
+               return 0; /* let "git commit" barf as necessary */
+       index_unchanged = is_index_unchanged();
+       if (index_unchanged < 0)
+               return index_unchanged;
+       if (!index_unchanged)
+               return 0; /* we do not have to say --allow-empty */
+       if (opts->keep_redundant_commits)
+               return 1;
+       empty_commit = is_original_commit_empty(commit);
+       if (empty_commit < 0)
+               return empty_commit;
+       if (!empty_commit)
+               return 0;
+       else
+               return 1;
+ }
  static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
  {
        unsigned char head[20];
        char *defmsg = NULL;
        struct strbuf msgbuf = STRBUF_INIT;
        int res;
-       int empty_commit;
-       int index_unchanged;
  
        if (opts->no_commit) {
                /*
                free_commit_list(remotes);
        }
  
-       empty_commit = is_original_commit_empty(commit);
-       if (empty_commit < 0)
-               return empty_commit;
        /*
         * If the merge was clean or if it failed due to conflict, we write
         * CHERRY_PICK_HEAD for the subsequent invocation of commit to use.
                print_advice(res == 1, opts);
                rerere(opts->allow_rerere_auto);
        } else {
-               index_unchanged = is_index_unchanged();
-               /*
-                * If index_unchanged is less than 0, that indicates we either
-                * couldn't parse HEAD or the index, so error out here.
-                */
-               if (index_unchanged < 0)
-                       return index_unchanged;
-               if (!empty_commit && !opts->keep_redundant_commits && index_unchanged)
-                       /*
-                        * The head tree and the index match
-                        * meaning the commit is empty.  Since it wasn't created
-                        * empty (based on the previous test), we can conclude
-                        * the commit has been made redundant.  Since we don't
-                        * want to keep redundant commits, we can just return
-                        * here, skipping this commit
-                        */
-                       return 0;
+               int allow = allow_empty(opts, commit);
+               if (allow < 0)
+                       return allow;
                if (!opts->no_commit)
-                       res = run_git_commit(defmsg, opts);
+                       res = run_git_commit(defmsg, opts, allow);
        }
  
        free_message(&msg);
@@@ -551,6 -568,33 +568,6 @@@ static void read_and_refresh_cache(stru
        rollback_lock_file(&index_lock);
  }
  
 -/*
 - * Append a commit to the end of the commit_list.
 - *
 - * next starts by pointing to the variable that holds the head of an
 - * empty commit_list, and is updated to point to the "next" field of
 - * the last item on the list as new commits are appended.
 - *
 - * Usage example:
 - *
 - *     struct commit_list *list;
 - *     struct commit_list **next = &list;
 - *
 - *     next = commit_list_append(c1, next);
 - *     next = commit_list_append(c2, next);
 - *     assert(commit_list_count(list) == 2);
 - *     return list;
 - */
 -static struct commit_list **commit_list_append(struct commit *commit,
 -                                             struct commit_list **next)
 -{
 -      struct commit_list *new = xmalloc(sizeof(struct commit_list));
 -      new->item = commit;
 -      *next = new;
 -      new->next = NULL;
 -      return &new->next;
 -}
 -
  static int format_todo(struct strbuf *buf, struct commit_list *todo_list,
                struct replay_opts *opts)
  {