refs.c: Refactor code for mapping between shorthand names and full refnames

This patch is in preparation for extending the ways in which we expand
shorthand names into full refnames, and shorten full refnames into
unambiguous shorthand names.

We collect the logic for performing the expansion and shortening into two
functions: refname_expand() and refname_shorten(). refname_expand() takes
a shorthand name, and a pattern containing a wildcard (more on those
below), and substitutes the shorthand name for the wildcard. The result
is written into a strbuf provided by the caller. Correspondingly,
refname_shorten() takes a full refname and matches it against the given
pattern, extracting the portion of the full refname that matches the
pattern wildcard. The resulting shorthand name is written into a strbuf
provided by the caller.

The refname_expand() function no longer uses mkpath()/mksnpath() to
perform the pattern expansion. Instead, it uses strbuf_expand(), which
removes the need for using fixed-length buffers from the code. This also
means we no longer call cleanup_path() on the resulting refs, but AFAICS,
this is not really needed anyway (also it breaks no existing tests).

Since the pattern expansion is now done by strbuf_expand(), the syntax of
the pattern wildcard must change as well. Whereas a pattern used to look
like this:

    "refs/remotes/%.*s/HEAD"

it now looks like this:

    "refs/remotes/%*/HEAD"

where the "%*" wildcard is meant to be read as "the full shorthand name".
More wildcards will be added by future patches that require more complex
wildcard matching.

The list of patterns has been renamed from "ref_rev_parse_rules" to
"refname_patterns" (which should be more descriptive), and it has lost
the NULL terminator, which is no longer needed, since all iterations of
the list now uses ARRAY_SIZE(refname_patterns) to end iteration, instead
of testing each member against NULL.

Furthermore, refname_match() used to take the list of patterns as an
argument, but since all callers pass the one and only pattern list, we
can drop the argument altogether, and use refname_patterns directly in
refname_match(). This also enables us to make the pattern list static.

The code for shortening full refnames into shorthands, has been adjusted
to deal with the new "%*" patterns. It now uses strbuf_split_str() with
the '%' as terminator, to split the prefix part from the suffix part.
Then - as before - it matches the prefix from the start of the given
refname and the suffix from the end of the refname. If both matches are
successful, the middle portion is extracted as the resulting shorthand
name.

The end result of this refactoring is equivalent in behavior to the
existing code, but makes it easier for future patches to adjust how
expansion and shortening happens.

All of the existing users of ref_rev_parse_rules are converted to
refname_patterns by this patch, so ref_rev_parse_rules is removed
as well.

Signed-off-by: Johan Herland <johan@herland.net>
remote: Reject remote names containing '/'

Although we definitely support and encourage use of multi-level branch
names, we have never conciously tried to give support for multi-level
remote names. Currently, they are allowed, but there is no evidence that
they are commonly used.

Now, they do provide a source of problems when trying to expand the
"$nick/$name" shorthand notation (where $nick matches a remote name)
into a full refname. Consider the shorthand "foo/bar/baz": Does this
parse as $nick = foo, $name = bar/baz, or $nick = foo/bar, $name = baz?

Since we need to be unambiguous about these things, we hereby declare
that a remote name shall never contain a '/' character, and that the
only correct way to parse "foo/bar/baz" is $nick = foo, $name = bar/baz.

This patch teaches 'git remote' to reject remote names with slashes,
and adds tests verifying this.

Signed-off-by: Johan Herland <johan@herland.net>
refs.c: Add support for expanding/shortening refs in refs/peers/*

This patch adds the following patterns for expanding/shortening refs:

  "refs/peers/%*"
  "refs/peers/%1/tags/%*"
  "refs/peers/%1/heads/%*"

These allow shorthand names like "origin/master" to expand to refs in
the refs/peers/* hierarchy (in this case, the likely expansion would be
by the middle rule above, resulting in "refs/peers/origin/heads/master").

To accomplish this, we have added the new "%1" wildcard which shall
expand into the first component (i.e. up to the first '/') of the given
shorthand. The other wildcard ("%*") shall then expand into the remainder
of the shorthand (i.e. following the first '/').

Correspondingly, when shortening according to a pattern with "%1", a
single component (not including any '/' character) shall be extracted
from that point in the given refname, and shall be added to the resulting
shorthand, with a trailing '/'. Then, when hitting the "%*", the
remainder of the given refname (modulo a trailing match in the pattern)
shall be extracted and appended to the portion previously extracted by
the "%1" wildcard.

The need to split the "$remote/$ref" into its $remote and $ref parts is
the reason why multi-level remote names will no longer work (and hence
were disallowed in the previous patch). A testcase demonstrating how
multi-level remote names fail is therefore included in this patch.

Signed-off-by: Johan Herland <johan@herland.net>
t7900: Test git branch -r/-a output w/remote-tracking branches in refs/peers/*

These tests will be made to pass by subsequent patches.

Signed-off-by: Johan Herland <johan@herland.net>
t3203: Add testcase for fix in 1603ade81352a526ccb206f41ff81ecbc855df2d

This adds a testcase for some behavior that I very nearly broke while
refactoring some stuff in builtin/branch.c.

Signed-off-by: Johan Herland <johan@herland.net>
builtin/branch.c: Refactor ref_item.name and .dest into strbufs

In preparation of a future patch which reorganizes how the display of the
ref_list is done.

Signed-off-by: Johan Herland <johan@herland.net>
builtin/branch.c: Refactor "remotes/" prepending to remote-tracking branches

When running "git branch -a" (instead of "git branch -r"), we prefix the
remote-tracking branches with "remotes/" to allow the user to more easily
tell them apart from the local branches.

The code that prepended "remotes/" to remote-tracking branches was
located in print_ref_item(), while the code that adjusted the
ref_item.width (to account for the prepended "remotes/") was located in
append_ref().

This code moves the prepending of "remotes/" up into append_ref(), which
is a nice cleanup of the code, as well as a preparation for changing the
logic when remote-tracking branches start showing up in refs/peers/*.

Signed-off-by: Johan Herland <johan@herland.net>
branch: Fix display of remote branches in refs/peers/*

The current branch display code assumes all remote-tracking branches live
inside refs/remotes/*, and that their appropriate shorthand names can be
retrieved by simply stripping off the "refs/remotes/" prefix.

When we add remote-tracking branches in refs/peers/$remote/heads/*, the
code must not only be taught how to list refs from the new location, but
also how to appropriately derive shorthand names for the remote-tracking
branches there (instead of stripping off a hardcoded prefix, we must use
the refname_shorten() function introduced in an earlier patch.)

There is already a good set of tests for the expected output from git
branch, and this patch does not break any of them. However, we do fix
the two tests with remote-tracking branches in refs/peers/* introduced
in a previous patch.

Signed-off-by: Johan Herland <johan@herland.net>