Merge branch 'pw/sequencer-recover-from-unlockable-index'
authorJunio C Hamano <gitster@pobox.com>
Mon, 27 Nov 2017 02:06:35 +0000 (11:06 +0900)
committerJunio C Hamano <gitster@pobox.com>
Mon, 27 Nov 2017 02:06:35 +0000 (11:06 +0900)
The sequencer machinery (used by "git cherry-pick A..B", and "git
rebase -i", among other things) would have lost a commit if stopped
due to an unlockable index file, which has been fixed.

* pw/sequencer-recover-from-unlockable-index:
sequencer: reschedule pick if index can't be locked

1  2 
sequencer.c
diff --combined sequencer.c
index 19dd575ed9b3b280a3fdabc9121a2e193d6984db,10924ffd4962cf46cafc3f81ffd64e89c01c3649..fa94ed652d2ce87fddf824aa516456b5f42735e7
@@@ -393,7 -393,7 +393,7 @@@ static int fast_forward_to(const struc
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
            ref_transaction_update(transaction, "HEAD",
 -                                 to->hash, unborn ? null_sha1 : from->hash,
 +                                 to, unborn ? &null_oid : from,
                                   0, sb.buf, &err) ||
            ref_transaction_commit(transaction, &err)) {
                ref_transaction_free(transaction);
@@@ -438,7 -438,8 +438,8 @@@ static int do_recursive_merge(struct co
        char **xopt;
        static struct lock_file index_lock;
  
-       hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
+       if (hold_locked_index(&index_lock, LOCK_REPORT_ON_ERROR) < 0)
+               return -1;
  
        read_cache();
  
@@@ -489,7 -490,7 +490,7 @@@ static int is_index_unchanged(void
        struct object_id head_oid;
        struct commit *head_commit;
  
 -      if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_oid.hash, NULL))
 +      if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
                return error(_("could not resolve HEAD commit\n"));
  
        head_commit = lookup_commit(&head_oid);
@@@ -959,8 -960,7 +960,8 @@@ static int do_pick_commit(enum todo_com
                unborn = get_oid("HEAD", &head);
                if (unborn)
                        oidcpy(&head, &empty_tree_oid);
 -              if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0, 0))
 +              if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD",
 +                                     NULL, 0))
                        return error_dirty_index(opts);
        }
        discard_cache();
         * write it at all.
         */
        if (command == TODO_PICK && !opts->no_commit && (res == 0 || res == 1) &&
 -          update_ref(NULL, "CHERRY_PICK_HEAD", commit->object.oid.hash, NULL,
 -                     REF_NODEREF, UPDATE_REFS_MSG_ON_ERR))
 +          update_ref(NULL, "CHERRY_PICK_HEAD", &commit->object.oid, NULL,
 +                     REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
                res = -1;
        if (command == TODO_REVERT && ((opts->no_commit && res == 0) || res == 1) &&
 -          update_ref(NULL, "REVERT_HEAD", commit->object.oid.hash, NULL,
 -                     REF_NODEREF, UPDATE_REFS_MSG_ON_ERR))
 +          update_ref(NULL, "REVERT_HEAD", &commit->object.oid, NULL,
 +                     REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
                res = -1;
  
        if (res) {
@@@ -1185,6 -1185,7 +1186,6 @@@ static int read_and_refresh_cache(struc
        refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
        if (the_index.cache_changed && index_fd >= 0) {
                if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK)) {
 -                      rollback_lock_file(&index_lock);
                        return error(_("git %s: failed to refresh the index"),
                                _(action_name(opts)));
                }
@@@ -1630,7 -1631,7 +1631,7 @@@ static int rollback_single_pick(void
        if (!file_exists(git_path_cherry_pick_head()) &&
            !file_exists(git_path_revert_head()))
                return error(_("no cherry-pick or revert in progress"));
 -      if (read_ref_full("HEAD", 0, head_oid.hash, NULL))
 +      if (read_ref_full("HEAD", 0, &head_oid, NULL))
                return error(_("cannot resolve HEAD"));
        if (is_null_oid(&head_oid))
                return error(_("cannot abort from a branch yet to be born"));
@@@ -2129,8 -2130,8 +2130,8 @@@ cleanup_head_ref
                        }
                        msg = reflog_message(opts, "finish", "%s onto %s",
                                head_ref.buf, buf.buf);
 -                      if (update_ref(msg, head_ref.buf, head.hash, orig.hash,
 -                                      REF_NODEREF, UPDATE_REFS_MSG_ON_ERR)) {
 +                      if (update_ref(msg, head_ref.buf, &head, &orig,
 +                                     REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) {
                                res = error(_("could not update %s"),
                                        head_ref.buf);
                                goto cleanup_head_ref;
@@@ -2284,7 -2285,7 +2285,7 @@@ int sequencer_continue(struct replay_op
                        if (res)
                                goto release_todo_list;
                }
 -              if (index_differs_from("HEAD", 0, 0)) {
 +              if (index_differs_from("HEAD", NULL, 0)) {
                        res = error_dirty_index(opts);
                        goto release_todo_list;
                }
@@@ -2670,19 -2671,6 +2671,19 @@@ leave_check
        return res;
  }
  
 +static int rewrite_file(const char *path, const char *buf, size_t len)
 +{
 +      int rc = 0;
 +      int fd = open(path, O_WRONLY | O_TRUNC);
 +      if (fd < 0)
 +              return error_errno(_("could not open '%s' for writing"), path);
 +      if (write_in_full(fd, buf, len) < 0)
 +              rc = error_errno(_("could not write to '%s'"), path);
 +      if (close(fd) && !rc)
 +              rc = error_errno(_("could not close '%s'"), path);
 +      return rc;
 +}
 +
  /* skip picking commits whose parents are unchanged */
  int skip_unnecessary_picks(void)
  {
                }
                close(fd);
  
 -              fd = open(rebase_path_todo(), O_WRONLY, 0666);
 -              if (fd < 0) {
 -                      error_errno(_("could not open '%s' for writing"),
 -                                  rebase_path_todo());
 -                      todo_list_release(&todo_list);
 -                      return -1;
 -              }
 -              if (write_in_full(fd, todo_list.buf.buf + offset,
 -                              todo_list.buf.len - offset) < 0) {
 -                      error_errno(_("could not write to '%s'"),
 -                                  rebase_path_todo());
 -                      close(fd);
 -                      todo_list_release(&todo_list);
 -                      return -1;
 -              }
 -              if (ftruncate(fd, todo_list.buf.len - offset) < 0) {
 -                      error_errno(_("could not truncate '%s'"),
 -                                  rebase_path_todo());
 +              if (rewrite_file(rebase_path_todo(), todo_list.buf.buf + offset,
 +                               todo_list.buf.len - offset) < 0) {
                        todo_list_release(&todo_list);
 -                      close(fd);
                        return -1;
                }
 -              close(fd);
  
                todo_list.current = i;
                if (is_fixup(peek_command(&todo_list, 0)))
@@@ -2944,7 -2950,15 +2945,7 @@@ int rearrange_squash(void
                        }
                }
  
 -              fd = open(todo_file, O_WRONLY);
 -              if (fd < 0)
 -                      res = error_errno(_("could not open '%s'"), todo_file);
 -              else if (write(fd, buf.buf, buf.len) < 0)
 -                      res = error_errno(_("could not write to '%s'"), todo_file);
 -              else if (ftruncate(fd, buf.len) < 0)
 -                      res = error_errno(_("could not truncate '%s'"),
 -                                         todo_file);
 -              close(fd);
 +              res = rewrite_file(todo_file, buf.buf, buf.len);
                strbuf_release(&buf);
        }