summaryrefslogtreecommitdiff
path: root/builtin-show-ref.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-12-19 01:38:18 -0800
committerJunio C Hamano <junkio@cox.net>2006-12-19 01:38:18 -0800
commit5fed4668153c9ca6e44ec84a0976089f515705aa (patch)
tree82f3ce0d2ea76ca31cebd3a5b40d0993e019859a /builtin-show-ref.c
parent63085fabbdeaad9eb8b29d39d0998c704e6cd232 (diff)
parent8683a45d66967b0969516a2b72cdbf136c2064a2 (diff)
downloadgit-5fed4668153c9ca6e44ec84a0976089f515705aa.tar.gz
Merge branch 'jc/test-clone' into jc/clone
* jc/test-clone: (35 commits) Introduce GIT_TEMPLATE_DIR Revert "fix testsuite: make sure they use templates freshly built from the source" fix testsuite: make sure they use templates freshly built from the source rerere: fix breakage of resolving. Add config example with respect to branch Add documentation for show-branch --topics make git a bit less cryptic on fetch errors make patch_delta() error cases a bit more verbose racy-git: documentation updates. show-ref: fix --exclude-existing parse-remote::expand_refs_wildcard() vim syntax: follow recent changes to commit template show-ref: fix --verify --hash=length show-ref: fix --quiet --verify avoid accessing _all_ loose refs in git-show-ref --verify git-fetch: Avoid reading packed refs over and over again Teach show-branch how to show ref-log data. markup fix in svnimport documentation. Documentation: new option -P for git-svnimport Fix mis-mark-up in git-merge-file.txt documentation ...
Diffstat (limited to 'builtin-show-ref.c')
-rw-r--r--builtin-show-ref.c99
1 files changed, 91 insertions, 8 deletions
diff --git a/builtin-show-ref.c b/builtin-show-ref.c
index 073979855b..853f13f6ae 100644
--- a/builtin-show-ref.c
+++ b/builtin-show-ref.c
@@ -2,13 +2,23 @@
#include "refs.h"
#include "object.h"
#include "tag.h"
+#include "path-list.h"
-static const char show_ref_usage[] = "git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=<length>]] [--abbrev[=<length>]] [--tags] [--heads] [--] [pattern*]";
+static const char show_ref_usage[] = "git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=<length>]] [--abbrev[=<length>]] [--tags] [--heads] [--] [pattern*] < ref-list";
static int deref_tags = 0, show_head = 0, tags_only = 0, heads_only = 0,
found_match = 0, verify = 0, quiet = 0, hash_only = 0, abbrev = 0;
static const char **pattern;
+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;
@@ -57,11 +67,7 @@ match:
if (quiet)
return 0;
- hex = find_unique_abbrev(sha1, abbrev);
- if (hash_only)
- printf("%s\n", hex);
- else
- printf("%s %s\n", hex, refname);
+ show_one(refname, sha1);
if (!deref_tags)
return 0;
@@ -86,6 +92,60 @@ match:
return 0;
}
+static int add_existing(const char *refname, const unsigned char *sha1, int flag, void *cbdata)
+{
+ struct path_list *list = (struct path_list *)cbdata;
+ path_list_insert(refname, list);
+ return 0;
+}
+
+/*
+ * 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.
+ */
+static int exclude_existing(const char *match)
+{
+ static struct path_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)) {
+ fprintf(stderr, "warning: ref '%s' ignored\n", ref);
+ continue;
+ }
+ if (!path_list_has_path(&existing_refs, ref)) {
+ printf("%s\n", buf);
+ }
+ }
+ return 0;
+}
+
int cmd_show_ref(int argc, const char **argv, const char *prefix)
{
int i;
@@ -121,13 +181,13 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
if (!strncmp(arg, "--hash=", 7) ||
(!strncmp(arg, "--abbrev", 8) &&
(arg[8] == '=' || arg[8] == '\0'))) {
- if (arg[3] != 'h' && !arg[8])
+ if (arg[2] != 'h' && !arg[8])
/* --abbrev only */
abbrev = DEFAULT_ABBREV;
else {
/* --hash= or --abbrev= */
char *end;
- if (arg[3] == 'h') {
+ if (arg[2] == 'h') {
hash_only = 1;
arg += 7;
}
@@ -153,8 +213,31 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
heads_only = 1;
continue;
}
+ if (!strcmp(arg, "--exclude-existing"))
+ return exclude_existing(NULL);
+ if (!strncmp(arg, "--exclude-existing=", 19))
+ return exclude_existing(arg + 19);
usage(show_ref_usage);
}
+
+ if (verify) {
+ unsigned char sha1[20];
+
+ while (*pattern) {
+ if (!strncmp(*pattern, "refs/", 5) &&
+ 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);