From 81b50f3ce40bfdd66e5d967bf82be001039a9a98 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 22 Feb 2010 08:42:18 -0800 Subject: Move 'builtin-*' into a 'builtin/' subdirectory This shrinks the top-level directory a bit, and makes it much more pleasant to use auto-completion on the thing. Instead of [torvalds@nehalem git]$ em buil Display all 180 possibilities? (y or n) [torvalds@nehalem git]$ em builtin-sh builtin-shortlog.c builtin-show-branch.c builtin-show-ref.c builtin-shortlog.o builtin-show-branch.o builtin-show-ref.o [torvalds@nehalem git]$ em builtin-shor builtin-shortlog.c builtin-shortlog.o [torvalds@nehalem git]$ em builtin-shortlog.c you get [torvalds@nehalem git]$ em buil [type] builtin/ builtin.h [torvalds@nehalem git]$ em builtin [auto-completes to] [torvalds@nehalem git]$ em builtin/sh [type] shortlog.c shortlog.o show-branch.c show-branch.o show-ref.c show-ref.o [torvalds@nehalem git]$ em builtin/sho [auto-completes to] [torvalds@nehalem git]$ em builtin/shor [type] shortlog.c shortlog.o [torvalds@nehalem git]$ em builtin/shortlog.c which doesn't seem all that different, but not having that annoying break in "Display all 180 possibilities?" is quite a relief. NOTE! If you do this in a clean tree (no object files etc), or using an editor that has auto-completion rules that ignores '*.o' files, you won't see that annoying 'Display all 180 possibilities?' message - it will just show the choices instead. I think bash has some cut-off around 100 choices or something. So the reason I see this is that I'm using an odd editory, and thus don't have the rules to cut down on auto-completion. But you can simulate that by using 'ls' instead, or something similar. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin/show-ref.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 builtin/show-ref.c (limited to 'builtin/show-ref.c') diff --git a/builtin/show-ref.c b/builtin/show-ref.c new file mode 100644 index 0000000000..17ada88dfb --- /dev/null +++ b/builtin/show-ref.c @@ -0,0 +1,249 @@ +#include "builtin.h" +#include "cache.h" +#include "refs.h" +#include "object.h" +#include "tag.h" +#include "string-list.h" +#include "parse-options.h" + +static const char * const show_ref_usage[] = { + "git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--hash[=]] [--abbrev[=]] [--tags] [--heads] [--] [pattern*] ", + "git show-ref --exclude-existing[=pattern] < ref-list", + NULL +}; + +static int deref_tags, show_head, tags_only, heads_only, found_match, verify, + quiet, hash_only, abbrev, exclude_arg; +static const char **pattern; +static const char *exclude_existing_arg; + +static void show_one(const char *refname, const unsigned char *sha1) +{ + const char *hex = find_unique_abbrev(sha1, abbrev); + if (hash_only) + printf("%s\n", hex); + else + printf("%s %s\n", hex, refname); +} + +static int show_ref(const char *refname, const unsigned char *sha1, int flag, void *cbdata) +{ + struct object *obj; + const char *hex; + unsigned char peeled[20]; + + if (tags_only || heads_only) { + int match; + + match = heads_only && !prefixcmp(refname, "refs/heads/"); + match |= tags_only && !prefixcmp(refname, "refs/tags/"); + if (!match) + return 0; + } + if (pattern) { + int reflen = strlen(refname); + const char **p = pattern, *m; + 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; + /* "--verify" requires an exact match */ + if (verify) + continue; + if (refname[reflen - len - 1] == '/') + goto match; + } + return 0; + } + +match: + found_match++; + + /* This changes the semantics slightly that even under quiet we + * detect and return error if the repository is corrupt and + * ref points at a nonexistent object. + */ + if (!has_sha1_file(sha1)) + die("git show-ref: bad ref %s (%s)", refname, + sha1_to_hex(sha1)); + + if (quiet) + return 0; + + show_one(refname, sha1); + + if (!deref_tags) + return 0; + + if ((flag & REF_ISPACKED) && !peel_ref(refname, peeled)) { + if (!is_null_sha1(peeled)) { + hex = find_unique_abbrev(peeled, abbrev); + printf("%s %s^{}\n", hex, refname); + } + } + else { + obj = parse_object(sha1); + if (!obj) + die("git show-ref: bad ref %s (%s)", refname, + sha1_to_hex(sha1)); + if (obj->type == OBJ_TAG) { + obj = deref_tag(obj, refname, 0); + if (!obj) + die("git show-ref: bad tag at ref %s (%s)", refname, + sha1_to_hex(sha1)); + hex = find_unique_abbrev(obj->sha1, abbrev); + printf("%s %s^{}\n", hex, refname); + } + } + return 0; +} + +static int add_existing(const char *refname, const unsigned char *sha1, int flag, void *cbdata) +{ + struct string_list *list = (struct string_list *)cbdata; + string_list_insert(refname, list); + return 0; +} + +/* + * read "^(?:\s)?(?:\^\{\})?$" 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. + */ +static int exclude_existing(const char *match) +{ + static struct string_list existing_refs = { NULL, 0, 0, 0 }; + char buf[1024]; + int matchlen = match ? strlen(match) : 0; + + for_each_ref(add_existing, &existing_refs); + while (fgets(buf, sizeof(buf), stdin)) { + char *ref; + int len = strlen(buf); + + if (len > 0 && buf[len - 1] == '\n') + buf[--len] = '\0'; + if (3 <= len && !strcmp(buf + len - 3, "^{}")) { + len -= 3; + buf[len] = '\0'; + } + for (ref = buf + len; buf < ref; ref--) + if (isspace(ref[-1])) + break; + if (match) { + int reflen = buf + len - ref; + if (reflen < matchlen) + continue; + if (strncmp(ref, match, matchlen)) + continue; + } + if (check_ref_format(ref)) { + warning("ref '%s' ignored", ref); + continue; + } + if (!string_list_has_string(&existing_refs, ref)) { + printf("%s\n", buf); + } + } + return 0; +} + +static int hash_callback(const struct option *opt, const char *arg, int unset) +{ + hash_only = 1; + /* Use full length SHA1 if no argument */ + if (!arg) + return 0; + return parse_opt_abbrev_cb(opt, arg, unset); +} + +static int exclude_existing_callback(const struct option *opt, const char *arg, + int unset) +{ + exclude_arg = 1; + *(const char **)opt->value = arg; + return 0; +} + +static int help_callback(const struct option *opt, const char *arg, int unset) +{ + return -1; +} + +static const struct option show_ref_options[] = { + OPT_BOOLEAN(0, "tags", &tags_only, "only show tags (can be combined with heads)"), + OPT_BOOLEAN(0, "heads", &heads_only, "only show heads (can be combined with tags)"), + OPT_BOOLEAN(0, "verify", &verify, "stricter reference checking, " + "requires exact ref path"), + { OPTION_BOOLEAN, 'h', NULL, &show_head, NULL, + "show the HEAD reference", + PARSE_OPT_NOARG | PARSE_OPT_HIDDEN }, + OPT_BOOLEAN(0, "head", &show_head, "show the HEAD reference"), + OPT_BOOLEAN('d', "dereference", &deref_tags, + "dereference tags into object IDs"), + { OPTION_CALLBACK, 's', "hash", &abbrev, "n", + "only show SHA1 hash using digits", + PARSE_OPT_OPTARG, &hash_callback }, + OPT__ABBREV(&abbrev), + OPT__QUIET(&quiet), + { OPTION_CALLBACK, 0, "exclude-existing", &exclude_existing_arg, + "pattern", "show refs from stdin that aren't in local repository", + PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback }, + { OPTION_CALLBACK, 0, "help-all", NULL, NULL, "show usage", + PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback }, + OPT_END() +}; + +int cmd_show_ref(int argc, const char **argv, const char *prefix) +{ + if (argc == 2 && !strcmp(argv[1], "-h")) + usage_with_options(show_ref_usage, show_ref_options); + + argc = parse_options(argc, argv, prefix, show_ref_options, + show_ref_usage, PARSE_OPT_NO_INTERNAL_HELP); + + if (exclude_arg) + return exclude_existing(exclude_existing_arg); + + pattern = argv; + if (!*pattern) + pattern = NULL; + + if (verify) { + if (!pattern) + die("--verify requires a reference"); + while (*pattern) { + unsigned char sha1[20]; + + if (!prefixcmp(*pattern, "refs/") && + resolve_ref(*pattern, sha1, 1, NULL)) { + if (!quiet) + show_one(*pattern, sha1); + } + else if (!quiet) + die("'%s' - not a valid ref", *pattern); + else + return 1; + pattern++; + } + return 0; + } + + if (show_head) + head_ref(show_ref, NULL); + for_each_ref(show_ref, NULL); + if (!found_match) { + if (verify && !quiet) + die("No match"); + return 1; + } + return 0; +} -- cgit v1.2.3 From 78a395d371ec9fd14297178ec98b8b1042a64fb6 Mon Sep 17 00:00:00 2001 From: Julian Phillips Date: Sat, 26 Jun 2010 00:41:35 +0100 Subject: string_list: Fix argument order for string_list_insert Update the definition and callers of string_list_insert to use the string_list as the first argument. This helps make the string_list API easier to use by being more consistent. Signed-off-by: Julian Phillips Signed-off-by: Junio C Hamano --- builtin/show-ref.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin/show-ref.c') diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 17ada88dfb..0b2a9ad1a9 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -105,7 +105,7 @@ match: static int add_existing(const char *refname, const unsigned char *sha1, int flag, void *cbdata) { struct string_list *list = (struct string_list *)cbdata; - string_list_insert(refname, list); + string_list_insert(list, refname); return 0; } -- cgit v1.2.3 From 183113a5ca99cb228b2ba0a29e53f1ac11f2c7c2 Mon Sep 17 00:00:00 2001 From: Thiago Farina Date: Sun, 4 Jul 2010 16:46:19 -0300 Subject: string_list: Add STRING_LIST_INIT macro and make use of it. Acked-by: Jonathan Nieder Signed-off-by: Thiago Farina Signed-off-by: Junio C Hamano --- builtin/show-ref.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin/show-ref.c') diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 0b2a9ad1a9..be9b512eeb 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -120,7 +120,7 @@ static int add_existing(const char *refname, const unsigned char *sha1, int flag */ static int exclude_existing(const char *match) { - static struct string_list existing_refs = { NULL, 0, 0, 0 }; + static struct string_list existing_refs = STRING_LIST_INIT_NODUP; char buf[1024]; int matchlen = match ? strlen(match) : 0; -- cgit v1.2.3 From d52ee6e6131f65bb4360743ebea2e7b400b544e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Mon, 8 Nov 2010 19:06:54 +0100 Subject: add description parameter to OPT__QUIET Allows better help text to be defined than "be quiet". Also make use of the macro in a place that already had a different description. No object code changes intended. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin/show-ref.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin/show-ref.c') diff --git a/builtin/show-ref.c b/builtin/show-ref.c index be9b512eeb..6507f03d32 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -193,7 +193,7 @@ static const struct option show_ref_options[] = { "only show SHA1 hash using digits", PARSE_OPT_OPTARG, &hash_callback }, OPT__ABBREV(&abbrev), - OPT__QUIET(&quiet), + OPT__QUIET(&quiet, "be quiet"), { OPTION_CALLBACK, 0, "exclude-existing", &exclude_existing_arg, "pattern", "show refs from stdin that aren't in local repository", PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback }, -- cgit v1.2.3 From 8c83968385e1e742e188435fd2fe5ebf57565e49 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Mon, 8 Nov 2010 13:54:48 -0600 Subject: Describe various forms of "be quiet" using OPT__QUIET Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- builtin/show-ref.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'builtin/show-ref.c') diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 6507f03d32..45f0340c3e 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -193,7 +193,8 @@ static const struct option show_ref_options[] = { "only show SHA1 hash using digits", PARSE_OPT_OPTARG, &hash_callback }, OPT__ABBREV(&abbrev), - OPT__QUIET(&quiet, "be quiet"), + OPT__QUIET(&quiet, + "do not print results to stdout (useful with --verify)"), { OPTION_CALLBACK, 0, "exclude-existing", &exclude_existing_arg, "pattern", "show refs from stdin that aren't in local repository", PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback }, -- cgit v1.2.3