Junio C Hamano <gitster@xxxxxxxxx> writes: >> I don't think there is any need to prepare it upon my 4d03f955, >> though. I'd think it could simply replace it. > > Yeah, it ended up that way, it seems. Still it needs a bit of doc > updates to balance the description. So here is what I have now on 'pu'. Clearly not a 2.15 material yet. -- >8 -- Subject: [PATCH] check-ref-format: --branch cannot grok @{-1} outside a repository "git check-ref-format --branch $name" feature was originally introduced (and was advertised) as a way for scripts to take any end-user supplied string (like "master", "@{-1}" etc.) and see if that is usable when Git expects to see a branch name, and also obtain the concrete branch name that the at-mark magic expands to. When the user asks to interpret a branch name like "@{-1}", we have to dig the answer out of the HEAD reflog. We can obviously only do that if we have a repository, and indeed, running it outside a repository causes us to hit a BUG(). Let's disable the "expand @{-n}" half of the feature when it is run outside a repository, but keep the feature to check the syntax of a proposed branch name, as "git check-ref-format --branch $name" can be stricter than "git check-ref-format refs/heads/$name", and Porcelain scripts need to have a way to check a given name against the stricter rule. Helped-by: Jeff King <peff@xxxxxxxx> Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- Documentation/git-check-ref-format.txt | 9 ++++++++- builtin/check-ref-format.c | 15 ++++++++++++--- cache.h | 14 ++++++++++++++ sha1_name.c | 22 +++++++++++++++++++--- strbuf.h | 6 ++++++ t/t1402-check-ref-format.sh | 12 ++++++++++++ 6 files changed, 71 insertions(+), 7 deletions(-) diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt index 92777cef25..cf0a0b7df2 100644 --- a/Documentation/git-check-ref-format.txt +++ b/Documentation/git-check-ref-format.txt @@ -77,7 +77,14 @@ reference name expressions (see linkgit:gitrevisions[7]): . at-open-brace `@{` is used as a notation to access a reflog entry. -With the `--branch` option, it expands the ``previous branch syntax'' +With the `--branch` option, the command takes a name and checks if +it can be used as a valid branch name (e.g. when creating a new +branch). The rule `git check-ref-format --branch $name` implements +may be stricter than what `git check-ref-format refs/heads/$name` +says (e.g. a dash may appear at the beginning of a ref component, +but it is explicitly forbidden at the beginning of a branch name). +When run with `--branch` option in a repository, the input is first +expanded for the ``previous branch syntax'' `@{-n}`. For example, `@{-1}` is a way to refer the last branch you were on. This option should be used by porcelains to accept this syntax anywhere a branch name is expected, so they can act as if you diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c index eac499450f..4e62852089 100644 --- a/builtin/check-ref-format.c +++ b/builtin/check-ref-format.c @@ -38,13 +38,22 @@ static char *collapse_slashes(const char *refname) static int check_ref_format_branch(const char *arg) { + int nongit, malformed; struct strbuf sb = STRBUF_INIT; - int nongit; + const char *name = arg; setup_git_directory_gently(&nongit); - if (strbuf_check_branch_ref(&sb, arg)) + + if (!nongit) + malformed = (strbuf_check_branch_ref(&sb, arg) || + !skip_prefix(sb.buf, "refs/heads/", &name)); + else + malformed = check_branch_ref_format(arg); + + if (malformed) die("'%s' is not a valid branch name", arg); - printf("%s\n", sb.buf + 11); + printf("%s\n", name); + strbuf_release(&sb); return 0; } diff --git a/cache.h b/cache.h index 52b91f5b64..3815925122 100644 --- a/cache.h +++ b/cache.h @@ -1444,6 +1444,20 @@ extern int parse_oid_hex(const char *hex, struct object_id *oid, const char **en #define INTERPRET_BRANCH_HEAD (1<<2) extern int interpret_branch_name(const char *str, int len, struct strbuf *, unsigned allowed); + +/* + * NEEDSWORK: declare strbuf_branchname() and strbuf_check_branch_ref() + * here, not in strbuf.h + */ + +/* + * Check if a 'name' is suitable to be used as a branch name; this can + * be and is stricter than what check_refname_format() returns for a + * string that is a concatenation of "name" after "refs/heads/"; a + * name that begins with "-" is not allowed, for example. + */ +extern int check_branch_ref_format(const char *name); + extern int get_oid_mb(const char *str, struct object_id *oid); extern int validate_headref(const char *ref); diff --git a/sha1_name.c b/sha1_name.c index 5e2ec37b65..c95080258f 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -1319,15 +1319,31 @@ void strbuf_branchname(struct strbuf *sb, const char *name, unsigned allowed) strbuf_add(sb, name + used, len - used); } -int strbuf_check_branch_ref(struct strbuf *sb, const char *name) +static int strbuf_check_branch_ref_format(struct strbuf *sb) { - strbuf_branchname(sb, name, INTERPRET_BRANCH_LOCAL); - if (name[0] == '-') + if (*sb->buf == '-') return -1; strbuf_splice(sb, 0, 0, "refs/heads/", 11); return check_refname_format(sb->buf, 0); } +int check_branch_ref_format(const char *name) +{ + struct strbuf sb = STRBUF_INIT; + int result; + + strbuf_addstr(&sb, name); + result = strbuf_check_branch_ref_format(&sb); + strbuf_release(&sb); + return result; +} + +int strbuf_check_branch_ref(struct strbuf *sb, const char *name) +{ + strbuf_branchname(sb, name, INTERPRET_BRANCH_LOCAL); + return strbuf_check_branch_ref_format(sb); +} + /* * This is like "get_sha1_basic()", except it allows "sha1 expressions", * notably "xyz^" for "parent of xyz" diff --git a/strbuf.h b/strbuf.h index d785258649..3da95685b2 100644 --- a/strbuf.h +++ b/strbuf.h @@ -568,6 +568,12 @@ static inline void strbuf_complete_line(struct strbuf *sb) strbuf_complete(sb, '\n'); } +/* + * NEEDSWORK: the following two functions should not be in this file; + * these are about refnames, and should be declared next to + * interpret_branch_name() in cache.h + */ + /* * Copy "name" to "sb", expanding any special @-marks as handled by * interpret_branch_name(). The result is a non-qualified branch name diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index 0790edf60d..2ddefb4bd1 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -161,6 +161,18 @@ test_expect_success 'check-ref-format --branch from subdir' ' test "$refname" = "$sha1" ' +test_expect_success 'check-ref-format --branch @{-1} from non-repo' ' + test_must_fail nongit git check-ref-format --branch @{-1} +' + +test_expect_success 'check-ref-format --branch master in non-repo' ' + nongit git check-ref-format --branch master +' + +test_expect_success 'check-ref-format --branch -naster in repo' ' + test_must_fail git check-ref-format --branch -naster +' + valid_ref_normalized() { prereq= case $1 in -- 2.15.0-rc1-178-geb01ff2fe8