2007-07-15 07:14:45 +08:00
|
|
|
#include "builtin.h"
|
Honor core.precomposeUnicode in more places
On Mac's HFS where git sets core.precomposeUnicode to true automatically
by git init/clone, when a user creates a simple unicode refname (in NFC
format) such as españa:
$ git branch españa
different commands would display the branch name differently. For
example, git branch, git log --decorate, and git fast-export all used
65 73 70 61 c3 b1 61 (or "espa\xc3\xb1a")
(NFC form) while show-ref would use
65 73 70 61 6e cc 83 61 (or "espan\xcc\x83a")
(NFD form). A stress test for git filter-repo was tripped up by this
inconsistency, though digging in I found that the problems could
compound; for example, if the user ran
$ git pack-refs --all
and then tried to check out the branch, they would be met with:
$ git checkout españa
error: pathspec 'españa' did not match any file(s) known to git
$ git checkout españa --
fatal: invalid reference: españa
$ git branch
españa
* master
Note that the user could run the `git branch` command first and copy and
paste the `españa` portion of the output and still see the same two
errors. Also, if the user added --no-prune to the pack-refs command,
then they would see three branches: master, españa, and españa (those
last two are NFC vs. NFD forms, even if they render the same).
Further, if the user had the `españa` branch checked out before
running `git pack-refs --all`, the user would be greeted with (note
that I'm trimming trailing output with an ellipsis):
$ git rev-parse HEAD
fatal: ambiguous argument 'HEAD': unknown revision or path...
$ git status
On branch españa
No commits yet...
Or worse, if the user didn't check this stuff first, running `git
commit` will create a new commit with all changes of all of history
being squashed into it.
In addition to pack-refs, one could also get into this state with
upload-pack or anything that calls either pack-refs or upload-pack (e.g.
gc or clone).
Add code in a few places (pack-refs, show-ref, upload-pack) to check and
honor the setting of core.precomposeUnicode to avoid these bugs.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-04-25 22:58:54 +08:00
|
|
|
#include "config.h"
|
2023-03-21 14:25:54 +08:00
|
|
|
#include "gettext.h"
|
2023-02-24 08:09:27 +08:00
|
|
|
#include "hex.h"
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
#include "refs.h"
|
2023-04-11 15:41:49 +08:00
|
|
|
#include "object-name.h"
|
2023-05-16 14:34:06 +08:00
|
|
|
#include "object-store-ll.h"
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
#include "object.h"
|
|
|
|
#include "tag.h"
|
2008-07-22 02:03:49 +08:00
|
|
|
#include "string-list.h"
|
2009-06-21 12:40:46 +08:00
|
|
|
#include "parse-options.h"
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
|
2009-06-21 12:40:46 +08:00
|
|
|
static const char * const show_ref_usage[] = {
|
2022-10-13 23:39:02 +08:00
|
|
|
N_("git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference]\n"
|
|
|
|
" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n"
|
|
|
|
" [--heads] [--] [<pattern>...]"),
|
usage: do not insist that standard input must come from a file
The synopsys text and the usage string of subcommands that read list
of things from the standard input are often shown like this:
git gostak [--distim] < <list-of-doshes>
This is problematic in a number of ways:
* The way to use these commands is more often to feed them the
output from another command, not feed them from a file.
* Manual pages outside Git, commands that operate on the data read
from the standard input, e.g "sort", "grep", "sed", etc., are not
described with such a "< redirection-from-file" in their synopsys
text. Our doing so introduces inconsistency.
* We do not insist on where the output should go, by saying
git gostak [--distim] < <list-of-doshes> > <output>
* As it is our convention to enclose placeholders inside <braket>,
the redirection operator followed by a placeholder filename
becomes very hard to read, both in the documentation and in the
help text.
Let's clean them all up, after making sure that the documentation
clearly describes the modes that take information from the standard
input and what kind of things are expected on the input.
[jc: stole example for fmt-merge-msg from Jonathan]
Helped-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-10-17 02:27:42 +08:00
|
|
|
N_("git show-ref --exclude-existing[=<pattern>]"),
|
2009-06-21 12:40:46 +08:00
|
|
|
NULL
|
|
|
|
};
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
|
2023-10-31 16:16:38 +08:00
|
|
|
struct show_one_options {
|
|
|
|
int quiet;
|
|
|
|
int hash_only;
|
|
|
|
int abbrev;
|
|
|
|
int deref_tags;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void show_one(const struct show_one_options *opts,
|
|
|
|
const char *refname, const struct object_id *oid)
|
2006-12-18 11:27:49 +08:00
|
|
|
{
|
2017-01-24 02:00:56 +08:00
|
|
|
const char *hex;
|
|
|
|
struct object_id peeled;
|
|
|
|
|
2023-03-28 21:58:50 +08:00
|
|
|
if (!repo_has_object_file(the_repository, oid))
|
2017-01-24 02:00:58 +08:00
|
|
|
die("git show-ref: bad ref %s (%s)", refname,
|
|
|
|
oid_to_hex(oid));
|
|
|
|
|
2023-10-31 16:16:38 +08:00
|
|
|
if (opts->quiet)
|
2017-01-24 02:00:57 +08:00
|
|
|
return;
|
|
|
|
|
2023-10-31 16:16:38 +08:00
|
|
|
hex = repo_find_unique_abbrev(the_repository, oid, opts->abbrev);
|
|
|
|
if (opts->hash_only)
|
2006-12-18 11:27:49 +08:00
|
|
|
printf("%s\n", hex);
|
|
|
|
else
|
|
|
|
printf("%s %s\n", hex, refname);
|
2017-01-24 02:00:56 +08:00
|
|
|
|
2023-10-31 16:16:38 +08:00
|
|
|
if (!opts->deref_tags)
|
2017-01-24 02:00:56 +08:00
|
|
|
return;
|
|
|
|
|
refs: switch peel_ref() to peel_iterated_oid()
The peel_ref() interface is confusing and error-prone:
- it's typically used by ref iteration callbacks that have both a
refname and oid. But since they pass only the refname, we may load
the ref value from the filesystem again. This is inefficient, but
also means we are open to a race if somebody simultaneously updates
the ref. E.g., this:
int some_ref_cb(const char *refname, const struct object_id *oid, ...)
{
if (!peel_ref(refname, &peeled))
printf("%s peels to %s",
oid_to_hex(oid), oid_to_hex(&peeled);
}
could print nonsense. It is correct to say "refname peels to..."
(you may see the "before" value or the "after" value, either of
which is consistent), but mentioning both oids may be mixing
before/after values.
Worse, whether this is possible depends on whether the optimization
to read from the current iterator value kicks in. So it is actually
not possible with:
for_each_ref(some_ref_cb);
but it _is_ possible with:
head_ref(some_ref_cb);
which does not use the iterator mechanism (though in practice, HEAD
should never peel to anything, so this may not be triggerable).
- it must take a fully-qualified refname for the read_ref_full() code
path to work. Yet we routinely pass it partial refnames from
callbacks to for_each_tag_ref(), etc. This happens to work when
iterating because there we do not call read_ref_full() at all, and
only use the passed refname to check if it is the same as the
iterator. But the requirements for the function parameters are quite
unclear.
Instead of taking a refname, let's instead take an oid. That fixes both
problems. It's a little funny for a "ref" function not to involve refs
at all. The key thing is that it's optimizing under the hood based on
having access to the ref iterator. So let's change the name to make it
clear why you'd want this function versus just peel_object().
There are two other directions I considered but rejected:
- we could pass the peel information into the each_ref_fn callback.
However, we don't know if the caller actually wants it or not. For
packed-refs, providing it is essentially free. But for loose refs,
we actually have to peel the object, which would be wasteful in most
cases. We could likewise pass in a flag to the callback indicating
whether the peeled information is known, but that complicates those
callbacks, as they then have to decide whether to manually peel
themselves. Plus it requires changing the interface of every
callback, whether they care about peeling or not, and there are many
of them.
- we could make a function to return the peeled value of the current
iterated ref (computing it if necessary), and BUG() otherwise. I.e.:
int peel_current_iterated_ref(struct object_id *out);
Each of the current callers is an each_ref_fn callback, so they'd
mostly be happy. But:
- we use those callbacks with functions like head_ref(), which do
not use the iteration code. So we'd need to handle the fallback
case there, anyway.
- it's possible that a caller would want to call into generic code
that sometimes is used during iteration and sometimes not. This
encapsulates the logic to do the fast thing when possible, and
fallback when necessary.
The implementation is mostly obvious, but I want to call out a few
things in the patch:
- the test-tool coverage for peel_ref() is now meaningless, as it all
collapses to a single peel_object() call (arguably they were pretty
uninteresting before; the tricky part of that function is the
fast-path we see during iteration, but these calls didn't trigger
that). I've just dropped it entirely, though note that some other
tests relied on the tags we created; I've moved that creation to the
tests where it matters.
- we no longer need to take a ref_store parameter, since we'd never
look up a ref now. We do still rely on a global "current iterator"
variable which _could_ be kept per-ref-store. But in practice this
is only useful if there are multiple recursive iterations, at which
point the more appropriate solution is probably a stack of
iterators. No caller used the actual ref-store parameter anyway
(they all call the wrapper that passes the_repository).
- the original only kicked in the optimization when the "refname"
pointer matched (i.e., not string comparison). We do likewise with
the "oid" parameter here, but fall back to doing an actual oideq()
call. This in theory lets us kick in the optimization more often,
though in practice no current caller cares. It should never be
wrong, though (peeling is a property of an object, so two refs
pointing to the same object would peel identically).
- the original took care not to touch the peeled out-parameter unless
we found something to put in it. But no caller cares about this, and
anyway, it is enforced by peel_object() itself (and even in the
optimized iterator case, that's where we eventually end up). We can
shorten the code and avoid an extra copy by just passing the
out-parameter through the stack.
Signed-off-by: Jeff King <peff@peff.net>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-01-21 03:44:43 +08:00
|
|
|
if (!peel_iterated_oid(oid, &peeled)) {
|
2023-10-31 16:16:38 +08:00
|
|
|
hex = repo_find_unique_abbrev(the_repository, &peeled, opts->abbrev);
|
2017-01-24 02:00:56 +08:00
|
|
|
printf("%s %s^{}\n", hex, refname);
|
|
|
|
}
|
2006-12-18 11:27:49 +08:00
|
|
|
}
|
|
|
|
|
2023-10-31 16:16:12 +08:00
|
|
|
struct show_ref_data {
|
2023-10-31 16:16:38 +08:00
|
|
|
const struct show_one_options *show_one_opts;
|
2023-10-31 16:16:12 +08:00
|
|
|
const char **patterns;
|
2023-10-31 16:16:33 +08:00
|
|
|
int found_match;
|
2023-10-31 16:16:42 +08:00
|
|
|
int show_head;
|
2023-10-31 16:16:12 +08:00
|
|
|
};
|
|
|
|
|
2015-05-26 02:38:51 +08:00
|
|
|
static int show_ref(const char *refname, const struct object_id *oid,
|
2023-10-31 16:16:12 +08:00
|
|
|
int flag UNUSED, void *cbdata)
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
{
|
2023-10-31 16:16:12 +08:00
|
|
|
struct show_ref_data *data = cbdata;
|
|
|
|
|
2023-10-31 16:16:42 +08:00
|
|
|
if (data->show_head && !strcmp(refname, "HEAD"))
|
2013-07-17 08:05:14 +08:00
|
|
|
goto match;
|
|
|
|
|
2023-10-31 16:16:12 +08:00
|
|
|
if (data->patterns) {
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
int reflen = strlen(refname);
|
2023-10-31 16:16:12 +08:00
|
|
|
const char **p = data->patterns, *m;
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
while ((m = *p++) != NULL) {
|
|
|
|
int len = strlen(m);
|
|
|
|
if (len > reflen)
|
|
|
|
continue;
|
|
|
|
if (memcmp(m, refname + reflen - len, len))
|
|
|
|
continue;
|
|
|
|
if (len == reflen)
|
|
|
|
goto match;
|
|
|
|
if (refname[reflen - len - 1] == '/')
|
|
|
|
goto match;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
match:
|
2023-10-31 16:16:33 +08:00
|
|
|
data->found_match++;
|
2006-11-20 05:22:44 +08:00
|
|
|
|
2023-10-31 16:16:38 +08:00
|
|
|
show_one(data->show_one_opts, refname, oid);
|
2006-11-20 05:22:44 +08:00
|
|
|
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-19 18:08:32 +08:00
|
|
|
static int add_existing(const char *refname,
|
2022-08-26 01:09:48 +08:00
|
|
|
const struct object_id *oid UNUSED,
|
|
|
|
int flag UNUSED, void *cbdata)
|
2006-12-18 09:57:19 +08:00
|
|
|
{
|
2008-07-22 02:03:49 +08:00
|
|
|
struct string_list *list = (struct string_list *)cbdata;
|
2010-06-26 07:41:35 +08:00
|
|
|
string_list_insert(list, refname);
|
2006-12-18 09:57:19 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-10-31 16:16:29 +08:00
|
|
|
struct exclude_existing_options {
|
|
|
|
/*
|
|
|
|
* We need an explicit `enabled` field because it is perfectly valid
|
|
|
|
* for `pattern` to be `NULL` even if `--exclude-existing` was given.
|
|
|
|
*/
|
|
|
|
int enabled;
|
|
|
|
const char *pattern;
|
|
|
|
};
|
|
|
|
|
2006-12-18 09:57:19 +08:00
|
|
|
/*
|
|
|
|
* read "^(?:<anything>\s)?<refname>(?:\^\{\})?$" from the standard input,
|
|
|
|
* and
|
|
|
|
* (1) strip "^{}" at the end of line if any;
|
|
|
|
* (2) ignore if match is provided and does not head-match refname;
|
|
|
|
* (3) warn if refname is not a well-formed refname and skip;
|
|
|
|
* (4) ignore if refname is a ref that exists in the local repository;
|
|
|
|
* (5) otherwise output the line.
|
|
|
|
*/
|
2023-10-31 16:16:29 +08:00
|
|
|
static int cmd_show_ref__exclude_existing(const struct exclude_existing_options *opts)
|
2006-12-18 09:57:19 +08:00
|
|
|
{
|
2023-10-31 16:16:21 +08:00
|
|
|
struct string_list existing_refs = STRING_LIST_INIT_DUP;
|
2006-12-18 09:57:19 +08:00
|
|
|
char buf[1024];
|
2023-10-31 16:16:29 +08:00
|
|
|
int patternlen = opts->pattern ? strlen(opts->pattern) : 0;
|
2006-12-18 09:57:19 +08:00
|
|
|
|
2015-05-26 02:38:51 +08:00
|
|
|
for_each_ref(add_existing, &existing_refs);
|
2006-12-18 09:57:19 +08:00
|
|
|
while (fgets(buf, sizeof(buf), stdin)) {
|
|
|
|
char *ref;
|
2006-12-19 05:33:47 +08:00
|
|
|
int len = strlen(buf);
|
|
|
|
|
2006-12-18 09:57:19 +08:00
|
|
|
if (len > 0 && buf[len - 1] == '\n')
|
|
|
|
buf[--len] = '\0';
|
2006-12-19 05:33:47 +08:00
|
|
|
if (3 <= len && !strcmp(buf + len - 3, "^{}")) {
|
2006-12-18 09:57:19 +08:00
|
|
|
len -= 3;
|
|
|
|
buf[len] = '\0';
|
|
|
|
}
|
|
|
|
for (ref = buf + len; buf < ref; ref--)
|
|
|
|
if (isspace(ref[-1]))
|
|
|
|
break;
|
2023-10-31 16:16:29 +08:00
|
|
|
if (opts->pattern) {
|
2006-12-18 09:57:19 +08:00
|
|
|
int reflen = buf + len - ref;
|
2023-10-31 16:16:29 +08:00
|
|
|
if (reflen < patternlen)
|
2006-12-18 09:57:19 +08:00
|
|
|
continue;
|
2023-10-31 16:16:29 +08:00
|
|
|
if (strncmp(ref, opts->pattern, patternlen))
|
2006-12-18 09:57:19 +08:00
|
|
|
continue;
|
|
|
|
}
|
2011-09-16 05:10:25 +08:00
|
|
|
if (check_refname_format(ref, 0)) {
|
2009-03-24 09:09:16 +08:00
|
|
|
warning("ref '%s' ignored", ref);
|
2006-12-18 09:57:19 +08:00
|
|
|
continue;
|
|
|
|
}
|
2008-07-22 02:03:49 +08:00
|
|
|
if (!string_list_has_string(&existing_refs, ref)) {
|
2006-12-18 09:57:19 +08:00
|
|
|
printf("%s\n", buf);
|
|
|
|
}
|
|
|
|
}
|
2023-10-31 16:16:21 +08:00
|
|
|
|
|
|
|
string_list_clear(&existing_refs, 0);
|
2006-12-18 09:57:19 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-10-31 16:16:38 +08:00
|
|
|
static int cmd_show_ref__verify(const struct show_one_options *show_one_opts,
|
|
|
|
const char **refs)
|
2023-10-31 16:16:17 +08:00
|
|
|
{
|
|
|
|
if (!refs || !*refs)
|
|
|
|
die("--verify requires a reference");
|
|
|
|
|
|
|
|
while (*refs) {
|
|
|
|
struct object_id oid;
|
|
|
|
|
|
|
|
if ((starts_with(*refs, "refs/") || !strcmp(*refs, "HEAD")) &&
|
|
|
|
!read_ref(*refs, &oid)) {
|
2023-10-31 16:16:38 +08:00
|
|
|
show_one(show_one_opts, *refs, &oid);
|
2023-10-31 16:16:17 +08:00
|
|
|
}
|
2023-10-31 16:16:38 +08:00
|
|
|
else if (!show_one_opts->quiet)
|
2023-10-31 16:16:17 +08:00
|
|
|
die("'%s' - not a valid ref", *refs);
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
refs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-10-31 16:16:42 +08:00
|
|
|
struct patterns_options {
|
|
|
|
int show_head;
|
|
|
|
int heads_only;
|
|
|
|
int tags_only;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int cmd_show_ref__patterns(const struct patterns_options *opts,
|
|
|
|
const struct show_one_options *show_one_opts,
|
2023-10-31 16:16:38 +08:00
|
|
|
const char **patterns)
|
2023-10-31 16:16:17 +08:00
|
|
|
{
|
2023-10-31 16:16:38 +08:00
|
|
|
struct show_ref_data show_ref_data = {
|
|
|
|
.show_one_opts = show_one_opts,
|
2023-10-31 16:16:42 +08:00
|
|
|
.show_head = opts->show_head,
|
2023-10-31 16:16:38 +08:00
|
|
|
};
|
2023-10-31 16:16:17 +08:00
|
|
|
|
|
|
|
if (patterns && *patterns)
|
|
|
|
show_ref_data.patterns = patterns;
|
|
|
|
|
2023-10-31 16:16:42 +08:00
|
|
|
if (opts->show_head)
|
2023-10-31 16:16:17 +08:00
|
|
|
head_ref(show_ref, &show_ref_data);
|
2023-10-31 16:16:42 +08:00
|
|
|
if (opts->heads_only || opts->tags_only) {
|
|
|
|
if (opts->heads_only)
|
2023-10-31 16:16:17 +08:00
|
|
|
for_each_fullref_in("refs/heads/", show_ref, &show_ref_data);
|
2023-10-31 16:16:42 +08:00
|
|
|
if (opts->tags_only)
|
2023-10-31 16:16:17 +08:00
|
|
|
for_each_fullref_in("refs/tags/", show_ref, &show_ref_data);
|
|
|
|
} else {
|
|
|
|
for_each_ref(show_ref, &show_ref_data);
|
|
|
|
}
|
2023-10-31 16:16:33 +08:00
|
|
|
if (!show_ref_data.found_match)
|
2023-10-31 16:16:17 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-06-21 12:40:46 +08:00
|
|
|
static int hash_callback(const struct option *opt, const char *arg, int unset)
|
|
|
|
{
|
2023-10-31 16:16:38 +08:00
|
|
|
struct show_one_options *opts = opt->value;
|
|
|
|
struct option abbrev_opt = *opt;
|
|
|
|
|
|
|
|
opts->hash_only = 1;
|
2009-06-21 12:40:46 +08:00
|
|
|
/* Use full length SHA1 if no argument */
|
|
|
|
if (!arg)
|
|
|
|
return 0;
|
2023-10-31 16:16:38 +08:00
|
|
|
|
|
|
|
abbrev_opt.value = &opts->abbrev;
|
|
|
|
return parse_opt_abbrev_cb(&abbrev_opt, arg, unset);
|
2009-06-21 12:40:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int exclude_existing_callback(const struct option *opt, const char *arg,
|
|
|
|
int unset)
|
|
|
|
{
|
2023-10-31 16:16:29 +08:00
|
|
|
struct exclude_existing_options *opts = opt->value;
|
assert NOARG/NONEG behavior of parse-options callbacks
When we define a parse-options callback, the flags we put in the option
struct must match what the callback expects. For example, a callback
which does not handle the "unset" parameter should only be used with
PARSE_OPT_NONEG. But since the callback and the option struct are not
defined next to each other, it's easy to get this wrong (as earlier
patches in this series show).
Fortunately, the compiler can help us here: compiling with
-Wunused-parameters can show us which callbacks ignore their "unset"
parameters (and likewise, ones that ignore "arg" expect to be triggered
with PARSE_OPT_NOARG).
But after we've inspected a callback and determined that all of its
callers use the right flags, what do we do next? We'd like to silence
the compiler warning, but do so in a way that will catch any wrong calls
in the future.
We can do that by actually checking those variables and asserting that
they match our expectations. Because this is such a common pattern,
we'll introduce some helper macros. The resulting messages aren't
as descriptive as we could make them, but the file/line information from
BUG() is enough to identify the problem (and anyway, the point is that
these should never be seen).
Each of the annotated callbacks in this patch triggers
-Wunused-parameters, and was manually inspected to make sure all callers
use the correct options (so none of these BUGs should be triggerable).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-05 14:45:42 +08:00
|
|
|
BUG_ON_OPT_NEG(unset);
|
2023-10-31 16:16:29 +08:00
|
|
|
opts->enabled = 1;
|
|
|
|
opts->pattern = arg;
|
2009-06-21 12:40:46 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
int cmd_show_ref(int argc, const char **argv, const char *prefix)
|
|
|
|
{
|
2023-10-31 16:16:29 +08:00
|
|
|
struct exclude_existing_options exclude_existing_opts = {0};
|
2023-10-31 16:16:42 +08:00
|
|
|
struct patterns_options patterns_opts = {0};
|
2023-10-31 16:16:38 +08:00
|
|
|
struct show_one_options show_one_opts = {0};
|
2023-10-31 16:16:42 +08:00
|
|
|
int verify = 0;
|
2023-10-31 16:16:29 +08:00
|
|
|
const struct option show_ref_options[] = {
|
2023-10-31 16:16:42 +08:00
|
|
|
OPT_BOOL(0, "tags", &patterns_opts.tags_only, N_("only show tags (can be combined with heads)")),
|
|
|
|
OPT_BOOL(0, "heads", &patterns_opts.heads_only, N_("only show heads (can be combined with tags)")),
|
2023-10-31 16:16:29 +08:00
|
|
|
OPT_BOOL(0, "verify", &verify, N_("stricter reference checking, "
|
|
|
|
"requires exact ref path")),
|
2023-10-31 16:16:42 +08:00
|
|
|
OPT_HIDDEN_BOOL('h', NULL, &patterns_opts.show_head,
|
2023-10-31 16:16:29 +08:00
|
|
|
N_("show the HEAD reference, even if it would be filtered out")),
|
2023-10-31 16:16:42 +08:00
|
|
|
OPT_BOOL(0, "head", &patterns_opts.show_head,
|
2023-10-31 16:16:29 +08:00
|
|
|
N_("show the HEAD reference, even if it would be filtered out")),
|
2023-10-31 16:16:38 +08:00
|
|
|
OPT_BOOL('d', "dereference", &show_one_opts.deref_tags,
|
2023-10-31 16:16:29 +08:00
|
|
|
N_("dereference tags into object IDs")),
|
2023-10-31 16:16:38 +08:00
|
|
|
OPT_CALLBACK_F('s', "hash", &show_one_opts, N_("n"),
|
2023-10-31 16:16:29 +08:00
|
|
|
N_("only show SHA1 hash using <n> digits"),
|
|
|
|
PARSE_OPT_OPTARG, &hash_callback),
|
2023-10-31 16:16:38 +08:00
|
|
|
OPT__ABBREV(&show_one_opts.abbrev),
|
|
|
|
OPT__QUIET(&show_one_opts.quiet,
|
2023-10-31 16:16:29 +08:00
|
|
|
N_("do not print results to stdout (useful with --verify)")),
|
|
|
|
OPT_CALLBACK_F(0, "exclude-existing", &exclude_existing_opts,
|
|
|
|
N_("pattern"), N_("show refs from stdin that aren't in local repository"),
|
|
|
|
PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback),
|
|
|
|
OPT_END()
|
|
|
|
};
|
|
|
|
|
Honor core.precomposeUnicode in more places
On Mac's HFS where git sets core.precomposeUnicode to true automatically
by git init/clone, when a user creates a simple unicode refname (in NFC
format) such as españa:
$ git branch españa
different commands would display the branch name differently. For
example, git branch, git log --decorate, and git fast-export all used
65 73 70 61 c3 b1 61 (or "espa\xc3\xb1a")
(NFC form) while show-ref would use
65 73 70 61 6e cc 83 61 (or "espan\xcc\x83a")
(NFD form). A stress test for git filter-repo was tripped up by this
inconsistency, though digging in I found that the problems could
compound; for example, if the user ran
$ git pack-refs --all
and then tried to check out the branch, they would be met with:
$ git checkout españa
error: pathspec 'españa' did not match any file(s) known to git
$ git checkout españa --
fatal: invalid reference: españa
$ git branch
españa
* master
Note that the user could run the `git branch` command first and copy and
paste the `españa` portion of the output and still see the same two
errors. Also, if the user added --no-prune to the pack-refs command,
then they would see three branches: master, españa, and españa (those
last two are NFC vs. NFD forms, even if they render the same).
Further, if the user had the `españa` branch checked out before
running `git pack-refs --all`, the user would be greeted with (note
that I'm trimming trailing output with an ellipsis):
$ git rev-parse HEAD
fatal: ambiguous argument 'HEAD': unknown revision or path...
$ git status
On branch españa
No commits yet...
Or worse, if the user didn't check this stuff first, running `git
commit` will create a new commit with all changes of all of history
being squashed into it.
In addition to pack-refs, one could also get into this state with
upload-pack or anything that calls either pack-refs or upload-pack (e.g.
gc or clone).
Add code in a few places (pack-refs, show-ref, upload-pack) to check and
honor the setting of core.precomposeUnicode to avoid these bugs.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-04-25 22:58:54 +08:00
|
|
|
git_config(git_default_config, NULL);
|
|
|
|
|
2009-06-21 12:40:46 +08:00
|
|
|
argc = parse_options(argc, argv, prefix, show_ref_options,
|
2015-11-17 18:26:05 +08:00
|
|
|
show_ref_usage, 0);
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
|
2023-10-31 16:16:46 +08:00
|
|
|
if ((!!exclude_existing_opts.enabled + !!verify) > 1)
|
|
|
|
die(_("only one of '%s' or '%s' can be given"),
|
|
|
|
"--exclude-existing", "--verify");
|
|
|
|
|
2023-10-31 16:16:29 +08:00
|
|
|
if (exclude_existing_opts.enabled)
|
|
|
|
return cmd_show_ref__exclude_existing(&exclude_existing_opts);
|
2023-10-31 16:16:17 +08:00
|
|
|
else if (verify)
|
2023-10-31 16:16:38 +08:00
|
|
|
return cmd_show_ref__verify(&show_one_opts, argv);
|
2023-10-31 16:16:17 +08:00
|
|
|
else
|
2023-10-31 16:16:42 +08:00
|
|
|
return cmd_show_ref__patterns(&patterns_opts, &show_one_opts, argv);
|
Add "git show-ref" builtin command
It's kind of like "git peek-remote", but works only locally (and thus
avoids the whole overhead of git_connect()) and has some extra
verification features.
For example, it allows you to filter the results, and to choose whether
you want the tag dereferencing or not. You can also use it to just test
whether a particular ref exists.
For example:
git show-ref master
will show all references called "master", whether tags or heads or
anything else, and regardless of how deep in the reference naming
hierarchy they are (so it would show "refs/heads/master" but also
"refs/remote/other-repo/master").
When using the "--verify" flag, the command requires an exact ref path:
git show-ref --verify refs/heads/master
will only match the exact branch called "master".
If nothing matches, show-ref will return an error code of 1, and in the
case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
allows you to do things like
git-show-ref --quiet --verify -- "refs/heads/$headname" ||
echo "$headname is not a valid branch"
to check whether a particular branch exists or not (notice how we don't
actually want to show any results, and we want to use the full refname for
it in order to not trigger the problem with ambiguous partial matches).
To show only tags, or only proper branch heads, use "--tags" and/or
"--heads" respectively (using both means that it shows tags _and_ heads,
but not other random references under the refs/ subdirectory).
To do automatic tag object dereferencing, use the "-d" or "--dereference"
flag, so you can do
git show-ref --tags --dereference
to get a listing of all tags together with what they dereference.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-09-16 02:19:32 +08:00
|
|
|
}
|