Re: [PATCH 2/6] cherry-pick: Use refs infrastructure for CHERRY_PICK_HEAD

2015-06-25 Thread Junio C Hamano
David Turner dtur...@twopensource.com writes:

 Subject: Re: [PATCH 2/6] cherry-pick: Use refs infrastructure for 
 CHERRY_PICK_HEAD
 Also use refs infrastructure for REVERT_HEAD.  These refs
 need to go through the refs backend, since some code
 assumes that they can be read as refs.

cherry-pick: treat CHERRY_PICK_HEAD and REVERT_HEAD as refs

Instead of directly writing to and reading from files in
$GIT_DIR, use ref API to interact with CHERRY_PICK_HEAD
and REVERT_HEAD.


  void remove_branch_state(void)
  {
 - unlink(git_path(CHERRY_PICK_HEAD));
 - unlink(git_path(REVERT_HEAD));
 + delete_ref(CHERRY_PICK_HEAD, NULL, REF_NODEREF | REF_NO_REFLOG);
 + delete_ref(REVERT_HEAD, NULL, REF_NODEREF | REF_NO_REFLOG);

Interesting.  There is a separate question about NO_REFLOG I'll
discuss in more detail later.  But no-deref puzzled me.  They should
not be symbolic, but if somebody by mistake made a symbolic one, we
won't accidentally remove another unrelated one through them, so
that bit is a good thing to have.

  static void determine_whence(struct wt_status *s)
  {
 + unsigned char unused[20];
   if (file_exists(git_path(MERGE_HEAD)))
   whence = FROM_MERGE;
 - else if (file_exists(git_path(CHERRY_PICK_HEAD))) {
 + else if (!read_ref(CHERRY_PICK_HEAD, unused)) {

I would have expected that you would use ref_exists() here.

 diff --git a/contrib/completion/git-prompt.sh 
 b/contrib/completion/git-prompt.sh
 index 366f0bc..5e27a34 100644
 --- a/contrib/completion/git-prompt.sh
 +++ b/contrib/completion/git-prompt.sh
 @@ -415,9 +415,9 @@ __git_ps1 ()
   fi
   elif [ -f $g/MERGE_HEAD ]; then
   r=|MERGING
 - elif [ -f $g/CHERRY_PICK_HEAD ]; then
 + elif git rev-parse --quiet --verify CHERRY_PICK_HEAD 
 /dev/null; then
   r=|CHERRY-PICKING
 - elif [ -f $g/REVERT_HEAD ]; then
 + elif git rev-parse --quiet --verify REVERT_HEAD /dev/null; 
 then
   r=|REVERTING

Functionality-wise this may be OK but at some point we might want to
have a native way to produce $r with a single execution of a binary.

 @@ -429,8 +429,9 @@ __git_ps1 ()
   # symlink symbolic ref
   b=$(git symbolic-ref HEAD 2/dev/null)
   else
 - local head=
 - if ! __git_eread $g/HEAD head; then
 + local head
 + head=ref: $(git symbolic-ref HEAD 2/dev/null) || 
 head=$(git rev-parse HEAD)
 + if [ -z $head ]; then

This is questionable; before the pre-context of this hunk is a check
for HEAD inside $GIT_DIR on the filesystem.  Besides, the theme
of this patch is about CHERRY_PICK_HEAD and REVERT_HEAD; it does not
justify to touch things that deal with HEAD in the same patch.

 diff --git a/refs.c b/refs.c
 index b34a54a..c1a563f 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -2979,7 +2979,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
const unsigned char *sha1, struct strbuf* err);
  static int commit_ref_update(struct ref_lock *lock,
const unsigned char *sha1, const char *logmsg,
 -  struct strbuf *err);
 +  struct strbuf *err, int flags);
  
  int rename_ref(const char *oldrefname, const char *newrefname, const char 
 *logmsg)
  {
 @@ -3041,7 +3041,7 @@ int rename_ref(const char *oldrefname, const char 
 *newrefname, const char *logms
   hashcpy(lock-old_oid.hash, orig_sha1);
  
   if (write_ref_to_lockfile(lock, orig_sha1, err) ||
 - commit_ref_update(lock, orig_sha1, logmsg, err)) {
 + commit_ref_update(lock, orig_sha1, logmsg, err, 0)) {
   error(unable to write current sha1 into %s: %s, newrefname, 
 err.buf);
   strbuf_release(err);
   goto rollback;
 @@ -3060,7 +3060,7 @@ int rename_ref(const char *oldrefname, const char 
 *newrefname, const char *logms
   flag = log_all_ref_updates;
   log_all_ref_updates = 0;
   if (write_ref_to_lockfile(lock, orig_sha1, err) ||
 - commit_ref_update(lock, orig_sha1, NULL, err)) {
 + commit_ref_update(lock, orig_sha1, NULL, err, 0)) {
   error(unable to write current sha1 into %s: %s, oldrefname, 
 err.buf);
   strbuf_release(err);
   }
 @@ -3291,12 +3291,13 @@ static int write_ref_to_lockfile(struct ref_lock 
 *lock,
   */
  static int commit_ref_update(struct ref_lock *lock,
const unsigned char *sha1, const char *logmsg,
 -  struct strbuf *err)
 +  struct strbuf *err, int flags)
  {
   clear_loose_ref_cache(ref_cache);
 - if (log_ref_write(lock-ref_name, lock-old_oid.hash, sha1, logmsg, 
 err)  0 ||
 - (strcmp(lock-ref_name, lock

[PATCH 2/6] cherry-pick: Use refs infrastructure for CHERRY_PICK_HEAD

2015-06-24 Thread David Turner
Also use refs infrastructure for REVERT_HEAD.  These refs
need to go through the refs backend, since some code
assumes that they can be read as refs.

Signed-off-by: David Turner dtur...@twopensource.com
---
 branch.c |  4 ++--
 builtin/commit.c |  7 ---
 builtin/merge.c  |  3 ++-
 contrib/completion/git-prompt.sh |  9 +
 git-gui/lib/commit.tcl   |  2 +-
 refs.c   | 17 +
 refs.h   |  5 +
 sequencer.c  | 39 +--
 t/t7509-commit.sh|  4 ++--
 wt-status.c  |  6 ++
 10 files changed, 53 insertions(+), 43 deletions(-)

diff --git a/branch.c b/branch.c
index b002435..8371a16 100644
--- a/branch.c
+++ b/branch.c
@@ -302,8 +302,8 @@ void create_branch(const char *head,
 
 void remove_branch_state(void)
 {
-   unlink(git_path(CHERRY_PICK_HEAD));
-   unlink(git_path(REVERT_HEAD));
+   delete_ref(CHERRY_PICK_HEAD, NULL, REF_NODEREF | REF_NO_REFLOG);
+   delete_ref(REVERT_HEAD, NULL, REF_NODEREF | REF_NO_REFLOG);
unlink(git_path(MERGE_HEAD));
unlink(git_path(MERGE_RR));
unlink(git_path(MERGE_MSG));
diff --git a/builtin/commit.c b/builtin/commit.c
index b5b1158..0f0b184 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -166,9 +166,10 @@ static int opt_parse_m(const struct option *opt, const 
char *arg, int unset)
 
 static void determine_whence(struct wt_status *s)
 {
+   unsigned char unused[20];
if (file_exists(git_path(MERGE_HEAD)))
whence = FROM_MERGE;
-   else if (file_exists(git_path(CHERRY_PICK_HEAD))) {
+   else if (!read_ref(CHERRY_PICK_HEAD, unused)) {
whence = FROM_CHERRY_PICK;
if (file_exists(git_path(SEQ_DIR)))
sequencer_in_use = 1;
@@ -1777,8 +1778,8 @@ int cmd_commit(int argc, const char **argv, const char 
*prefix)
}
ref_transaction_free(transaction);
 
-   unlink(git_path(CHERRY_PICK_HEAD));
-   unlink(git_path(REVERT_HEAD));
+   delete_ref(CHERRY_PICK_HEAD, NULL, REF_NODEREF | REF_NO_REFLOG);
+   delete_ref(REVERT_HEAD, NULL, REF_NODEREF | REF_NO_REFLOG);
unlink(git_path(MERGE_HEAD));
unlink(git_path(MERGE_MSG));
unlink(git_path(MERGE_MODE));
diff --git a/builtin/merge.c b/builtin/merge.c
index 46aacd6..a4abf93 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1144,6 +1144,7 @@ int cmd_merge(int argc, const char **argv, const char 
*prefix)
unsigned char result_tree[20];
unsigned char stash[20];
unsigned char head_sha1[20];
+   unsigned char unused[20];
struct commit *head_commit;
struct strbuf buf = STRBUF_INIT;
int flag, i, ret = 0, head_subsumed;
@@ -1206,7 +1207,7 @@ int cmd_merge(int argc, const char **argv, const char 
*prefix)
else
die(_(You have not concluded your merge (MERGE_HEAD 
exists).));
}
-   if (file_exists(git_path(CHERRY_PICK_HEAD))) {
+   if (!read_ref(CHERRY_PICK_HEAD, unused)) {
if (advice_resolve_conflict)
die(_(You have not concluded your cherry-pick 
(CHERRY_PICK_HEAD exists).\n
Please, commit your changes before you merge.));
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 366f0bc..5e27a34 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -415,9 +415,9 @@ __git_ps1 ()
fi
elif [ -f $g/MERGE_HEAD ]; then
r=|MERGING
-   elif [ -f $g/CHERRY_PICK_HEAD ]; then
+   elif git rev-parse --quiet --verify CHERRY_PICK_HEAD 
/dev/null; then
r=|CHERRY-PICKING
-   elif [ -f $g/REVERT_HEAD ]; then
+   elif git rev-parse --quiet --verify REVERT_HEAD /dev/null; 
then
r=|REVERTING
elif [ -f $g/BISECT_LOG ]; then
r=|BISECTING
@@ -429,8 +429,9 @@ __git_ps1 ()
# symlink symbolic ref
b=$(git symbolic-ref HEAD 2/dev/null)
else
-   local head=
-   if ! __git_eread $g/HEAD head; then
+   local head
+   head=ref: $(git symbolic-ref HEAD 2/dev/null) || 
head=$(git rev-parse HEAD)
+   if [ -z $head ]; then
return $exit
fi
# is it a symbolic ref?
diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl
index 864b687..2b08b13 100644
--- a/git-gui/lib/commit.tcl
+++ b/git-gui/lib/commit.tcl
@@ -409,7 +409,7 @@ A rescan will be automatically started now.
catch {file delete [gitdir