{"thread":{"id":"39824","subject":"[PATCH v8 0/7] ref backend preamble","startedAt":"2015-07-09T22:50:53Z","lastAt":"2015-07-21T14:02:43Z","messageCount":14,"participants":["David Turner","Philip Oakley","Michael Haggerty"],"isPatch":true,"patchVersion":8,"patchTotal":7},"messages":[{"id":"265953","messageId":"1436482260-28088-1-git-send-email-dturner@twopensource.com","threadId":"39824","inReplyTo":null,"subject":"[PATCH v8 0/7] ref backend preamble","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-09T22:50:53Z","receivedAt":"2015-07-09T22:50:53Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"The current state of the discussion on alternate ref backends is that\nwe're going to continue to store pseudorefs (e.g. CHERRY_PICK_HEAD) as\nfiles in $GIT_DIR.  So this re-roll of the refs backend preamble\ndoesn't do anything to pseudorefs.  It just does reflog stuff.\n\nIn addition, this version removes the over-aggressive die() on reflog\nupdate failure from v7.  It adds the REF_FORCE_CREATE_REFLOG flag, as\nMichael Haggerty suggested.  And it fixes commit message or two, as\nsuggested.  I believe this addresses all comments I've seen on v7.\n\nThis addresses Johannes Sixt's concerns too, by removing the offending\ncode.\n"},{"id":"265955","messageId":"1436482260-28088-2-git-send-email-dturner@twopensource.com","threadId":"39824","inReplyTo":"1436482260-28088-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v8 1/7] refs.c: add err arguments to reflog functions","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-09T22:50:54Z","receivedAt":"2015-07-09T22:50:54Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Add an err argument to log_ref_setup that can explain the reason\nfor a failure. This then eliminates the need to manage errno through\nthis function since we can just add strerror(errno) to the err string\nwhen meaningful. No callers relied on errno from this function for\nanything else than the error message.\n\nAlso add err arguments to private functions write_ref_to_lockfile,\nlog_ref_write_1, commit_ref_update. This again eliminates the need to\nmanage errno in these functions.\n\nSome error messages are slightly reordered.\n\nUpdate of a patch by Ronnie Sahlberg.\n\nSigned-off-by: Ronnie Sahlberg <sahlberg@google.com>\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n builtin/checkout.c |   8 ++--\n refs.c             | 127 +++++++++++++++++++++++++++++++----------------------\n refs.h             |   4 +-\n 3 files changed, 81 insertions(+), 58 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex c018ab3..93f63d3 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -624,16 +624,18 @@ static void update_refs_for_switch(const struct checkout_opts *opts,\n \t\t\t\tstruct strbuf log_file = STRBUF_INIT;\n \t\t\t\tint ret;\n \t\t\t\tconst char *ref_name;\n+\t\t\t\tstruct strbuf err = STRBUF_INIT;\n \n \t\t\t\tref_name = mkpath(\"refs/heads/%s\", opts->new_orphan_branch);\n \t\t\t\ttemp = log_all_ref_updates;\n \t\t\t\tlog_all_ref_updates = 1;\n-\t\t\t\tret = log_ref_setup(ref_name, &log_file);\n+\t\t\t\tret = log_ref_setup(ref_name, &log_file, &err);\n \t\t\t\tlog_all_ref_updates = temp;\n \t\t\t\tstrbuf_release(&log_file);\n \t\t\t\tif (ret) {\n-\t\t\t\t\tfprintf(stderr, _(\"Can not do reflog for '%s'\\n\"),\n-\t\t\t\t\t    opts->new_orphan_branch);\n+\t\t\t\t\tfprintf(stderr, _(\"Can not do reflog for '%s'. %s\\n\"),\n+\t\t\t\t\t\topts->new_orphan_branch, err.buf);\n+\t\t\t\t\tstrbuf_release(&err);\n \t\t\t\t\treturn;\n \t\t\t\t}\n \t\t\t}\ndiff --git a/refs.c b/refs.c\nindex fb568d7..03e7505 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -2975,9 +2975,11 @@ static int rename_ref_available(const char *oldname, const char *newname)\n \treturn ret;\n }\n \n-static int write_ref_to_lockfile(struct ref_lock *lock, const unsigned char *sha1);\n+static int write_ref_to_lockfile(struct ref_lock *lock,\n+\t\t\t\t const unsigned char *sha1, struct strbuf *err);\n static int commit_ref_update(struct ref_lock *lock,\n-\t\t\t     const unsigned char *sha1, const char *logmsg);\n+\t\t\t     const unsigned char *sha1, const char *logmsg,\n+\t\t\t     struct strbuf *err);\n \n int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)\n {\n@@ -3038,9 +3040,10 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms\n \t}\n \thashcpy(lock->old_oid.hash, orig_sha1);\n \n-\tif (write_ref_to_lockfile(lock, orig_sha1) ||\n-\t    commit_ref_update(lock, orig_sha1, logmsg)) {\n-\t\terror(\"unable to write current sha1 into %s\", newrefname);\n+\tif (write_ref_to_lockfile(lock, orig_sha1, &err) ||\n+\t    commit_ref_update(lock, orig_sha1, logmsg, &err)) {\n+\t\terror(\"unable to write current sha1 into %s: %s\", newrefname, err.buf);\n+\t\tstrbuf_release(&err);\n \t\tgoto rollback;\n \t}\n \n@@ -3056,9 +3059,11 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms\n \n \tflag = log_all_ref_updates;\n \tlog_all_ref_updates = 0;\n-\tif (write_ref_to_lockfile(lock, orig_sha1) ||\n-\t    commit_ref_update(lock, orig_sha1, NULL))\n-\t\terror(\"unable to write current sha1 into %s\", oldrefname);\n+\tif (write_ref_to_lockfile(lock, orig_sha1, &err) ||\n+\t    commit_ref_update(lock, orig_sha1, NULL, &err)) {\n+\t\terror(\"unable to write current sha1 into %s: %s\", oldrefname, err.buf);\n+\t\tstrbuf_release(&err);\n+\t}\n \tlog_all_ref_updates = flag;\n \n  rollbacklog:\n@@ -3113,8 +3118,8 @@ static int copy_msg(char *buf, const char *msg)\n \treturn cp - buf;\n }\n \n-/* This function must set a meaningful errno on failure */\n-int log_ref_setup(const char *refname, struct strbuf *sb_logfile)\n+/* This function will fill in *err and return -1 on failure */\n+int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf *err)\n {\n \tint logfd, oflags = O_APPEND | O_WRONLY;\n \tchar *logfile;\n@@ -3129,9 +3134,8 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile)\n \t     starts_with(refname, \"refs/notes/\") ||\n \t     !strcmp(refname, \"HEAD\"))) {\n \t\tif (safe_create_leading_directories(logfile) < 0) {\n-\t\t\tint save_errno = errno;\n-\t\t\terror(\"unable to create directory for %s\", logfile);\n-\t\t\terrno = save_errno;\n+\t\t\tstrbuf_addf(err, \"unable to create directory for %s. \"\n+\t\t\t\t    \"%s\", logfile, strerror(errno));\n \t\t\treturn -1;\n \t\t}\n \t\toflags |= O_CREAT;\n@@ -3144,20 +3148,16 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile)\n \n \t\tif (errno == EISDIR) {\n \t\t\tif (remove_empty_directories(logfile)) {\n-\t\t\t\tint save_errno = errno;\n-\t\t\t\terror(\"There are still logs under '%s'\",\n-\t\t\t\t      logfile);\n-\t\t\t\terrno = save_errno;\n+\t\t\t\tstrbuf_addf(err, \"There are still logs under \"\n+\t\t\t\t\t    \"'%s'\", logfile);\n \t\t\t\treturn -1;\n \t\t\t}\n \t\t\tlogfd = open(logfile, oflags, 0666);\n \t\t}\n \n \t\tif (logfd < 0) {\n-\t\t\tint save_errno = errno;\n-\t\t\terror(\"Unable to append to %s: %s\", logfile,\n-\t\t\t      strerror(errno));\n-\t\t\terrno = save_errno;\n+\t\t\tstrbuf_addf(err, \"Unable to append to %s: %s\",\n+\t\t\t\t    logfile, strerror(errno));\n \t\t\treturn -1;\n \t\t}\n \t}\n@@ -3195,7 +3195,7 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,\n \n static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,\n \t\t\t   const unsigned char *new_sha1, const char *msg,\n-\t\t\t   struct strbuf *sb_log_file)\n+\t\t\t   struct strbuf *sb_log_file, struct strbuf *err)\n {\n \tint logfd, result, oflags = O_APPEND | O_WRONLY;\n \tchar *log_file;\n@@ -3203,7 +3203,8 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,\n \tif (log_all_ref_updates < 0)\n \t\tlog_all_ref_updates = !is_bare_repository();\n \n-\tresult = log_ref_setup(refname, sb_log_file);\n+\tresult = log_ref_setup(refname, sb_log_file, err);\n+\n \tif (result)\n \t\treturn result;\n \tlog_file = sb_log_file->buf;\n@@ -3216,26 +3217,25 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,\n \tresult = log_ref_write_fd(logfd, old_sha1, new_sha1,\n \t\t\t\t  git_committer_info(0), msg);\n \tif (result) {\n-\t\tint save_errno = errno;\n+\t\tstrbuf_addf(err, \"Unable to append to %s. %s\", log_file,\n+\t\t\t    strerror(errno));\n \t\tclose(logfd);\n-\t\terror(\"Unable to append to %s\", log_file);\n-\t\terrno = save_errno;\n \t\treturn -1;\n \t}\n \tif (close(logfd)) {\n-\t\tint save_errno = errno;\n-\t\terror(\"Unable to append to %s\", log_file);\n-\t\terrno = save_errno;\n+\t\tstrbuf_addf(err, \"Unable to append to %s. %s\", log_file,\n+\t\t\t    strerror(errno));\n \t\treturn -1;\n \t}\n \treturn 0;\n }\n \n static int log_ref_write(const char *refname, const unsigned char *old_sha1,\n-\t\t\t const unsigned char *new_sha1, const char *msg)\n+\t\t\t const unsigned char *new_sha1, const char *msg,\n+\t\t\t struct strbuf *err)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n-\tint ret = log_ref_write_1(refname, old_sha1, new_sha1, msg, &sb);\n+\tint ret = log_ref_write_1(refname, old_sha1, new_sha1, msg, &sb, err);\n \tstrbuf_release(&sb);\n \treturn ret;\n }\n@@ -3247,25 +3247,28 @@ int is_branch(const char *refname)\n \n /*\n  * Write sha1 into the open lockfile, then close the lockfile. On\n- * errors, rollback the lockfile and set errno to reflect the problem.\n+ * errors, rollback the lockfile, fill in *err and\n+ * return -1.\n  */\n static int write_ref_to_lockfile(struct ref_lock *lock,\n-\t\t\t\t const unsigned char *sha1)\n+\t\t\t\t const unsigned char *sha1, struct strbuf *err)\n {\n \tstatic char term = '\\n';\n \tstruct object *o;\n \n \to = parse_object(sha1);\n \tif (!o) {\n-\t\terror(\"Trying to write ref %s with nonexistent object %s\",\n-\t\t\tlock->ref_name, sha1_to_hex(sha1));\n+\t\tstrbuf_addf(err,\n+\t\t\t    \"Trying to write ref %s with nonexistent object %s\",\n+\t\t\t    lock->ref_name, sha1_to_hex(sha1));\n \t\tunlock_ref(lock);\n \t\terrno = EINVAL;\n \t\treturn -1;\n \t}\n \tif (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {\n-\t\terror(\"Trying to write non-commit object %s to branch %s\",\n-\t\t\tsha1_to_hex(sha1), lock->ref_name);\n+\t\tstrbuf_addf(err,\n+\t\t\t    \"Trying to write non-commit object %s to branch %s\",\n+\t\t\t    sha1_to_hex(sha1), lock->ref_name);\n \t\tunlock_ref(lock);\n \t\terrno = EINVAL;\n \t\treturn -1;\n@@ -3273,10 +3276,9 @@ static int write_ref_to_lockfile(struct ref_lock *lock,\n \tif (write_in_full(lock->lk->fd, sha1_to_hex(sha1), 40) != 40 ||\n \t    write_in_full(lock->lk->fd, &term, 1) != 1 ||\n \t    close_ref(lock) < 0) {\n-\t\tint save_errno = errno;\n-\t\terror(\"Couldn't write %s\", lock->lk->filename.buf);\n+\t\tstrbuf_addf(err,\n+\t\t\t    \"Couldn't write %s\", lock->lk->filename.buf);\n \t\tunlock_ref(lock);\n-\t\terrno = save_errno;\n \t\treturn -1;\n \t}\n \treturn 0;\n@@ -3288,12 +3290,17 @@ static int write_ref_to_lockfile(struct ref_lock *lock,\n  * necessary, using the specified lockmsg (which can be NULL).\n  */\n static int commit_ref_update(struct ref_lock *lock,\n-\t\t\t     const unsigned char *sha1, const char *logmsg)\n+\t\t\t     const unsigned char *sha1, const char *logmsg,\n+\t\t\t     struct strbuf *err)\n {\n \tclear_loose_ref_cache(&ref_cache);\n-\tif (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg) < 0 ||\n+\tif (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0 ||\n \t    (strcmp(lock->ref_name, lock->orig_ref_name) &&\n-\t     log_ref_write(lock->orig_ref_name, lock->old_oid.hash, sha1, logmsg) < 0)) {\n+\t     log_ref_write(lock->orig_ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0)) {\n+\t\tchar *old_msg = strbuf_detach(err, NULL);\n+\t\tstrbuf_addf(err, \"Cannot update the ref '%s': '%s'\",\n+\t\t\t    lock->ref_name, old_msg);\n+\t\tfree(old_msg);\n \t\tunlock_ref(lock);\n \t\treturn -1;\n \t}\n@@ -3316,14 +3323,21 @@ static int commit_ref_update(struct ref_lock *lock,\n \t\thead_ref = resolve_ref_unsafe(\"HEAD\", RESOLVE_REF_READING,\n \t\t\t\t\t      head_sha1, &head_flag);\n \t\tif (head_ref && (head_flag & REF_ISSYMREF) &&\n-\t\t    !strcmp(head_ref, lock->ref_name))\n-\t\t\tlog_ref_write(\"HEAD\", lock->old_oid.hash, sha1, logmsg);\n+\t\t    !strcmp(head_ref, lock->ref_name)) {\n+\t\t\tstruct strbuf log_err = STRBUF_INIT;\n+\t\t\tif (log_ref_write(\"HEAD\", lock->old_oid.hash, sha1,\n+\t\t\t\t\t  logmsg, &log_err)) {\n+\t\t\t\terror(\"%s\", log_err.buf);\n+\t\t\t\tstrbuf_release(&log_err);\n+\t\t\t}\n+\t\t}\n \t}\n \tif (commit_ref(lock)) {\n \t\terror(\"Couldn't set %s\", lock->ref_name);\n \t\tunlock_ref(lock);\n \t\treturn -1;\n \t}\n+\n \tunlock_ref(lock);\n \treturn 0;\n }\n@@ -3336,6 +3350,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,\n \tint fd, len, written;\n \tchar *git_HEAD = git_pathdup(\"%s\", ref_target);\n \tunsigned char old_sha1[20], new_sha1[20];\n+\tstruct strbuf err = STRBUF_INIT;\n \n \tif (logmsg && read_ref(ref_target, old_sha1))\n \t\thashclr(old_sha1);\n@@ -3384,8 +3399,11 @@ int create_symref(const char *ref_target, const char *refs_heads_master,\n #ifndef NO_SYMLINK_HEAD\n \tdone:\n #endif\n-\tif (logmsg && !read_ref(refs_heads_master, new_sha1))\n-\t\tlog_ref_write(ref_target, old_sha1, new_sha1, logmsg);\n+\tif (logmsg && !read_ref(refs_heads_master, new_sha1) &&\n+\t\tlog_ref_write(ref_target, old_sha1, new_sha1, logmsg, &err)) {\n+\t\terror(\"%s\", err.buf);\n+\t\tstrbuf_release(&err);\n+\t}\n \n \tfree(git_HEAD);\n \treturn 0;\n@@ -4021,14 +4039,19 @@ int ref_transaction_commit(struct ref_transaction *transaction,\n \t\t\t\t * value, so we don't need to write it.\n \t\t\t\t */\n \t\t\t} else if (write_ref_to_lockfile(update->lock,\n-\t\t\t\t\t\t\t update->new_sha1)) {\n+\t\t\t\t\t\t\t update->new_sha1,\n+\t\t\t\t\t\t\t err)) {\n+\t\t\t\tchar *write_err = strbuf_detach(err, NULL);\n+\n \t\t\t\t/*\n \t\t\t\t * The lock was freed upon failure of\n \t\t\t\t * write_ref_to_lockfile():\n \t\t\t\t */\n \t\t\t\tupdate->lock = NULL;\n-\t\t\t\tstrbuf_addf(err, \"cannot update the ref '%s'.\",\n-\t\t\t\t\t    update->refname);\n+\t\t\t\tstrbuf_addf(err,\n+\t\t\t\t\t    \"cannot update the ref '%s': %s\",\n+\t\t\t\t\t    update->refname, write_err);\n+\t\t\t\tfree(write_err);\n \t\t\t\tret = TRANSACTION_GENERIC_ERROR;\n \t\t\t\tgoto cleanup;\n \t\t\t} else {\n@@ -4054,11 +4077,9 @@ int ref_transaction_commit(struct ref_transaction *transaction,\n \n \t\tif (update->flags & REF_NEEDS_COMMIT) {\n \t\t\tif (commit_ref_update(update->lock,\n-\t\t\t\t\t      update->new_sha1, update->msg)) {\n+\t\t\t\t\t      update->new_sha1, update->msg, err)) {\n \t\t\t\t/* freed by commit_ref_update(): */\n \t\t\t\tupdate->lock = NULL;\n-\t\t\t\tstrbuf_addf(err, \"Cannot update the ref '%s'.\",\n-\t\t\t\t\t    update->refname);\n \t\t\t\tret = TRANSACTION_GENERIC_ERROR;\n \t\t\t\tgoto cleanup;\n \t\t\t} else {\ndiff --git a/refs.h b/refs.h\nindex e82fca5..debdefc 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -226,9 +226,9 @@ int pack_refs(unsigned int flags);\n #define REF_NODEREF\t0x01\n \n /*\n- * Setup reflog before using. Set errno to something meaningful on failure.\n+ * Setup reflog before using. Fill in err and return -1 on failure.\n  */\n-int log_ref_setup(const char *refname, struct strbuf *logfile);\n+int log_ref_setup(const char *refname, struct strbuf *logfile, struct strbuf *err);\n \n /** Reads log for the value of ref during at_time. **/\n extern int read_ref_at(const char *refname, unsigned int flags,\n-- \n2.0.5.499.g01f6352.dirty-twtrsrc\n"},{"id":"265954","messageId":"1436482260-28088-3-git-send-email-dturner@twopensource.com","threadId":"39824","inReplyTo":"1436482260-28088-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v8 2/7] refs: Break out check for reflog autocreation","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-09T22:50:55Z","receivedAt":"2015-07-09T22:50:55Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"This is just for clarity.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n refs.c | 16 +++++++++++-----\n 1 file changed, 11 insertions(+), 5 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 03e7505..903b401 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -3118,6 +3118,16 @@ static int copy_msg(char *buf, const char *msg)\n \treturn cp - buf;\n }\n \n+static int should_autocreate_reflog(const char *refname)\n+{\n+\tif (!log_all_ref_updates)\n+\t\treturn 0;\n+\treturn starts_with(refname, \"refs/heads/\") ||\n+\t\tstarts_with(refname, \"refs/remotes/\") ||\n+\t\tstarts_with(refname, \"refs/notes/\") ||\n+\t\t!strcmp(refname, \"HEAD\");\n+}\n+\n /* This function will fill in *err and return -1 on failure */\n int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf *err)\n {\n@@ -3128,11 +3138,7 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf\n \tlogfile = sb_logfile->buf;\n \t/* make sure the rest of the function can't change \"logfile\" */\n \tsb_logfile = NULL;\n-\tif (log_all_ref_updates &&\n-\t    (starts_with(refname, \"refs/heads/\") ||\n-\t     starts_with(refname, \"refs/remotes/\") ||\n-\t     starts_with(refname, \"refs/notes/\") ||\n-\t     !strcmp(refname, \"HEAD\"))) {\n+\tif (should_autocreate_reflog(refname)) {\n \t\tif (safe_create_leading_directories(logfile) < 0) {\n \t\t\tstrbuf_addf(err, \"unable to create directory for %s. \"\n \t\t\t\t    \"%s\", logfile, strerror(errno));\n-- \n2.0.5.499.g01f6352.dirty-twtrsrc\n"},{"id":"265956","messageId":"1436482260-28088-4-git-send-email-dturner@twopensource.com","threadId":"39824","inReplyTo":"1436482260-28088-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v8 3/7] refs: new public ref function: safe_create_reflog","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-09T22:50:56Z","receivedAt":"2015-07-09T22:50:56Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"The safe_create_reflog function creates a reflog, if it does not\nalready exist.\n\nThe log_ref_setup function becomes private and gains a force_create\nparameter to force the creation of a reflog even if log_all_ref_updates\nis false or the refname is not one of the special refnames.\n\nThe new parameter also reduces the need to store, modify, and restore\nthe log_all_ref_updates global before reflog creation.\n\nIn a moment, we will use this to add reflog creation commands to\ngit-reflog.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n builtin/checkout.c | 16 ++++++----------\n refs.c             | 24 ++++++++++++++++++++----\n refs.h             |  2 +-\n 3 files changed, 27 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 93f63d3..9923fd5 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -620,24 +620,20 @@ static void update_refs_for_switch(const struct checkout_opts *opts,\n \tif (opts->new_branch) {\n \t\tif (opts->new_orphan_branch) {\n \t\t\tif (opts->new_branch_log && !log_all_ref_updates) {\n-\t\t\t\tint temp;\n-\t\t\t\tstruct strbuf log_file = STRBUF_INIT;\n \t\t\t\tint ret;\n-\t\t\t\tconst char *ref_name;\n+\t\t\t\tchar *refname;\n \t\t\t\tstruct strbuf err = STRBUF_INIT;\n \n-\t\t\t\tref_name = mkpath(\"refs/heads/%s\", opts->new_orphan_branch);\n-\t\t\t\ttemp = log_all_ref_updates;\n-\t\t\t\tlog_all_ref_updates = 1;\n-\t\t\t\tret = log_ref_setup(ref_name, &log_file, &err);\n-\t\t\t\tlog_all_ref_updates = temp;\n-\t\t\t\tstrbuf_release(&log_file);\n+\t\t\t\trefname = mkpathdup(\"refs/heads/%s\", opts->new_orphan_branch);\n+\t\t\t\tret = safe_create_reflog(refname, &err, 1);\n+\t\t\t\tfree(refname);\n \t\t\t\tif (ret) {\n-\t\t\t\t\tfprintf(stderr, _(\"Can not do reflog for '%s'. %s\\n\"),\n+\t\t\t\t\tfprintf(stderr, _(\"can not do reflog for '%s'. %s\\n\"),\n \t\t\t\t\t\topts->new_orphan_branch, err.buf);\n \t\t\t\t\tstrbuf_release(&err);\n \t\t\t\t\treturn;\n \t\t\t\t}\n+\t\t\t\tstrbuf_release(&err);\n \t\t\t}\n \t\t}\n \t\telse\ndiff --git a/refs.c b/refs.c\nindex 903b401..4857f0b 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -3128,8 +3128,13 @@ static int should_autocreate_reflog(const char *refname)\n \t\t!strcmp(refname, \"HEAD\");\n }\n \n-/* This function will fill in *err and return -1 on failure */\n-int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf *err)\n+/*\n+ * Create a reflog for a ref.  If force_create = 0, the reflog will\n+ * only be created for certain refs (those for which\n+ * should_autocreate_reflog returns non-zero.  Otherwise, create it\n+ * regardless of the ref name.  Fill in *err and return -1 on failure.\n+ */\n+static int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf *err, int force_create)\n {\n \tint logfd, oflags = O_APPEND | O_WRONLY;\n \tchar *logfile;\n@@ -3138,7 +3143,7 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf\n \tlogfile = sb_logfile->buf;\n \t/* make sure the rest of the function can't change \"logfile\" */\n \tsb_logfile = NULL;\n-\tif (should_autocreate_reflog(refname)) {\n+\tif (force_create || should_autocreate_reflog(refname)) {\n \t\tif (safe_create_leading_directories(logfile) < 0) {\n \t\t\tstrbuf_addf(err, \"unable to create directory for %s. \"\n \t\t\t\t    \"%s\", logfile, strerror(errno));\n@@ -3173,6 +3178,17 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf\n \treturn 0;\n }\n \n+\n+int safe_create_reflog(const char *refname, struct strbuf *err, int force_create)\n+{\n+\tint ret;\n+\tstruct strbuf sb = STRBUF_INIT;\n+\n+\tret = log_ref_setup(refname, &sb, err, force_create);\n+\tstrbuf_release(&sb);\n+\treturn ret;\n+}\n+\n static int log_ref_write_fd(int fd, const unsigned char *old_sha1,\n \t\t\t    const unsigned char *new_sha1,\n \t\t\t    const char *committer, const char *msg)\n@@ -3209,7 +3225,7 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,\n \tif (log_all_ref_updates < 0)\n \t\tlog_all_ref_updates = !is_bare_repository();\n \n-\tresult = log_ref_setup(refname, sb_log_file, err);\n+\tresult = log_ref_setup(refname, sb_log_file, err, 0);\n \n \tif (result)\n \t\treturn result;\ndiff --git a/refs.h b/refs.h\nindex debdefc..3b90e16 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -228,7 +228,7 @@ int pack_refs(unsigned int flags);\n /*\n  * Setup reflog before using. Fill in err and return -1 on failure.\n  */\n-int log_ref_setup(const char *refname, struct strbuf *logfile, struct strbuf *err);\n+int safe_create_reflog(const char *refname, struct strbuf *err, int force_create);\n \n /** Reads log for the value of ref during at_time. **/\n extern int read_ref_at(const char *refname, unsigned int flags,\n-- \n2.0.5.499.g01f6352.dirty-twtrsrc\n"},{"id":"265958","messageId":"1436482260-28088-5-git-send-email-dturner@twopensource.com","threadId":"39824","inReplyTo":"1436482260-28088-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v8 4/7] git-reflog: add exists command","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-09T22:50:57Z","receivedAt":"2015-07-09T22:50:57Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Theis are necessary because alternate ref backends might store reflogs\nsomewhere other than .git/logs.  Code that now directly manipulates\n.git/logs should instead go through git-reflog.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n Documentation/git-reflog.txt |  4 ++++\n builtin/reflog.c             | 33 ++++++++++++++++++++++++++++++++-\n t/t1411-reflog-show.sh       |  5 +++++\n 3 files changed, 41 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt\nindex 5e7908e..4b08fc7 100644\n--- a/Documentation/git-reflog.txt\n+++ b/Documentation/git-reflog.txt\n@@ -23,6 +23,7 @@ depending on the subcommand:\n \t[--dry-run] [--verbose] [--all | <refs>...]\n 'git reflog delete' [--rewrite] [--updateref]\n \t[--dry-run] [--verbose] ref@\\{specifier\\}...\n+'git reflog exists' <ref>\n \n Reference logs, or \"reflogs\", record when the tips of branches and\n other references were updated in the local repository. Reflogs are\n@@ -52,6 +53,9 @@ argument must be an _exact_ entry (e.g. \"`git reflog delete\n master@{2}`\"). This subcommand is also typically not used directly by\n end users.\n \n+The \"exists\" subcommand checks whether a ref has a reflog.  It exists\n+with zero status if the reflog exists, and non-zero status if it does\n+not.\n \n OPTIONS\n -------\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex c2eb8ff..7ed0e85 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -13,6 +13,8 @@ static const char reflog_expire_usage[] =\n \"git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] <refs>...\";\n static const char reflog_delete_usage[] =\n \"git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <refs>...\";\n+static const char reflog_exists_usage[] =\n+\"git reflog exists <ref>\";\n \n static unsigned long default_reflog_expire;\n static unsigned long default_reflog_expire_unreachable;\n@@ -699,12 +701,38 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n \treturn status;\n }\n \n+static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n+{\n+\tint i, start = 0;\n+\n+\tfor (i = 1; i < argc; i++) {\n+\t\tconst char *arg = argv[i];\n+\t\tif (!strcmp(arg, \"--\")) {\n+\t\t\ti++;\n+\t\t\tbreak;\n+\t\t}\n+\t\telse if (arg[0] == '-')\n+\t\t\tusage(reflog_exists_usage);\n+\t\telse\n+\t\t\tbreak;\n+\t}\n+\n+\tstart = i;\n+\n+\tif (argc - start != 1)\n+\t\tusage(reflog_exists_usage);\n+\n+\tif (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL))\n+\t\tdie(\"invalid ref format: %s\", argv[start]);\n+\treturn !reflog_exists(argv[start]);\n+}\n+\n /*\n  * main \"reflog\"\n  */\n \n static const char reflog_usage[] =\n-\"git reflog [ show | expire | delete ]\";\n+\"git reflog [ show | expire | delete | exists ]\";\n \n int cmd_reflog(int argc, const char **argv, const char *prefix)\n {\n@@ -724,5 +752,8 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)\n \tif (!strcmp(argv[1], \"delete\"))\n \t\treturn cmd_reflog_delete(argc - 1, argv + 1, prefix);\n \n+\tif (!strcmp(argv[1], \"exists\"))\n+\t\treturn cmd_reflog_exists(argc - 1, argv + 1, prefix);\n+\n \treturn cmd_log_reflog(argc, argv, prefix);\n }\ndiff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh\nindex 6f47c0d..3eb4f10 100755\n--- a/t/t1411-reflog-show.sh\n+++ b/t/t1411-reflog-show.sh\n@@ -166,4 +166,9 @@ test_expect_success 'git log -g -p shows diffs vs. parents' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'reflog exists works' '\n+\tgit reflog exists refs/heads/master &&\n+\t! git reflog exists refs/heads/nonexistent\n+'\n+\n test_done\n-- \n2.0.5.499.g01f6352.dirty-twtrsrc\n"},{"id":"265957","messageId":"1436482260-28088-6-git-send-email-dturner@twopensource.com","threadId":"39824","inReplyTo":"1436482260-28088-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v8 5/7] refs: add REF_FORCE_CREATE_REFLOG flag","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-09T22:50:58Z","receivedAt":"2015-07-09T22:50:58Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Add a flag to allow forcing the creation of a reflog even if the ref\nname and core.logAllRefUpdates setting would not ordinarily cause ref\ncreation.\n\nIn a moment, we will use this to add options to git tag and git\nupdate-ref to force reflog creation.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n refs.c | 34 +++++++++++++++++++++-------------\n refs.h |  1 +\n 2 files changed, 22 insertions(+), 13 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 4857f0b..06c62c8 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -63,6 +63,11 @@ static unsigned char refname_disposition[256] = {\n #define REF_NEEDS_COMMIT 0x20\n \n /*\n+ * 0x40 is REF_FORCE_CREATE_REFLOG, so skip it if you're adding a\n+ * value to ref_update::flags\n+ */\n+\n+/*\n  * Try to read one refname component from the front of refname.\n  * Return the length of the component found, or -1 if the component is\n  * not legal.  It is legal if it is something reasonable to have under\n@@ -2979,7 +2984,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock,\n \t\t\t\t const unsigned char *sha1, struct strbuf *err);\n static int commit_ref_update(struct ref_lock *lock,\n \t\t\t     const unsigned char *sha1, const char *logmsg,\n-\t\t\t     struct strbuf *err);\n+\t\t\t     int flags, struct strbuf *err);\n \n int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)\n {\n@@ -3041,7 +3046,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms\n \thashcpy(lock->old_oid.hash, orig_sha1);\n \n \tif (write_ref_to_lockfile(lock, orig_sha1, &err) ||\n-\t    commit_ref_update(lock, orig_sha1, logmsg, &err)) {\n+\t    commit_ref_update(lock, orig_sha1, logmsg, 0, &err)) {\n \t\terror(\"unable to write current sha1 into %s: %s\", newrefname, err.buf);\n \t\tstrbuf_release(&err);\n \t\tgoto rollback;\n@@ -3060,7 +3065,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms\n \tflag = log_all_ref_updates;\n \tlog_all_ref_updates = 0;\n \tif (write_ref_to_lockfile(lock, orig_sha1, &err) ||\n-\t    commit_ref_update(lock, orig_sha1, NULL, &err)) {\n+\t    commit_ref_update(lock, orig_sha1, NULL, 0, &err)) {\n \t\terror(\"unable to write current sha1 into %s: %s\", oldrefname, err.buf);\n \t\tstrbuf_release(&err);\n \t}\n@@ -3217,7 +3222,8 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,\n \n static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,\n \t\t\t   const unsigned char *new_sha1, const char *msg,\n-\t\t\t   struct strbuf *sb_log_file, struct strbuf *err)\n+\t\t\t   struct strbuf *sb_log_file, int flags,\n+\t\t\t   struct strbuf *err)\n {\n \tint logfd, result, oflags = O_APPEND | O_WRONLY;\n \tchar *log_file;\n@@ -3225,7 +3231,7 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,\n \tif (log_all_ref_updates < 0)\n \t\tlog_all_ref_updates = !is_bare_repository();\n \n-\tresult = log_ref_setup(refname, sb_log_file, err, 0);\n+\tresult = log_ref_setup(refname, sb_log_file, err, flags & REF_FORCE_CREATE_REFLOG);\n \n \tif (result)\n \t\treturn result;\n@@ -3254,10 +3260,11 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,\n \n static int log_ref_write(const char *refname, const unsigned char *old_sha1,\n \t\t\t const unsigned char *new_sha1, const char *msg,\n-\t\t\t struct strbuf *err)\n+\t\t\t int flags, struct strbuf *err)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n-\tint ret = log_ref_write_1(refname, old_sha1, new_sha1, msg, &sb, err);\n+\tint ret = log_ref_write_1(refname, old_sha1, new_sha1, msg, &sb, flags,\n+\t\t\t\t  err);\n \tstrbuf_release(&sb);\n \treturn ret;\n }\n@@ -3313,12 +3320,12 @@ static int write_ref_to_lockfile(struct ref_lock *lock,\n  */\n static int commit_ref_update(struct ref_lock *lock,\n \t\t\t     const unsigned char *sha1, const char *logmsg,\n-\t\t\t     struct strbuf *err)\n+\t\t\t     int flags, struct strbuf *err)\n {\n \tclear_loose_ref_cache(&ref_cache);\n-\tif (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0 ||\n+\tif (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg, flags, err) < 0 ||\n \t    (strcmp(lock->ref_name, lock->orig_ref_name) &&\n-\t     log_ref_write(lock->orig_ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0)) {\n+\t     log_ref_write(lock->orig_ref_name, lock->old_oid.hash, sha1, logmsg, flags, err) < 0)) {\n \t\tchar *old_msg = strbuf_detach(err, NULL);\n \t\tstrbuf_addf(err, \"Cannot update the ref '%s': '%s'\",\n \t\t\t    lock->ref_name, old_msg);\n@@ -3348,7 +3355,7 @@ static int commit_ref_update(struct ref_lock *lock,\n \t\t    !strcmp(head_ref, lock->ref_name)) {\n \t\t\tstruct strbuf log_err = STRBUF_INIT;\n \t\t\tif (log_ref_write(\"HEAD\", lock->old_oid.hash, sha1,\n-\t\t\t\t\t  logmsg, &log_err)) {\n+\t\t\t\t\t  logmsg, 0, &log_err)) {\n \t\t\t\terror(\"%s\", log_err.buf);\n \t\t\t\tstrbuf_release(&log_err);\n \t\t\t}\n@@ -3422,7 +3429,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,\n \tdone:\n #endif\n \tif (logmsg && !read_ref(refs_heads_master, new_sha1) &&\n-\t\tlog_ref_write(ref_target, old_sha1, new_sha1, logmsg, &err)) {\n+\t\tlog_ref_write(ref_target, old_sha1, new_sha1, logmsg, 0, &err)) {\n \t\terror(\"%s\", err.buf);\n \t\tstrbuf_release(&err);\n \t}\n@@ -4099,7 +4106,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,\n \n \t\tif (update->flags & REF_NEEDS_COMMIT) {\n \t\t\tif (commit_ref_update(update->lock,\n-\t\t\t\t\t      update->new_sha1, update->msg, err)) {\n+\t\t\t\t\t      update->new_sha1, update->msg,\n+\t\t\t\t\t      update->flags, err)) {\n \t\t\t\t/* freed by commit_ref_update(): */\n \t\t\t\tupdate->lock = NULL;\n \t\t\t\tret = TRANSACTION_GENERIC_ERROR;\ndiff --git a/refs.h b/refs.h\nindex 3b90e16..297ec45 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -224,6 +224,7 @@ int pack_refs(unsigned int flags);\n  * Other flags are reserved for internal use.\n  */\n #define REF_NODEREF\t0x01\n+#define REF_FORCE_CREATE_REFLOG 0x40\n \n /*\n  * Setup reflog before using. Fill in err and return -1 on failure.\n-- \n2.0.5.499.g01f6352.dirty-twtrsrc\n"},{"id":"265960","messageId":"1436482260-28088-7-git-send-email-dturner@twopensource.com","threadId":"39824","inReplyTo":"1436482260-28088-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v8 6/7] update-ref and tag: add --create-reflog arg","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-09T22:50:59Z","receivedAt":"2015-07-09T22:50:59Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Allow the creation of a ref (e.g. stash) with a reflog already in\nplace. For most refs (e.g. those under refs/heads), this happens\nautomatically, but for others, we need this option.\n\nCurrently, git does this by pre-creating the reflog, but alternate ref\nbackends might store reflogs somewhere other than .git/logs.  Code\nthat now directly manipulates .git/logs should instead use git\nplumbing commands.\n\nI also added --create-reflog to git tag, just for completeness.\n\nIn a moment, we will use this argument to make git stash work with\nalternate ref backends.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n Documentation/git-tag.txt        |  5 ++++-\n Documentation/git-update-ref.txt |  5 ++++-\n builtin/tag.c                    |  5 ++++-\n builtin/update-ref.c             | 14 +++++++++++---\n t/t1400-update-ref.sh            | 38 ++++++++++++++++++++++++++++++++++++++\n t/t7004-tag.sh                   | 14 +++++++++++++-\n 6 files changed, 74 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt\nindex 034d10d..2312980 100644\n--- a/Documentation/git-tag.txt\n+++ b/Documentation/git-tag.txt\n@@ -13,7 +13,7 @@ SYNOPSIS\n \t<tagname> [<commit> | <object>]\n 'git tag' -d <tagname>...\n 'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]\n-\t[--column[=<options>] | --no-column] [<pattern>...]\n+\t[--column[=<options>] | --no-column] [--create-reflog] [<pattern>...]\n \t[<pattern>...]\n 'git tag' -v <tagname>...\n \n@@ -143,6 +143,9 @@ This option is only applicable when listing tags without annotation lines.\n \tall, 'whitespace' removes just leading/trailing whitespace lines and\n \t'strip' removes both whitespace and commentary.\n \n+--create-reflog::\n+\tCreate a reflog for the tag.\n+\n <tagname>::\n \tThe name of the tag to create, delete, or describe.\n \tThe new tag name must pass all checks defined by\ndiff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt\nindex c8f5ae5..969bfab 100644\n--- a/Documentation/git-update-ref.txt\n+++ b/Documentation/git-update-ref.txt\n@@ -8,7 +8,7 @@ git-update-ref - Update the object name stored in a ref safely\n SYNOPSIS\n --------\n [verse]\n-'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>] | --stdin [-z])\n+'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] [--create-reflog] <ref> <newvalue> [<oldvalue>] | --stdin [-z])\n \n DESCRIPTION\n -----------\n@@ -67,6 +67,9 @@ performs all modifications together.  Specify commands of the form:\n \tverify SP <ref> [SP <oldvalue>] LF\n \toption SP <opt> LF\n \n+With `--create-reflog`, update-ref will create a reflog for each ref\n+even if one would not ordinarily be created.\n+\n Quote fields containing whitespace as if they were strings in C source\n code; i.e., surrounded by double-quotes and with backslash escapes.\n Use 40 \"0\" characters or the empty string to specify a zero value.  To\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 5f6cdc5..cccca99 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -579,6 +579,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \tstruct create_tag_options opt;\n \tchar *cleanup_arg = NULL;\n \tint annotate = 0, force = 0, lines = -1;\n+\tint create_reflog = 0;\n \tint cmdmode = 0;\n \tconst char *msgfile = NULL, *keyid = NULL;\n \tstruct msg_arg msg = { 0, STRBUF_INIT };\n@@ -605,6 +606,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\tOPT_STRING('u', \"local-user\", &keyid, N_(\"key-id\"),\n \t\t\t\t\tN_(\"use another key to sign the tag\")),\n \t\tOPT__FORCE(&force, N_(\"replace the tag if exists\")),\n+\t\tOPT_BOOL(0, \"create-reflog\", &create_reflog, N_(\"create_reflog\")),\n \n \t\tOPT_GROUP(N_(\"Tag listing options\")),\n \t\tOPT_COLUMN(0, \"column\", &colopts, N_(\"show tag list in columns\")),\n@@ -733,7 +735,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \ttransaction = ref_transaction_begin(&err);\n \tif (!transaction ||\n \t    ref_transaction_update(transaction, ref.buf, object, prev,\n-\t\t\t\t   0, NULL, &err) ||\n+\t\t\t\t   create_reflog ? REF_FORCE_CREATE_REFLOG : 0,\n+\t\t\t\t   NULL, &err) ||\n \t    ref_transaction_commit(transaction, &err))\n \t\tdie(\"%s\", err.buf);\n \tref_transaction_free(transaction);\ndiff --git a/builtin/update-ref.c b/builtin/update-ref.c\nindex 6763cf1..d9646ef 100644\n--- a/builtin/update-ref.c\n+++ b/builtin/update-ref.c\n@@ -14,6 +14,7 @@ static const char * const git_update_ref_usage[] = {\n \n static char line_termination = '\\n';\n static int update_flags;\n+int create_reflog_flag;\n static const char *msg;\n \n /*\n@@ -200,7 +201,8 @@ static const char *parse_cmd_update(struct ref_transaction *transaction,\n \n \tif (ref_transaction_update(transaction, refname,\n \t\t\t\t   new_sha1, have_old ? old_sha1 : NULL,\n-\t\t\t\t   update_flags, msg, &err))\n+\t\t\t\t   update_flags | create_reflog_flag,\n+\t\t\t\t   msg, &err))\n \t\tdie(\"%s\", err.buf);\n \n \tupdate_flags = 0;\n@@ -231,7 +233,8 @@ static const char *parse_cmd_create(struct ref_transaction *transaction,\n \t\tdie(\"create %s: extra input: %s\", refname, next);\n \n \tif (ref_transaction_create(transaction, refname, new_sha1,\n-\t\t\t\t   update_flags, msg, &err))\n+\t\t\t\t   update_flags | create_reflog_flag,\n+\t\t\t\t   msg, &err))\n \t\tdie(\"%s\", err.buf);\n \n \tupdate_flags = 0;\n@@ -354,6 +357,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)\n \tunsigned char sha1[20], oldsha1[20];\n \tint delete = 0, no_deref = 0, read_stdin = 0, end_null = 0;\n \tunsigned int flags = 0;\n+\tint create_reflog = 0;\n \tstruct option options[] = {\n \t\tOPT_STRING( 'm', NULL, &msg, N_(\"reason\"), N_(\"reason of the update\")),\n \t\tOPT_BOOL('d', NULL, &delete, N_(\"delete the reference\")),\n@@ -361,6 +365,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)\n \t\t\t\t\tN_(\"update <refname> not the one it points to\")),\n \t\tOPT_BOOL('z', NULL, &end_null, N_(\"stdin has NUL-terminated arguments\")),\n \t\tOPT_BOOL( 0 , \"stdin\", &read_stdin, N_(\"read updates from stdin\")),\n+\t\tOPT_BOOL( 0 , \"create-reflog\", &create_reflog, N_(\"create_reflog\")),\n \t\tOPT_END(),\n \t};\n \n@@ -370,6 +375,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)\n \tif (msg && !*msg)\n \t\tdie(\"Refusing to perform update with empty message.\");\n \n+\tcreate_reflog_flag = create_reflog ? REF_FORCE_CREATE_REFLOG : 0;\n+\n \tif (read_stdin) {\n \t\tstruct strbuf err = STRBUF_INIT;\n \t\tstruct ref_transaction *transaction;\n@@ -431,5 +438,6 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)\n \t\t\t\t  flags);\n \telse\n \t\treturn update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,\n-\t\t\t\t  flags, UPDATE_REFS_DIE_ON_ERR);\n+\t\t\t\t  flags | create_reflog_flag,\n+\t\t\t\t  UPDATE_REFS_DIE_ON_ERR);\n }\ndiff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh\nindex d787bf5..9d21c19 100755\n--- a/t/t1400-update-ref.sh\n+++ b/t/t1400-update-ref.sh\n@@ -23,6 +23,7 @@ test_expect_success setup '\n m=refs/heads/master\n n_dir=refs/heads/gu\n n=$n_dir/fixes\n+outside=foo\n \n test_expect_success \\\n \t\"create $m\" \\\n@@ -74,6 +75,24 @@ test_expect_success \"delete $m (by HEAD)\" '\n '\n rm -f .git/$m\n \n+test_expect_success 'update-ref does not create reflogs by default' '\n+\ttest_when_finished \"git update-ref -d $outside\" &&\n+\tgit update-ref $outside $A &&\n+\tgit rev-parse $A >expect &&\n+\tgit rev-parse $outside >actual &&\n+\ttest_cmp expect actual &&\n+\ttest_must_fail git reflog exists $outside\n+'\n+\n+test_expect_success 'update-ref creates reflogs with --create-reflog' '\n+\ttest_when_finished \"git update-ref -d $outside\" &&\n+\tgit update-ref --create-reflog $outside $A &&\n+\tgit rev-parse $A >expect &&\n+\tgit rev-parse $outside >actual &&\n+\ttest_cmp expect actual &&\n+\tgit reflog exists $outside\n+'\n+\n test_expect_success \\\n \t\"create $m (by HEAD)\" \\\n \t\"git update-ref HEAD $A &&\n@@ -472,6 +491,25 @@ test_expect_success 'stdin create ref works' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'stdin does not create reflogs by default' '\n+\ttest_when_finished \"git update-ref -d $outside\" &&\n+\techo \"create $outside $m\" >stdin &&\n+\tgit update-ref --stdin <stdin &&\n+\tgit rev-parse $m >expect &&\n+\tgit rev-parse $outside >actual &&\n+\ttest_cmp expect actual &&\n+\ttest_must_fail git reflog exists $outside\n+'\n+\n+test_expect_success 'stdin creates reflogs with --create-reflog' '\n+\techo \"create $outside $m\" >stdin &&\n+\tgit update-ref --create-reflog --stdin <stdin &&\n+\tgit rev-parse $m >expect &&\n+\tgit rev-parse $outside >actual &&\n+\ttest_cmp expect actual &&\n+\tgit reflog exists $outside\n+'\n+\n test_expect_success 'stdin succeeds with quoted argument' '\n \tgit update-ref -d $a &&\n \techo \"create $a \\\"$m\\\"\" >stdin &&\ndiff --git a/t/t7004-tag.sh b/t/t7004-tag.sh\nindex d1ff5c9..75423ab 100755\n--- a/t/t7004-tag.sh\n+++ b/t/t7004-tag.sh\n@@ -51,7 +51,19 @@ test_expect_success 'creating a tag using default HEAD should succeed' '\n \techo foo >foo &&\n \tgit add foo &&\n \tgit commit -m Foo &&\n-\tgit tag mytag\n+\tgit tag mytag &&\n+\ttest_must_fail git reflog exists refs/tags/mytag\n+'\n+\n+test_expect_success 'creating a tag with --create-reflog should create reflog' '\n+\ttest_when_finished \"git tag -d tag_with_reflog\" &&\n+\tgit tag --create-reflog tag_with_reflog &&\n+\tgit reflog exists refs/tags/tag_with_reflog\n+'\n+\n+test_expect_success '--create-reflog does not creates reflog on failure' '\n+\ttest_must_fail git tag --create-reflog mytag &&\n+\ttest_must_fail git reflog exists refs/tags/tag_with_reflog\n '\n \n test_expect_success 'listing all tags if one exists should succeed' '\n-- \n2.0.5.499.g01f6352.dirty-twtrsrc\n"},{"id":"265959","messageId":"1436482260-28088-8-git-send-email-dturner@twopensource.com","threadId":"39824","inReplyTo":"1436482260-28088-1-git-send-email-dturner@twopensource.com","subject":"[PATCH v8 7/7] git-stash: use update-ref --create-reflog instead of creating files","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-09T22:51:00Z","receivedAt":"2015-07-09T22:51:00Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"This is in support of alternate ref backends which don't necessarily\nstore reflogs as files.\n\nSigned-off-by: David Turner <dturner@twopensource.com>\n---\n git-stash.sh | 6 ++----\n 1 file changed, 2 insertions(+), 4 deletions(-)\n\ndiff --git a/git-stash.sh b/git-stash.sh\nindex 8e9e2cd..1d5ba7a 100755\n--- a/git-stash.sh\n+++ b/git-stash.sh\n@@ -183,9 +183,7 @@ store_stash () {\n \t\tstash_msg=\"Created via \\\"git stash store\\\".\"\n \tfi\n \n-\t# Make sure the reflog for stash is kept.\n-\t: >>\"$(git rev-parse --git-path logs/$ref_stash)\"\n-\tgit update-ref -m \"$stash_msg\" $ref_stash $w_commit\n+\tgit update-ref --create-reflog -m \"$stash_msg\" $ref_stash $w_commit\n \tret=$?\n \ttest $ret != 0 && test -z $quiet &&\n \tdie \"$(eval_gettext \"Cannot update \\$ref_stash with \\$w_commit\")\"\n@@ -262,7 +260,7 @@ save_stash () {\n \t\tsay \"$(gettext \"No local changes to save\")\"\n \t\texit 0\n \tfi\n-\ttest -f \"$(git rev-parse --git-path logs/$ref_stash)\" ||\n+\tgit reflog exists $ref_stash ||\n \t\tclear_stash || die \"$(gettext \"Cannot initialize stash\")\"\n \n \tcreate_stash \"$stash_msg\" $untracked\n-- \n2.0.5.499.g01f6352.dirty-twtrsrc\n"},{"id":"265993","messageId":"8C71190FFE324B1599E89376429C8F84@PhilipOakley","threadId":"39824","inReplyTo":"1436482260-28088-1-git-send-email-dturner@twopensource.com","subject":"Re: [PATCH v8 0/7] ref backend preamble","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.org","sentAt":"2015-07-10T14:34:09Z","receivedAt":"2015-07-10T14:34:09Z","isPatch":true,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"From: \"David Turner\" <dturner@twopensource.com>\n> The current state of the discussion on alternate ref backends is that\n> we're going to continue to store pseudorefs (e.g. CHERRY_PICK_HEAD) as\n\nAssuming this is accepted, should the definition of pseudorefs be \nincluded in the gitglossary?\n\nOnce ref backends become common, the distinction will needed in the \ndocs.\n\n> files in $GIT_DIR.  So this re-roll of the refs backend preamble\n> doesn't do anything to pseudorefs.  It just does reflog stuff.\n>\n--\nPhilip \n"},{"id":"265995","messageId":"1436550673.4542.66.camel@twopensource.com","threadId":"39824","inReplyTo":"8C71190FFE324B1599E89376429C8F84@PhilipOakley","subject":"Re: [PATCH v8 0/7] ref backend preamble","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2015-07-10T17:51:13Z","receivedAt":"2015-07-10T17:51:13Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"On Fri, 2015-07-10 at 15:34 +0100, Philip Oakley wrote:\n> From: \"David Turner\" <dturner@twopensource.com>\n> > The current state of the discussion on alternate ref backends is that\n> > we're going to continue to store pseudorefs (e.g. CHERRY_PICK_HEAD) as\n> \n> Assuming this is accepted, should the definition of pseudorefs be \n> included in the gitglossary?\n>\n> Once ref backends become common, the distinction will needed in the \n> docs.\n\nThis term is only in this message (that is, I don't think I used it in\nany commit messages yet).  The code uses it in at least one place\nalready.  But yes, I think if we decided to go with the pseudoref\nconcept, we should document it.\n"},{"id":"266538","messageId":"55AE465C.6000905@alum.mit.edu","threadId":"39824","inReplyTo":"1436482260-28088-2-git-send-email-dturner@twopensource.com","subject":"Re: [PATCH v8 1/7] refs.c: add err arguments to reflog functions","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2015-07-21T13:17:16Z","receivedAt":"2015-07-21T13:17:16Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 07/09/2015 03:50 PM, David Turner wrote:\n> Add an err argument to log_ref_setup that can explain the reason\n> for a failure. This then eliminates the need to manage errno through\n> this function since we can just add strerror(errno) to the err string\n> when meaningful. No callers relied on errno from this function for\n> anything else than the error message.\n> \n> Also add err arguments to private functions write_ref_to_lockfile,\n> log_ref_write_1, commit_ref_update. This again eliminates the need to\n> manage errno in these functions.\n> \n> Some error messages are slightly reordered.\n> \n> Update of a patch by Ronnie Sahlberg.\n> \n> Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>\n> Signed-off-by: David Turner <dturner@twopensource.com>\n> ---\n>  builtin/checkout.c |   8 ++--\n>  refs.c             | 127 +++++++++++++++++++++++++++++++----------------------\n>  refs.h             |   4 +-\n>  3 files changed, 81 insertions(+), 58 deletions(-)\n> \n> diff --git a/builtin/checkout.c b/builtin/checkout.c\n> index c018ab3..93f63d3 100644\n> --- a/builtin/checkout.c\n> +++ b/builtin/checkout.c\n> @@ -624,16 +624,18 @@ static void update_refs_for_switch(const struct checkout_opts *opts,\n>  \t\t\t\tstruct strbuf log_file = STRBUF_INIT;\n>  \t\t\t\tint ret;\n>  \t\t\t\tconst char *ref_name;\n> +\t\t\t\tstruct strbuf err = STRBUF_INIT;\n>  \n>  \t\t\t\tref_name = mkpath(\"refs/heads/%s\", opts->new_orphan_branch);\n>  \t\t\t\ttemp = log_all_ref_updates;\n>  \t\t\t\tlog_all_ref_updates = 1;\n> -\t\t\t\tret = log_ref_setup(ref_name, &log_file);\n> +\t\t\t\tret = log_ref_setup(ref_name, &log_file, &err);\n>  \t\t\t\tlog_all_ref_updates = temp;\n>  \t\t\t\tstrbuf_release(&log_file);\n>  \t\t\t\tif (ret) {\n> -\t\t\t\t\tfprintf(stderr, _(\"Can not do reflog for '%s'\\n\"),\n> -\t\t\t\t\t    opts->new_orphan_branch);\n> +\t\t\t\t\tfprintf(stderr, _(\"Can not do reflog for '%s'. %s\\n\"),\n> +\t\t\t\t\t\topts->new_orphan_branch, err.buf);\n\nOur usual pattern for chaining error messages is\n\n    $problem: $reason\n\nIn this patch (and maybe later patches too? I haven't checked yet) I see\n\n    $problem. $reason\n\nand also\n\n    $problem. '$reason'\n\nI think it would be good to use the first pattern consistently.\n\n> +\t\t\t\t\tstrbuf_release(&err);\n>  \t\t\t\t\treturn;\n>  \t\t\t\t}\n>  \t\t\t}\n> diff --git a/refs.c b/refs.c\n> index fb568d7..03e7505 100644\n> --- a/refs.c\n> +++ b/refs.c\n> [...]\n> @@ -3247,25 +3247,28 @@ int is_branch(const char *refname)\n>  \n>  /*\n>   * Write sha1 into the open lockfile, then close the lockfile. On\n> - * errors, rollback the lockfile and set errno to reflect the problem.\n> + * errors, rollback the lockfile, fill in *err and\n> + * return -1.\n>   */\n>  static int write_ref_to_lockfile(struct ref_lock *lock,\n> -\t\t\t\t const unsigned char *sha1)\n> +\t\t\t\t const unsigned char *sha1, struct strbuf *err)\n>  {\n>  \tstatic char term = '\\n';\n>  \tstruct object *o;\n>  \n>  \to = parse_object(sha1);\n>  \tif (!o) {\n> -\t\terror(\"Trying to write ref %s with nonexistent object %s\",\n> -\t\t\tlock->ref_name, sha1_to_hex(sha1));\n> +\t\tstrbuf_addf(err,\n> +\t\t\t    \"Trying to write ref %s with nonexistent object %s\",\n> +\t\t\t    lock->ref_name, sha1_to_hex(sha1));\n>  \t\tunlock_ref(lock);\n>  \t\terrno = EINVAL;\n\nIs it intentional that this function is still setting errno (here and a\nfew lines farther down)? I'm guessing that this is no longer needed,\nthough I haven't audited the callers.\n\n>  \t\treturn -1;\n>  \t}\n>  \tif (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {\n> -\t\terror(\"Trying to write non-commit object %s to branch %s\",\n> -\t\t\tsha1_to_hex(sha1), lock->ref_name);\n> +\t\tstrbuf_addf(err,\n> +\t\t\t    \"Trying to write non-commit object %s to branch %s\",\n> +\t\t\t    sha1_to_hex(sha1), lock->ref_name);\n>  \t\tunlock_ref(lock);\n>  \t\terrno = EINVAL;\n>  \t\treturn -1;\n> [...]\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\n"},{"id":"266541","messageId":"55AE48C5.8000007@alum.mit.edu","threadId":"39824","inReplyTo":"1436482260-28088-5-git-send-email-dturner@twopensource.com","subject":"Re: [PATCH v8 4/7] git-reflog: add exists command","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2015-07-21T13:27:33Z","receivedAt":"2015-07-21T13:27:33Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 07/09/2015 03:50 PM, David Turner wrote:\n> Theis are necessary because alternate ref backends might store reflogs\n> somewhere other than .git/logs.  Code that now directly manipulates\n> .git/logs should instead go through git-reflog.\n> \n> Signed-off-by: David Turner <dturner@twopensource.com>\n> ---\n>  Documentation/git-reflog.txt |  4 ++++\n>  builtin/reflog.c             | 33 ++++++++++++++++++++++++++++++++-\n>  t/t1411-reflog-show.sh       |  5 +++++\n>  3 files changed, 41 insertions(+), 1 deletion(-)\n> \n> diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt\n> index 5e7908e..4b08fc7 100644\n> --- a/Documentation/git-reflog.txt\n> +++ b/Documentation/git-reflog.txt\n> @@ -23,6 +23,7 @@ depending on the subcommand:\n>  \t[--dry-run] [--verbose] [--all | <refs>...]\n>  'git reflog delete' [--rewrite] [--updateref]\n>  \t[--dry-run] [--verbose] ref@\\{specifier\\}...\n> +'git reflog exists' <ref>\n>  \n>  Reference logs, or \"reflogs\", record when the tips of branches and\n>  other references were updated in the local repository. Reflogs are\n> @@ -52,6 +53,9 @@ argument must be an _exact_ entry (e.g. \"`git reflog delete\n>  master@{2}`\"). This subcommand is also typically not used directly by\n>  end users.\n>  \n> +The \"exists\" subcommand checks whether a ref has a reflog.  It exists\n\nThe second \"exists\" should be \"exits\".\n\n> +with zero status if the reflog exists, and non-zero status if it does\n> +not.\n>  \n> [...]\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\n"},{"id":"266542","messageId":"55AE4D1C.1010308@alum.mit.edu","threadId":"39824","inReplyTo":"1436482260-28088-7-git-send-email-dturner@twopensource.com","subject":"Re: [PATCH v8 6/7] update-ref and tag: add --create-reflog arg","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2015-07-21T13:46:04Z","receivedAt":"2015-07-21T13:46:04Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 07/09/2015 03:50 PM, David Turner wrote:\n> Allow the creation of a ref (e.g. stash) with a reflog already in\n> place. For most refs (e.g. those under refs/heads), this happens\n> automatically, but for others, we need this option.\n> \n> Currently, git does this by pre-creating the reflog, but alternate ref\n> backends might store reflogs somewhere other than .git/logs.  Code\n> that now directly manipulates .git/logs should instead use git\n> plumbing commands.\n> \n> I also added --create-reflog to git tag, just for completeness.\n> \n> In a moment, we will use this argument to make git stash work with\n> alternate ref backends.\n> \n> Signed-off-by: David Turner <dturner@twopensource.com>\n> ---\n>  Documentation/git-tag.txt        |  5 ++++-\n>  Documentation/git-update-ref.txt |  5 ++++-\n>  builtin/tag.c                    |  5 ++++-\n>  builtin/update-ref.c             | 14 +++++++++++---\n>  t/t1400-update-ref.sh            | 38 ++++++++++++++++++++++++++++++++++++++\n>  t/t7004-tag.sh                   | 14 +++++++++++++-\n>  6 files changed, 74 insertions(+), 7 deletions(-)\n> \n> [...]\n> diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh\n> index d1ff5c9..75423ab 100755\n> --- a/t/t7004-tag.sh\n> +++ b/t/t7004-tag.sh\n> @@ -51,7 +51,19 @@ test_expect_success 'creating a tag using default HEAD should succeed' '\n>  \techo foo >foo &&\n>  \tgit add foo &&\n>  \tgit commit -m Foo &&\n> -\tgit tag mytag\n> +\tgit tag mytag &&\n> +\ttest_must_fail git reflog exists refs/tags/mytag\n> +'\n> +\n> +test_expect_success 'creating a tag with --create-reflog should create reflog' '\n> +\ttest_when_finished \"git tag -d tag_with_reflog\" &&\n> +\tgit tag --create-reflog tag_with_reflog &&\n> +\tgit reflog exists refs/tags/tag_with_reflog\n> +'\n> +\n> +test_expect_success '--create-reflog does not creates reflog on failure' '\n\ns/creates/create/\n\n> +\ttest_must_fail git tag --create-reflog mytag &&\n> +\ttest_must_fail git reflog exists refs/tags/tag_with_reflog\n\nShouldn't this be\n\n\ttest_must_fail git reflog exists refs/tags/mytag\n\n?\n\n> [...]\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\n"},{"id":"266543","messageId":"55AE5103.7020907@alum.mit.edu","threadId":"39824","inReplyTo":"1436482260-28088-1-git-send-email-dturner@twopensource.com","subject":"Re: [PATCH v8 0/7] ref backend preamble","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2015-07-21T14:02:43Z","receivedAt":"2015-07-21T14:02:43Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 07/09/2015 03:50 PM, David Turner wrote:\n> The current state of the discussion on alternate ref backends is that\n> we're going to continue to store pseudorefs (e.g. CHERRY_PICK_HEAD) as\n> files in $GIT_DIR.  So this re-roll of the refs backend preamble\n> doesn't do anything to pseudorefs.  It just does reflog stuff.\n> \n> In addition, this version removes the over-aggressive die() on reflog\n> update failure from v7.  It adds the REF_FORCE_CREATE_REFLOG flag, as\n> Michael Haggerty suggested.  And it fixes commit message or two, as\n> suggested.  I believe this addresses all comments I've seen on v7.\n> \n> This addresses Johannes Sixt's concerns too, by removing the offending\n> code.\n\nI just reviewed the whole patch series. Aside from the minor points that\nI commented on, it all looks good to me.\n\nReviewed-by: Michael Haggerty <mhagger@alum.mit.edu>\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\n"}]}