{"thread":{"id":"6551","subject":"[PATCH 1/7] make reflog filename independent from struct ref_lock","startedAt":"2007-01-26T22:26:05Z","lastAt":"2007-01-27T01:49:00Z","messageCount":8,"participants":["Nicolas Pitre","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"32768","messageId":"1169850371517-git-send-email-nico@cam.org","threadId":"6551","inReplyTo":null,"subject":"[PATCH 1/7] make reflog filename independent from struct ref_lock","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-26T22:26:05Z","receivedAt":"2007-01-26T22:26:05Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"This allows for ref_log_write() to be used in a more flexible way,\nand is needed for future changes.\n\nThis is only code reorg with no behavior change.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n builtin-reflog.c |   10 ++++++----\n refs.c           |   44 ++++++++++++++++++++++----------------------\n refs.h           |    1 -\n 3 files changed, 28 insertions(+), 27 deletions(-)\n\ndiff --git a/builtin-reflog.c b/builtin-reflog.c\nindex b443ed9..b6612a9 100644\n--- a/builtin-reflog.c\n+++ b/builtin-reflog.c\n@@ -242,7 +242,7 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,\n \tstruct cmd_reflog_expire_cb *cmd = cb_data;\n \tstruct expire_reflog_cb cb;\n \tstruct ref_lock *lock;\n-\tchar *newlog_path = NULL;\n+\tchar *log_file, *newlog_path = NULL;\n \tint status = 0;\n \n \tif (strncmp(ref, \"refs/\", 5))\n@@ -255,7 +255,8 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,\n \tlock = lock_ref_sha1(ref + 5, sha1);\n \tif (!lock)\n \t\treturn error(\"cannot lock ref '%s'\", ref);\n-\tif (!file_exists(lock->log_file))\n+\tlog_file = xstrdup(git_path(\"logs/%s\", ref));\n+\tif (!file_exists(log_file))\n \t\tgoto finish;\n \tif (!cmd->dry_run) {\n \t\tnewlog_path = xstrdup(git_path(\"logs/%s.lock\", ref));\n@@ -271,13 +272,14 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,\n \t\tif (fclose(cb.newlog))\n \t\t\tstatus |= error(\"%s: %s\", strerror(errno),\n \t\t\t\t\tnewlog_path);\n-\t\tif (rename(newlog_path, lock->log_file)) {\n+\t\tif (rename(newlog_path, log_file)) {\n \t\t\tstatus |= error(\"cannot rename %s to %s\",\n-\t\t\t\t\tnewlog_path, lock->log_file);\n+\t\t\t\t\tnewlog_path, log_file);\n \t\t\tunlink(newlog_path);\n \t\t}\n \t}\n \tfree(newlog_path);\n+\tfree(log_file);\n \tunlock_ref(lock);\n \treturn status;\n }\ndiff --git a/refs.c b/refs.c\nindex 4323e9a..9395677 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -676,7 +676,6 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char\n \tlock->lk = xcalloc(1, sizeof(struct lock_file));\n \n \tlock->ref_name = xstrdup(ref);\n-\tlock->log_file = xstrdup(git_path(\"logs/%s\", ref));\n \tref_file = git_path(\"%s\", ref);\n \tlock->force_write = lstat(ref_file, &st) && errno == ENOENT;\n \n@@ -772,10 +771,10 @@ int delete_ref(const char *refname, unsigned char *sha1)\n \t */\n \tret |= repack_without_ref(refname);\n \n-\terr = unlink(lock->log_file);\n+\terr = unlink(git_path(\"logs/%s\", lock->ref_name));\n \tif (err && errno != ENOENT)\n \t\tfprintf(stderr, \"warning: unlink(%s) failed: %s\",\n-\t\t\tlock->log_file, strerror(errno));\n+\t\t\tgit_path(\"logs/%s\", lock->ref_name), strerror(errno));\n \tinvalidate_cached_refs();\n \tunlock_ref(lock);\n \treturn ret;\n@@ -916,46 +915,47 @@ void unlock_ref(struct ref_lock *lock)\n \t\t\trollback_lock_file(lock->lk);\n \t}\n \tfree(lock->ref_name);\n-\tfree(lock->log_file);\n \tfree(lock);\n }\n \n-static int log_ref_write(struct ref_lock *lock,\n-\tconst unsigned char *sha1, const char *msg)\n+static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,\n+\t\t\t const unsigned char *new_sha1, const char *msg)\n {\n \tint logfd, written, oflags = O_APPEND | O_WRONLY;\n \tunsigned maxlen, len;\n-\tchar *logrec;\n+\tchar *log_file, *logrec;\n \tconst char *committer;\n \n \tif (log_all_ref_updates < 0)\n \t\tlog_all_ref_updates = !is_bare_repository();\n \n+\tlog_file = git_path(\"logs/%s\", ref_name);\n+\n \tif (log_all_ref_updates &&\n-\t    (!strncmp(lock->ref_name, \"refs/heads/\", 11) ||\n-\t     !strncmp(lock->ref_name, \"refs/remotes/\", 13))) {\n-\t\tif (safe_create_leading_directories(lock->log_file) < 0)\n+\t    (!strncmp(ref_name, \"refs/heads/\", 11) ||\n+\t     !strncmp(ref_name, \"refs/remotes/\", 13))) {\n+\t\tif (safe_create_leading_directories(log_file) < 0)\n \t\t\treturn error(\"unable to create directory for %s\",\n-\t\t\t\tlock->log_file);\n+\t\t\t\t     log_file);\n \t\toflags |= O_CREAT;\n \t}\n \n-\tlogfd = open(lock->log_file, oflags, 0666);\n+\tlogfd = open(log_file, oflags, 0666);\n \tif (logfd < 0) {\n \t\tif (!(oflags & O_CREAT) && errno == ENOENT)\n \t\t\treturn 0;\n \n \t\tif ((oflags & O_CREAT) && errno == EISDIR) {\n-\t\t\tif (remove_empty_directories(lock->log_file)) {\n+\t\t\tif (remove_empty_directories(log_file)) {\n \t\t\t\treturn error(\"There are still logs under '%s'\",\n-\t\t\t\t\t     lock->log_file);\n+\t\t\t\t\t     log_file);\n \t\t\t}\n-\t\t\tlogfd = open(lock->log_file, oflags, 0666);\n+\t\t\tlogfd = open(log_file, oflags, 0666);\n \t\t}\n \n \t\tif (logfd < 0)\n \t\t\treturn error(\"Unable to append to %s: %s\",\n-\t\t\t\t     lock->log_file, strerror(errno));\n+\t\t\t\t     log_file, strerror(errno));\n \t}\n \n \tcommitter = git_committer_info(-1);\n@@ -963,8 +963,8 @@ static int log_ref_write(struct ref_lock *lock,\n \t\tmaxlen = strlen(committer) + strlen(msg) + 2*40 + 5;\n \t\tlogrec = xmalloc(maxlen);\n \t\tlen = snprintf(logrec, maxlen, \"%s %s %s\\t%s\\n\",\n-\t\t\tsha1_to_hex(lock->old_sha1),\n-\t\t\tsha1_to_hex(sha1),\n+\t\t\tsha1_to_hex(old_sha1),\n+\t\t\tsha1_to_hex(new_sha1),\n \t\t\tcommitter,\n \t\t\tmsg);\n \t}\n@@ -972,15 +972,15 @@ static int log_ref_write(struct ref_lock *lock,\n \t\tmaxlen = strlen(committer) + 2*40 + 4;\n \t\tlogrec = xmalloc(maxlen);\n \t\tlen = snprintf(logrec, maxlen, \"%s %s %s\\n\",\n-\t\t\tsha1_to_hex(lock->old_sha1),\n-\t\t\tsha1_to_hex(sha1),\n+\t\t\tsha1_to_hex(old_sha1),\n+\t\t\tsha1_to_hex(new_sha1),\n \t\t\tcommitter);\n \t}\n \twritten = len <= maxlen ? write_in_full(logfd, logrec, len) : -1;\n \tfree(logrec);\n \tclose(logfd);\n \tif (written != len)\n-\t\treturn error(\"Unable to append to %s\", lock->log_file);\n+\t\treturn error(\"Unable to append to %s\", log_file);\n \treturn 0;\n }\n \n@@ -1003,7 +1003,7 @@ int write_ref_sha1(struct ref_lock *lock,\n \t\treturn -1;\n \t}\n \tinvalidate_cached_refs();\n-\tif (log_ref_write(lock, sha1, logmsg) < 0) {\n+\tif (log_ref_write(lock->ref_name, lock->old_sha1, sha1, logmsg) < 0) {\n \t\tunlock_ref(lock);\n \t\treturn -1;\n \t}\ndiff --git a/refs.h b/refs.h\nindex 33450f1..2d2ba14 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -3,7 +3,6 @@\n \n struct ref_lock {\n \tchar *ref_name;\n-\tchar *log_file;\n \tstruct lock_file *lk;\n \tunsigned char old_sha1[20];\n \tint lock_fd;\n-- \n1.5.0.rc2.g6e2c\n"},{"id":"32770","messageId":"11698503712588-git-send-email-nico@cam.org","threadId":"6551","inReplyTo":"1169850371517-git-send-email-nico@cam.org","subject":"[PATCH 2/7] lock_ref_sha1_basic(): remember the original name of a ref when resolving it","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-26T22:26:06Z","receivedAt":"2007-01-26T22:26:06Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"A ref might be pointing to another ref but only the name of the last ref\nis remembered.  Let's remember about the first name as well.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n refs.c |    2 ++\n refs.h |    1 +\n 2 files changed, 3 insertions(+), 0 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 9395677..9641fad 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -676,6 +676,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char\n \tlock->lk = xcalloc(1, sizeof(struct lock_file));\n \n \tlock->ref_name = xstrdup(ref);\n+\tlock->orig_ref_name = xstrdup(orig_ref);\n \tref_file = git_path(\"%s\", ref);\n \tlock->force_write = lstat(ref_file, &st) && errno == ENOENT;\n \n@@ -915,6 +916,7 @@ void unlock_ref(struct ref_lock *lock)\n \t\t\trollback_lock_file(lock->lk);\n \t}\n \tfree(lock->ref_name);\n+\tfree(lock->orig_ref_name);\n \tfree(lock);\n }\n \ndiff --git a/refs.h b/refs.h\nindex 2d2ba14..94a58b4 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -3,6 +3,7 @@\n \n struct ref_lock {\n \tchar *ref_name;\n+\tchar *orig_ref_name;\n \tstruct lock_file *lk;\n \tunsigned char old_sha1[20];\n \tint lock_fd;\n-- \n1.5.0.rc2.g6e2c\n"},{"id":"32769","messageId":"11698503712998-git-send-email-nico@cam.org","threadId":"6551","inReplyTo":"11698503712588-git-send-email-nico@cam.org","subject":"[PATCH 3/7] enable separate reflog for HEAD","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-26T22:26:07Z","receivedAt":"2007-01-26T22:26:07Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"If HEAD is tied to a branch then both logs/HEAD and logs/heads/<branch> are\nupdated.  This is also true for any symbolic refs in general, but only HEAD\nwill see its reflog created automatically.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n refs.c |    7 +++++--\n 1 files changed, 5 insertions(+), 2 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 9641fad..92fa2e4 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -935,7 +935,8 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,\n \n \tif (log_all_ref_updates &&\n \t    (!strncmp(ref_name, \"refs/heads/\", 11) ||\n-\t     !strncmp(ref_name, \"refs/remotes/\", 13))) {\n+\t     !strncmp(ref_name, \"refs/remotes/\", 13) ||\n+\t     !strcmp(ref_name, \"HEAD\"))) {\n \t\tif (safe_create_leading_directories(log_file) < 0)\n \t\t\treturn error(\"unable to create directory for %s\",\n \t\t\t\t     log_file);\n@@ -1005,7 +1006,9 @@ int write_ref_sha1(struct ref_lock *lock,\n \t\treturn -1;\n \t}\n \tinvalidate_cached_refs();\n-\tif (log_ref_write(lock->ref_name, lock->old_sha1, sha1, logmsg) < 0) {\n+\tif (log_ref_write(lock->ref_name, lock->old_sha1, sha1, logmsg) < 0 ||\n+\t    (strcmp(lock->ref_name, lock->orig_ref_name) &&\n+\t     log_ref_write(lock->orig_ref_name, lock->old_sha1, sha1, logmsg) < 0)) {\n \t\tunlock_ref(lock);\n \t\treturn -1;\n \t}\n-- \n1.5.0.rc2.g6e2c\n"},{"id":"32771","messageId":"1169850372648-git-send-email-nico@cam.org","threadId":"6551","inReplyTo":"11698503712998-git-send-email-nico@cam.org","subject":"[PATCH 4/7] add reflog entries for HEAD when detached","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-26T22:26:08Z","receivedAt":"2007-01-26T22:26:08Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"Signed-off-by: Nicolas Pitre <nico@cam.org>\n---\n git-checkout.sh |    5 +++--\n 1 files changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex c52f352..ed344d8 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -259,8 +259,9 @@ if [ \"$?\" -eq 0 ]; then\n \t\t#\tgit update-ref --detach HEAD $new\n \t\t# or something like that...\n \t\t#\n-\t\techo \"$detached\" >\"$GIT_DIR/HEAD.new\" &&\n-\t\tmv \"$GIT_DIR/HEAD.new\" \"$GIT_DIR/HEAD\" ||\n+\t\tgit-rev-parse HEAD >\"$GIT_DIR/HEAD.new\" &&\n+\t\tmv \"$GIT_DIR/HEAD.new\" \"$GIT_DIR/HEAD\" &&\n+\t\tgit-update-ref -m \"checkout: moving to $arg\" HEAD \"$detached\" ||\n \t\t\tdie \"Cannot detach HEAD\"\n \t\tif test -n \"$detach_warn\"\n \t\tthen\n-- \n1.5.0.rc2.g6e2c\n"},{"id":"32774","messageId":"11698503722922-git-send-email-nico@cam.org","threadId":"6551","inReplyTo":"1169850372648-git-send-email-nico@cam.org","subject":"[PATCH 5/7] move create_symref() past log_ref_write()","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-26T22:26:09Z","receivedAt":"2007-01-26T22:26:09Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"This doesn't change the code at all.  It is done to makes the next patch\nmore obvious.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n refs.c |   86 ++++++++++++++++++++++++++++++++--------------------------------\n 1 files changed, 43 insertions(+), 43 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 92fa2e4..f91e853 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -309,49 +309,6 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *\n \treturn ref;\n }\n \n-int create_symref(const char *ref_target, const char *refs_heads_master)\n-{\n-\tconst char *lockpath;\n-\tchar ref[1000];\n-\tint fd, len, written;\n-\tconst char *git_HEAD = git_path(\"%s\", ref_target);\n-\n-#ifndef NO_SYMLINK_HEAD\n-\tif (prefer_symlink_refs) {\n-\t\tunlink(git_HEAD);\n-\t\tif (!symlink(refs_heads_master, git_HEAD))\n-\t\t\treturn 0;\n-\t\tfprintf(stderr, \"no symlink - falling back to symbolic ref\\n\");\n-\t}\n-#endif\n-\n-\tlen = snprintf(ref, sizeof(ref), \"ref: %s\\n\", refs_heads_master);\n-\tif (sizeof(ref) <= len) {\n-\t\terror(\"refname too long: %s\", refs_heads_master);\n-\t\treturn -1;\n-\t}\n-\tlockpath = mkpath(\"%s.lock\", git_HEAD);\n-\tfd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);\t\n-\twritten = write_in_full(fd, ref, len);\n-\tclose(fd);\n-\tif (written != len) {\n-\t\tunlink(lockpath);\n-\t\terror(\"Unable to write to %s\", lockpath);\n-\t\treturn -2;\n-\t}\n-\tif (rename(lockpath, git_HEAD) < 0) {\n-\t\tunlink(lockpath);\n-\t\terror(\"Unable to create %s\", git_HEAD);\n-\t\treturn -3;\n-\t}\n-\tif (adjust_shared_perm(git_HEAD)) {\n-\t\tunlink(lockpath);\n-\t\terror(\"Unable to fix permissions on %s\", lockpath);\n-\t\treturn -4;\n-\t}\n-\treturn 0;\n-}\n-\n int read_ref(const char *ref, unsigned char *sha1)\n {\n \tif (resolve_ref(ref, sha1, 1, NULL))\n@@ -1022,6 +979,49 @@ int write_ref_sha1(struct ref_lock *lock,\n \treturn 0;\n }\n \n+int create_symref(const char *ref_target, const char *refs_heads_master)\n+{\n+\tconst char *lockpath;\n+\tchar ref[1000];\n+\tint fd, len, written;\n+\tconst char *git_HEAD = git_path(\"%s\", ref_target);\n+\n+#ifndef NO_SYMLINK_HEAD\n+\tif (prefer_symlink_refs) {\n+\t\tunlink(git_HEAD);\n+\t\tif (!symlink(refs_heads_master, git_HEAD))\n+\t\t\treturn 0;\n+\t\tfprintf(stderr, \"no symlink - falling back to symbolic ref\\n\");\n+\t}\n+#endif\n+\n+\tlen = snprintf(ref, sizeof(ref), \"ref: %s\\n\", refs_heads_master);\n+\tif (sizeof(ref) <= len) {\n+\t\terror(\"refname too long: %s\", refs_heads_master);\n+\t\treturn -1;\n+\t}\n+\tlockpath = mkpath(\"%s.lock\", git_HEAD);\n+\tfd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);\t\n+\twritten = write_in_full(fd, ref, len);\n+\tclose(fd);\n+\tif (written != len) {\n+\t\tunlink(lockpath);\n+\t\terror(\"Unable to write to %s\", lockpath);\n+\t\treturn -2;\n+\t}\n+\tif (rename(lockpath, git_HEAD) < 0) {\n+\t\tunlink(lockpath);\n+\t\terror(\"Unable to create %s\", git_HEAD);\n+\t\treturn -3;\n+\t}\n+\tif (adjust_shared_perm(git_HEAD)) {\n+\t\tunlink(lockpath);\n+\t\terror(\"Unable to fix permissions on %s\", lockpath);\n+\t\treturn -4;\n+\t}\n+\treturn 0;\n+}\n+\n static char *ref_msg(const char *line, const char *endp)\n {\n \tconst char *ep;\n-- \n1.5.0.rc2.g6e2c\n"},{"id":"32773","messageId":"1169850372410-git-send-email-nico@cam.org","threadId":"6551","inReplyTo":"11698503722922-git-send-email-nico@cam.org","subject":"[PATCH 6/7] add logref support to git-symbolic-ref","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-26T22:26:10Z","receivedAt":"2007-01-26T22:26:10Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"Signed-off-by: Nicolas Pitre <nico@cam.org>\n---\n Documentation/git-symbolic-ref.txt |    6 +++++-\n builtin-branch.c                   |    3 ++-\n builtin-init-db.c                  |    2 +-\n builtin-symbolic-ref.c             |   16 ++++++++++++++--\n cache.h                            |    2 +-\n refs.c                             |   14 ++++++++++++--\n 6 files changed, 35 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt\nindex f93b79a..a88f722 100644\n--- a/Documentation/git-symbolic-ref.txt\n+++ b/Documentation/git-symbolic-ref.txt\n@@ -7,7 +7,7 @@ git-symbolic-ref - Read and modify symbolic refs\n \n SYNOPSIS\n --------\n-'git-symbolic-ref' [-q] <name> [<ref>]\n+'git-symbolic-ref' [-q] [-m <reason>] <name> [<ref>]\n \n DESCRIPTION\n -----------\n@@ -31,6 +31,10 @@ OPTIONS\n \tsymbolic ref but a detached HEAD; instead exit with\n \tnon-zero status silently.\n \n+-m::\n+\tUpdate the reflog for <name> with <reason>.  This is valid only\n+\twhen creating or updating a symbolic ref.\n+\n NOTES\n -----\n In the past, `.git/HEAD` was a symbolic link pointing at\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 25ffa54..52a9250 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -381,7 +381,8 @@ static void rename_branch(const char *oldname, const char *newname, int force)\n \tif (rename_ref(oldref, newref, logmsg))\n \t\tdie(\"Branch rename failed\");\n \n-\tif (!strcmp(oldname, head) && create_symref(\"HEAD\", newref))\n+\t/* no need to pass logmsg here as HEAD didn't really move */\n+\tif (!strcmp(oldname, head) && create_symref(\"HEAD\", newref, NULL))\n \t\tdie(\"Branch renamed to %s, but HEAD is not updated!\", newname);\n }\n \ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex 1865489..12e43d0 100644\n--- a/builtin-init-db.c\n+++ b/builtin-init-db.c\n@@ -231,7 +231,7 @@ static int create_default_files(const char *git_dir, const char *template_path)\n \tstrcpy(path + len, \"HEAD\");\n \treinit = !read_ref(\"HEAD\", sha1);\n \tif (!reinit) {\n-\t\tif (create_symref(\"HEAD\", \"refs/heads/master\") < 0)\n+\t\tif (create_symref(\"HEAD\", \"refs/heads/master\", NULL) < 0)\n \t\t\texit(1);\n \t}\n \ndiff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c\nindex 227c9d4..d41b406 100644\n--- a/builtin-symbolic-ref.c\n+++ b/builtin-symbolic-ref.c\n@@ -3,7 +3,7 @@\n #include \"refs.h\"\n \n static const char git_symbolic_ref_usage[] =\n-\"git-symbolic-ref [-q] name [ref]\";\n+\"git-symbolic-ref [-q] [-m <reason>] name [ref]\";\n \n static void check_symref(const char *HEAD, int quiet)\n {\n@@ -25,6 +25,7 @@ static void check_symref(const char *HEAD, int quiet)\n int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)\n {\n \tint quiet = 0;\n+\tconst char *msg = NULL;\n \n \tgit_config(git_default_config);\n \n@@ -34,6 +35,17 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\telse if (!strcmp(\"-q\", arg))\n \t\t\tquiet = 1;\n+\t\telse if (!strcmp(\"-m\", arg)) {\n+\t\t\targc--;\n+\t\t\targv++;\n+\t\t\tif (argc <= 1)\n+\t\t\t\tbreak;\n+\t\t\tmsg = argv[1];\n+\t\t\tif (!*msg)\n+\t\t\t\tdie(\"Refusing to perform update with empty message\");\n+\t\t\tif (strchr(msg, '\\n'))\n+\t\t\t\tdie(\"Refusing to perform update with \\\\n in message\");\n+\t\t}\n \t\telse if (!strcmp(\"--\", arg)) {\n \t\t\targc--;\n \t\t\targv++;\n@@ -50,7 +62,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)\n \t\tcheck_symref(argv[1], quiet);\n \t\tbreak;\n \tcase 3:\n-\t\tcreate_symref(argv[1], argv[2]);\n+\t\tcreate_symref(argv[1], argv[2], msg);\n \t\tbreak;\n \tdefault:\n \t\tusage(git_symbolic_ref_usage);\ndiff --git a/cache.h b/cache.h\nindex 9486132..6472608 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -302,7 +302,7 @@ extern int read_ref(const char *filename, unsigned char *sha1);\n extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *);\n extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);\n \n-extern int create_symref(const char *ref, const char *refs_heads_master);\n+extern int create_symref(const char *ref, const char *refs_heads_master, const char *logmsg);\n extern int validate_headref(const char *ref);\n \n extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);\ndiff --git a/refs.c b/refs.c\nindex f91e853..f632d49 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -979,18 +979,23 @@ int write_ref_sha1(struct ref_lock *lock,\n \treturn 0;\n }\n \n-int create_symref(const char *ref_target, const char *refs_heads_master)\n+int create_symref(const char *ref_target, const char *refs_heads_master,\n+\t\t  const char *logmsg)\n {\n \tconst char *lockpath;\n \tchar ref[1000];\n \tint fd, len, written;\n \tconst char *git_HEAD = git_path(\"%s\", ref_target);\n+\tunsigned char old_sha1[20], new_sha1[20];\n+\n+\tif (logmsg && read_ref(ref_target, old_sha1))\n+\t\thashclr(old_sha1);\n \n #ifndef NO_SYMLINK_HEAD\n \tif (prefer_symlink_refs) {\n \t\tunlink(git_HEAD);\n \t\tif (!symlink(refs_heads_master, git_HEAD))\n-\t\t\treturn 0;\n+\t\t\tgoto done;\n \t\tfprintf(stderr, \"no symlink - falling back to symbolic ref\\n\");\n \t}\n #endif\n@@ -1019,6 +1024,11 @@ int create_symref(const char *ref_target, const char *refs_heads_master)\n \t\terror(\"Unable to fix permissions on %s\", lockpath);\n \t\treturn -4;\n \t}\n+\n+\tdone:\n+\tif (logmsg && !read_ref(refs_heads_master, new_sha1))\n+\t\tlog_ref_write(ref_target, old_sha1, new_sha1, logmsg);\n+\n \treturn 0;\n }\n \n-- \n1.5.0.rc2.g6e2c\n"},{"id":"32772","messageId":"11698503731145-git-send-email-nico@cam.org","threadId":"6551","inReplyTo":"1169850372410-git-send-email-nico@cam.org","subject":"[PATCH 7/7] add reflog when moving HEAD to a new branch","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-01-26T22:26:11Z","receivedAt":"2007-01-26T22:26:11Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"Signed-off-by: Nicolas Pitre <nico@cam.org>\n---\n git-checkout.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex ed344d8..5dc281f 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -250,7 +250,7 @@ if [ \"$?\" -eq 0 ]; then\n \tfi\n \tif test -n \"$branch\"\n \tthen\n-\t\tGIT_DIR=\"$GIT_DIR\" git-symbolic-ref HEAD \"refs/heads/$branch\"\n+\t\tGIT_DIR=\"$GIT_DIR\" git-symbolic-ref -m \"checkout: moving to $branch\" HEAD \"refs/heads/$branch\"\n \telif test -n \"$detached\"\n \tthen\n \t\t# NEEDSWORK: we would want a command to detach the HEAD\n-- \n1.5.0.rc2.g6e2c\n"},{"id":"32792","messageId":"7vr6thqlwz.fsf@assigned-by-dhcp.cox.net","threadId":"6551","inReplyTo":"11698503722922-git-send-email-nico@cam.org","subject":"[PATCH 2/3] create_symref(): do not assume pathname from git_path() persists long enough","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-27T01:49:00Z","receivedAt":"2007-01-27T01:49:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Being lazy to rely on the cycling N buffers mkpath() and friends\nreturn is nice in general, but it makes it too easy to introduce\nnew bugs that are \"mysterious\".\n\nIntroduction of read_ref() in create_symref() after calling\ngit_path() to get the git_HEAD value (i.e. the path to create a\nnew symref at) consumed more than the available buffers and\nbroke a later call to mkpath() that derives lockpath from it.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n * t7201-co.sh caught three failures.  The problem this patch is\n   fixing overwrote and gave \".lock\" in lockpath, then open() on\n   that path failed and gave fd = -1 (because I scratched my\n   head and re-run the test without cleaning, and O_EXCL\n   triggered), which threw write_in_full() into infinite loop,\n   which will be fixed with the next patch.\n\n refs.c |   20 +++++++++++---------\n 1 files changed, 11 insertions(+), 9 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 5913185..4a52308 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -992,7 +992,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,\n \tconst char *lockpath;\n \tchar ref[1000];\n \tint fd, len, written;\n-\tconst char *git_HEAD = git_path(\"%s\", ref_target);\n+\tchar *git_HEAD = xstrdup(git_path(\"%s\", ref_target));\n \tunsigned char old_sha1[20], new_sha1[20];\n \n \tif (logmsg && read_ref(ref_target, old_sha1))\n@@ -1010,36 +1010,38 @@ int create_symref(const char *ref_target, const char *refs_heads_master,\n \tlen = snprintf(ref, sizeof(ref), \"ref: %s\\n\", refs_heads_master);\n \tif (sizeof(ref) <= len) {\n \t\terror(\"refname too long: %s\", refs_heads_master);\n-\t\treturn -1;\n+\t\tgoto error_free_return;\n \t}\n \tlockpath = mkpath(\"%s.lock\", git_HEAD);\n \tfd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);\n \tif (fd < 0) {\n \t\terror(\"Unable to open %s for writing\", lockpath);\n-\t\treturn -5;\n+\t\tgoto error_free_return;\n \t}\n \twritten = write_in_full(fd, ref, len);\n \tclose(fd);\n \tif (written != len) {\n-\t\tunlink(lockpath);\n \t\terror(\"Unable to write to %s\", lockpath);\n-\t\treturn -2;\n+\t\tgoto error_unlink_return;\n \t}\n \tif (rename(lockpath, git_HEAD) < 0) {\n-\t\tunlink(lockpath);\n \t\terror(\"Unable to create %s\", git_HEAD);\n-\t\treturn -3;\n+\t\tgoto error_unlink_return;\n \t}\n \tif (adjust_shared_perm(git_HEAD)) {\n-\t\tunlink(lockpath);\n \t\terror(\"Unable to fix permissions on %s\", lockpath);\n-\t\treturn -4;\n+\terror_unlink_return:\n+\t\tunlink(lockpath);\n+\terror_free_return:\n+\t\tfree(git_HEAD);\n+\t\treturn -1;\n \t}\n \n \tdone:\n \tif (logmsg && !read_ref(refs_heads_master, new_sha1))\n \t\tlog_ref_write(ref_target, old_sha1, new_sha1, logmsg);\n \n+\tfree(git_HEAD);\n \treturn 0;\n }\n \n-- \n1.5.0.rc2.g8ac6-dirty\n"}]}