Re: [PATCH v6 6/7] git-reflog: add create and exists functions
On 07/08/2015 02:49 AM, David Turner wrote: On Mon, 2015-07-06 at 18:51 +0200, Michael Haggerty wrote: [...] So all in all, I think it is unwise to allow a reflog to be created without its corresponding reference. This, in turn, suggests one or both of the following alternatives: 1. Allow git reflog create, but only for references that already exist. This turns out not to work for git stash, which wants to create a reflog for stash creation. 2. If we want to allow a reflog to be created at the same time as the corresponding reference, the reference-creation commands (git branch, git tag, git update-ref, and maybe some others) probably need a new option like --create-reflog (and, for symmetry, probably --no-create-reflog). git branch should already autocreate reflogs, since the refs it creates are under refs/heads. `git branch` only autocreates reflogs if core.logAllRefUpdates is on. That setting happens to be on by default in a non-bare repository but the user might turn it off. And it is off by default in a bare repository. In my opinion it would be nice for the user to be able to ask for a reflog to be created for a branch regardless of how core.logAllRefUpdates is set. Though I'm not saying that you have to be the one to implement that functionality :-) At the API level, it might make sense for the ref-transaction functions to get a new REF_FORCE_CREATE_REFLOG flag or something. Junio was opposed to the converse flag, so I'm going to just add manually add code to create reflogs. Unfortunately I wasn't keeping up with earlier versions of this patch series and now I can't find the email from Junio that you are referring to. If the earlier flag had the opposite (converse?) sense, like REF_INHIBIT_CREATE_REFLOG, then I agree that it wouldn't be an improvement. But I think this functionality *has to* be implemented within ref transactions for references that are just being created, because 1. The reflog must *not* be created if the reference creation fails for some reason. For example, the reflog shouldn't be created if the reference name has a D/F conflict with an existing one in the refs/foo vs. refs/foo/bar sense. (This conflict might not be obvious when creating the reflog file because the other reference might not have its reflog turned on.) There are other reasons that a reference creation might fail, and code outside of the refs API can't be expected to know all possibilities. 2. On the other hand, the reflog for a newly-created reference *should* reflect the creation of the reference. So it would be awkward to require the calling code to create the reference and *then* turn on the reflog. For references that already exist, I see no problem with a command that turns on the reflog without adding any entries to it. Though if you implement this, it would be prudent to check that existing reflog-handling code doesn't fail when confronted with an empty file; I think empty reflog files are rare now and might not be well-tested. Michael -- Michael Haggerty mhag...@alum.mit.edu -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
On Wed, 2015-07-08 at 15:16 +0200, Michael Haggerty wrote: On 07/08/2015 02:49 AM, David Turner wrote: On Mon, 2015-07-06 at 18:51 +0200, Michael Haggerty wrote: [...] So all in all, I think it is unwise to allow a reflog to be created without its corresponding reference. This, in turn, suggests one or both of the following alternatives: 1. Allow git reflog create, but only for references that already exist. This turns out not to work for git stash, which wants to create a reflog for stash creation. 2. If we want to allow a reflog to be created at the same time as the corresponding reference, the reference-creation commands (git branch, git tag, git update-ref, and maybe some others) probably need a new option like --create-reflog (and, for symmetry, probably --no-create-reflog). git branch should already autocreate reflogs, since the refs it creates are under refs/heads. `git branch` only autocreates reflogs if core.logAllRefUpdates is on. That setting happens to be on by default in a non-bare repository but the user might turn it off. And it is off by default in a bare repository. Oh, right. Well, we can always add that later, if anyone needs it. In my opinion it would be nice for the user to be able to ask for a reflog to be created for a branch regardless of how core.logAllRefUpdates is set. Though I'm not saying that you have to be the one to implement that functionality :-) At the API level, it might make sense for the ref-transaction functions to get a new REF_FORCE_CREATE_REFLOG flag or something. Junio was opposed to the converse flag, so I'm going to just add manually add code to create reflogs. Unfortunately I wasn't keeping up with earlier versions of this patch series and now I can't find the email from Junio that you are referring to. If the earlier flag had the opposite (converse?) sense, like REF_INHIBIT_CREATE_REFLOG, then I agree that it wouldn't be an improvement. But I think this functionality *has to* be implemented within ref transactions for references that are just being created, because 1. The reflog must *not* be created if the reference creation fails for some reason. For example, the reflog shouldn't be created if the reference name has a D/F conflict with an existing one in the refs/foo vs. refs/foo/bar sense. (This conflict might not be obvious when creating the reflog file because the other reference might not have its reflog turned on.) There are other reasons that a reference creation might fail, and code outside of the refs API can't be expected to know all possibilities. 2. On the other hand, the reflog for a newly-created reference *should* reflect the creation of the reference. So it would be awkward to require the calling code to create the reference and *then* turn on the reflog. Yep, makes sense. For references that already exist, I see no problem with a command that turns on the reflog without adding any entries to it. Though if you implement this, it would be prudent to check that existing reflog-handling code doesn't fail when confronted with an empty file; I think empty reflog files are rare now and might not be well-tested. I think empty reflog files are fine; I recall a few tests creating them (and git stash did so as well). But I also don't need that command (I think), so I won't implement it right now. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
On Mon, 2015-07-06 at 18:51 +0200, Michael Haggerty wrote: +{ + int i, status = 0, start = 0; It looks like start is initialized unconditionally after the first loop, so the initialization here is a red herring. Will fix. So, I have a philosophical question here with a practical side... It appears that this command allows you to create a reflog for a reference that doesn't yet exist. At first blush, this seems to make sense. Suppose you want the creation of a reference to be logged. Then you can first turn on its reflog, then create it. But I think this is going to create problems. Reflogs are rather intimately connected to their references. For example, writes to a reflog are guarded by locking the corresponding reference. And currently a reflog file is deleted when the corresponding reference is deleted. Also, there are constraints about which references can coexist; for example, references refs/heads/foo and refs/heads/foo/bar cannot exist at the same time, because (at least when using the filesystem backend), refs/heads/foo would have to be both a file and a directory at the same time. So if one of these references already exists, it would be an error to create a reflog for the other one. Similarly, if there is a reflog file for one of these references that was created by this command, but there is not yet a corresponding reference, then any command that later tries to create the other reference will not be able to create the reflog for *that* reference because it will conflict with the existing reflog. I doubt that the reference creation is smart enough to deal with this situation. So all in all, I think it is unwise to allow a reflog to be created without its corresponding reference. This, in turn, suggests one or both of the following alternatives: 1. Allow git reflog create, but only for references that already exist. This turns out not to work for git stash, which wants to create a reflog for stash creation. 2. If we want to allow a reflog to be created at the same time as the corresponding reference, the reference-creation commands (git branch, git tag, git update-ref, and maybe some others) probably need a new option like --create-reflog (and, for symmetry, probably --no-create-reflog). git branch should already autocreate reflogs, since the refs it creates are under refs/heads. At the API level, it might make sense for the ref-transaction functions to get a new REF_FORCE_CREATE_REFLOG flag or something. Junio was opposed to the converse flag, so I'm going to just add manually add code to create reflogs. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
On 06/29/2015 10:17 PM, David Turner wrote: These are necessary because alternate ref backends might store reflogs somewhere other than .git/logs. Code that now directly manipulates .git/logs should instead go through git-reflog. In a moment, we will use these functions to make git stash work with alternate ref backends. Signed-off-by: David Turner dtur...@twopensource.com --- Documentation/git-reflog.txt | 10 ++ builtin/reflog.c | 75 +++- t/t1411-reflog-show.sh | 12 +++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt index 5e7908e..2bf8aa6 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.txt @@ -23,6 +23,8 @@ depending on the subcommand: [--dry-run] [--verbose] [--all | refs...] 'git reflog delete' [--rewrite] [--updateref] [--dry-run] [--verbose] ref@\{specifier\}... +'git reflog create' refs... +'git reflog exists' ref Reference logs, or reflogs, record when the tips of branches and other references were updated in the local repository. Reflogs are @@ -52,6 +54,14 @@ argument must be an _exact_ entry (e.g. `git reflog delete master@{2}`). This subcommand is also typically not used directly by end users. +The create subcommand creates a reflog for one or more refs. Most +refs (those under refs/heads, refs/remotes, and refs/tags) will +automatically have reflogs created. Other refs will not. This command +allows manual ref creation. + +The exists subcommand checks whether a ref has a reflog. It exists +with zero status if the reflog exists, and non-zero status if it does +not. OPTIONS --- diff --git a/builtin/reflog.c b/builtin/reflog.c index c2eb8ff..3080865 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -13,6 +13,10 @@ static const char reflog_expire_usage[] = git reflog expire [--expire=time] [--expire-unreachable=time] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] refs...; static const char reflog_delete_usage[] = git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] refs...; +static const char reflog_create_usage[] = +git reflog create refs...; +static const char reflog_exists_usage[] = +git reflog exists ref; static unsigned long default_reflog_expire; static unsigned long default_reflog_expire_unreachable; @@ -699,12 +703,75 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) return status; } +static int cmd_reflog_create(int argc, const char **argv, const char *prefix) +{ + int i, status = 0, start = 0; It looks like start is initialized unconditionally after the first loop, so the initialization here is a red herring. + struct strbuf err = STRBUF_INIT; + + for (i = 1; i argc; i++) { + const char *arg = argv[i]; + if (!strcmp(arg, --)) { + i++; + break; + } + else if (arg[0] == '-') + usage(reflog_create_usage); + else + break; + } + + start = i; + + if (argc - start 1) if (start == argc) seems clearer, but that might just be me. + return error(Nothing to create?); + + for (i = start; i argc; i++) { + if (check_refname_format(argv[i], REFNAME_ALLOW_ONELEVEL)) + die(invalid ref format: %s, argv[i]); + } + for (i = start; i argc; i++) { + if (safe_create_reflog(argv[i], err, 1)) { + error(could not create reflog %s: %s, argv[i], + err.buf); + status = 1; + strbuf_release(err); + } + } + return status; +} + So, I have a philosophical question here with a practical side... It appears that this command allows you to create a reflog for a reference that doesn't yet exist. At first blush, this seems to make sense. Suppose you want the creation of a reference to be logged. Then you can first turn on its reflog, then create it. But I think this is going to create problems. Reflogs are rather intimately connected to their references. For example, writes to a reflog are guarded by locking the corresponding reference. And currently a reflog file is deleted when the corresponding reference is deleted. Also, there are constraints about which references can coexist; for example, references refs/heads/foo and refs/heads/foo/bar cannot exist at the same time, because (at least when using the filesystem backend), refs/heads/foo would have to be both a file and a directory at the same time. So if one of these references already exists, it would be an error to create a reflog for the other one. Similarly, if there is a reflog file for one of these references
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
On Mon, Jun 29, 2015 at 4:17 PM, David Turner dtur...@twopensource.com wrote: These are necessary because alternate ref backends might store reflogs somewhere other than .git/logs. Code that now directly manipulates .git/logs should instead go through git-reflog. In a moment, we will use these functions to make git stash work with alternate ref backends. Signed-off-by: David Turner dtur...@twopensource.com --- diff --git a/builtin/reflog.c b/builtin/reflog.c index c2eb8ff..3080865 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -13,6 +13,10 @@ static const char reflog_expire_usage[] = +static int cmd_reflog_create(int argc, const char **argv, const char *prefix) +{ + int i, status = 0, start = 0; + struct strbuf err = STRBUF_INIT; + + for (i = 1; i argc; i++) { + const char *arg = argv[i]; + if (!strcmp(arg, --)) { + i++; + break; + } + else if (arg[0] == '-') + usage(reflog_create_usage); + else + break; + } + + start = i; + + if (argc - start 1) + return error(Nothing to create?); + + for (i = start; i argc; i++) { + if (check_refname_format(argv[i], REFNAME_ALLOW_ONELEVEL)) + die(invalid ref format: %s, argv[i]); + } + for (i = start; i argc; i++) { + if (safe_create_reflog(argv[i], err, 1)) { + error(could not create reflog %s: %s, argv[i], + err.buf); + status = 1; + strbuf_release(err); This feels a bit dirty. While it's true that the current implementation of strbuf_release() re-initializes the strbuf (so you're not technically wrong by re-using it), that's an implementation detail; and indeed, the strbuf_release() documentation says: Release a string buffer and the memory it used. You should not use the string buffer after using this function, unless you initialize it again. Alternatives would be strbuf_reset() or declaring and releasing the strbuf within the for-loop scope. + } + } + return status; +} -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
On Tue, 2015-06-30 at 03:34 -0400, Eric Sunshine wrote: + strbuf_release(err); This feels a bit dirty. While it's true that the current Thanks. New patchset pushed to the branch on github: https://github.com/dturner-tw/git.git dturner/pluggable-backends-preamble -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
Eric Sunshine sunsh...@sunshineco.com writes: + for (i = start; i argc; i++) { + if (safe_create_reflog(argv[i], err, 1)) { + error(could not create reflog %s: %s, argv[i], + err.buf); + status = 1; + strbuf_release(err); This feels a bit dirty. Hmm, I do not share that feeling. I wouldn't be surprised if you found a lot of existing codepaths that run _init() a strbuf once, work on it and then _release() once a section of code is done with it, reuse it for further (unrelated) processing, knowing that _release() implicitly did _init() and the strbuf is ready to use after that. I thought that was a very well established pattern. While it's true that the current implementation of strbuf_release() re-initializes the strbuf (so you're not technically wrong by re-using it), that's an implementation detail; and indeed, the strbuf_release() documentation says: Release a string buffer and the memory it used. You should not use the string buffer after using this function, unless you initialize it again. Hmph. Perhaps the doc is wrong? ;-) Alternatives would be strbuf_reset() or declaring and releasing the strbuf within the for-loop scope. Because _reset() just rewinds the .len pointer without deallocating, you would need an extra _release() before it goes out of scope. If it is expected that the strbuf will be reused for a number of times, the length of the string each iteration uses is similar, and you will iterate the loop many times, _reset() each time and _release() to clean-up pattern would save many calls to realloc/free. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
On Tue, Jun 30, 2015 at 12:07 PM, Junio C Hamano gits...@pobox.com wrote: Eric Sunshine sunsh...@sunshineco.com writes: + for (i = start; i argc; i++) { + if (safe_create_reflog(argv[i], err, 1)) { + error(could not create reflog %s: %s, argv[i], + err.buf); + status = 1; + strbuf_release(err); This feels a bit dirty. Hmm, I do not share that feeling. I wouldn't be surprised if you found a lot of existing codepaths that run _init() a strbuf once, work on it and then _release() once a section of code is done with it, reuse it for further (unrelated) processing, knowing that _release() implicitly did _init() and the strbuf is ready to use after that. I thought that was a very well established pattern. That could the case, and I may not be familiar with code doing that. I have, however, seen plenty of code which uses strbuf_reset() in the way you describe. While it's true that the current implementation of strbuf_release() re-initializes the strbuf (so you're not technically wrong by re-using it), that's an implementation detail; and indeed, the strbuf_release() documentation says: Release a string buffer and the memory it used. You should not use the string buffer after using this function, unless you initialize it again. Hmph. Perhaps the doc is wrong? ;-) Perhaps. I always interpreted the documentation as meaning that the project reserved the right to change the underlying implementation. Alternatives would be strbuf_reset() or declaring and releasing the strbuf within the for-loop scope. Because _reset() just rewinds the .len pointer without deallocating, you would need an extra _release() before it goes out of scope. If it is expected that the strbuf will be reused for a number of times, the length of the string each iteration uses is similar, and you will iterate the loop many times, _reset() each time and _release() to clean-up pattern would save many calls to realloc/free. Yep, that's why I suggested strbuf_reset() as an alternative (and likely would have chosen it myself). -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
Eric Sunshine sunsh...@sunshineco.com writes: Alternatives would be strbuf_reset() or declaring and releasing the strbuf within the for-loop scope. Because _reset() just rewinds the .len pointer without deallocating, you would need an extra _release() before it goes out of scope. If it is expected that the strbuf will be reused for a number of times, the length of the string each iteration uses is similar, and you will iterate the loop many times, _reset() each time and _release() to clean-up pattern would save many calls to realloc/free. Yep, that's why I suggested strbuf_reset() as an alternative (and likely would have chosen it myself). OK, then let's do that by squashing this in. builtin/reflog.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builtin/reflog.c b/builtin/reflog.c index 3080865..e9ba600 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -733,10 +733,11 @@ static int cmd_reflog_create(int argc, const char **argv, const char *prefix) if (safe_create_reflog(argv[i], err, 1)) { error(could not create reflog %s: %s, argv[i], err.buf); + strbuf_reset(err); status = 1; - strbuf_release(err); } } + strbuf_release(err); return status; } -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
On Tue, 2015-06-30 at 12:48 -0700, Junio C Hamano wrote: Eric Sunshine sunsh...@sunshineco.com writes: Alternatives would be strbuf_reset() or declaring and releasing the strbuf within the for-loop scope. Because _reset() just rewinds the .len pointer without deallocating, you would need an extra _release() before it goes out of scope. If it is expected that the strbuf will be reused for a number of times, the length of the string each iteration uses is similar, and you will iterate the loop many times, _reset() each time and _release() to clean-up pattern would save many calls to realloc/free. Yep, that's why I suggested strbuf_reset() as an alternative (and likely would have chosen it myself). OK, then let's do that by squashing this in. builtin/reflog.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) I squashed that into my repo on github: https://github.com/dturner-tw/git.git on the branch dturner/pluggable-backends-preamble -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 6/7] git-reflog: add create and exists functions
David Turner dtur...@twopensource.com writes: On Tue, 2015-06-30 at 12:48 -0700, Junio C Hamano wrote: Eric Sunshine sunsh...@sunshineco.com writes: Alternatives would be strbuf_reset() or declaring and releasing the strbuf within the for-loop scope. Because _reset() just rewinds the .len pointer without deallocating, you would need an extra _release() before it goes out of scope. If it is expected that the strbuf will be reused for a number of times, the length of the string each iteration uses is similar, and you will iterate the loop many times, _reset() each time and _release() to clean-up pattern would save many calls to realloc/free. Yep, that's why I suggested strbuf_reset() as an alternative (and likely would have chosen it myself). OK, then let's do that by squashing this in. builtin/reflog.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) I squashed that into my repo on github: I'm already deep into today's integration cycle, so it is unlikely I'd pull that before I push the result out. Please let me know if the resulting tree looks wrong (I only queued it to be squashed, haven't done the squashing two into one yet). Thanks. The 7-patch series with this fixup looks good to me. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 6/7] git-reflog: add create and exists functions
These are necessary because alternate ref backends might store reflogs somewhere other than .git/logs. Code that now directly manipulates .git/logs should instead go through git-reflog. In a moment, we will use these functions to make git stash work with alternate ref backends. Signed-off-by: David Turner dtur...@twopensource.com --- Documentation/git-reflog.txt | 10 ++ builtin/reflog.c | 75 +++- t/t1411-reflog-show.sh | 12 +++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt index 5e7908e..2bf8aa6 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.txt @@ -23,6 +23,8 @@ depending on the subcommand: [--dry-run] [--verbose] [--all | refs...] 'git reflog delete' [--rewrite] [--updateref] [--dry-run] [--verbose] ref@\{specifier\}... +'git reflog create' refs... +'git reflog exists' ref Reference logs, or reflogs, record when the tips of branches and other references were updated in the local repository. Reflogs are @@ -52,6 +54,14 @@ argument must be an _exact_ entry (e.g. `git reflog delete master@{2}`). This subcommand is also typically not used directly by end users. +The create subcommand creates a reflog for one or more refs. Most +refs (those under refs/heads, refs/remotes, and refs/tags) will +automatically have reflogs created. Other refs will not. This command +allows manual ref creation. + +The exists subcommand checks whether a ref has a reflog. It exists +with zero status if the reflog exists, and non-zero status if it does +not. OPTIONS --- diff --git a/builtin/reflog.c b/builtin/reflog.c index c2eb8ff..3080865 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -13,6 +13,10 @@ static const char reflog_expire_usage[] = git reflog expire [--expire=time] [--expire-unreachable=time] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] refs...; static const char reflog_delete_usage[] = git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] refs...; +static const char reflog_create_usage[] = +git reflog create refs...; +static const char reflog_exists_usage[] = +git reflog exists ref; static unsigned long default_reflog_expire; static unsigned long default_reflog_expire_unreachable; @@ -699,12 +703,75 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) return status; } +static int cmd_reflog_create(int argc, const char **argv, const char *prefix) +{ + int i, status = 0, start = 0; + struct strbuf err = STRBUF_INIT; + + for (i = 1; i argc; i++) { + const char *arg = argv[i]; + if (!strcmp(arg, --)) { + i++; + break; + } + else if (arg[0] == '-') + usage(reflog_create_usage); + else + break; + } + + start = i; + + if (argc - start 1) + return error(Nothing to create?); + + for (i = start; i argc; i++) { + if (check_refname_format(argv[i], REFNAME_ALLOW_ONELEVEL)) + die(invalid ref format: %s, argv[i]); + } + for (i = start; i argc; i++) { + if (safe_create_reflog(argv[i], err, 1)) { + error(could not create reflog %s: %s, argv[i], + err.buf); + status = 1; + strbuf_release(err); + } + } + return status; +} + +static int cmd_reflog_exists(int argc, const char **argv, const char *prefix) +{ + int i, start = 0; + + for (i = 1; i argc; i++) { + const char *arg = argv[i]; + if (!strcmp(arg, --)) { + i++; + break; + } + else if (arg[0] == '-') + usage(reflog_exists_usage); + else + break; + } + + start = i; + + if (argc - start != 1) + usage(reflog_exists_usage); + + if (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL)) + die(invalid ref format: %s, argv[start]); + return !reflog_exists(argv[start]); +} + /* * main reflog */ static const char reflog_usage[] = -git reflog [ show | expire | delete ]; +git reflog [ show | expire | delete | create | exists ]; int cmd_reflog(int argc, const char **argv, const char *prefix) { @@ -724,5 +791,11 @@ int cmd_reflog(int argc, const char **argv, const char *prefix) if (!strcmp(argv[1], delete)) return cmd_reflog_delete(argc - 1, argv + 1, prefix); + if (!strcmp(argv[1], create)) + return cmd_reflog_create(argc - 1, argv + 1, prefix); + + if (!strcmp(argv[1], exists)) +