diff options
author | Junio C Hamano <gitster@pobox.com> | 2008-02-22 22:54:37 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-02-22 22:54:37 -0800 |
commit | 50f3ac29cbadbf7e0ff099b493b00cfa4129e1e0 (patch) | |
tree | 72b756b4c7d60709b7484cceeb3a1d82a18a86af /builtin-rev-parse.c | |
parent | builtin-reflog.c: fix typo that accesses an unset variable (diff) | |
parent | builtin-reflog.c: don't install new reflog on write failure (diff) | |
download | tgif-50f3ac29cbadbf7e0ff099b493b00cfa4129e1e0.tar.xz |
Merge branch 'bc/reflog-fix' into js/reflog-delete
* bc/reflog-fix: (1490 commits)
builtin-reflog.c: don't install new reflog on write failure
hash: fix lookup_hash semantics
gitweb: Better chopping in commit search results
builtin-tag.c: remove cruft
git-merge-index documentation: clarify synopsis
send-email: fix In-Reply-To regression
git-reset --hard and git-read-tree --reset: fix read_cache_unmerged()
Teach git-grep --name-only as synonym for -l
diff: fix java funcname pattern for solaris
t3404: use configured shell instead of /bin/sh
git_config_*: don't assume we are parsing a config file
prefix_path: use is_absolute_path() instead of *orig == '/'
git-clean: handle errors if removing files fails
Clarified the meaning of git-add -u in the documentation
git-clone.sh: properly configure remote even if remote's head is dangling
git.el: Set process-environment instead of invoking env
Documentation/git-stash: document options for git stash list
send-email: squelch warning due to comparing undefined $_ to ""
cvsexportcommit: be graceful when "cvs status" reorders the arguments
Rename git-core rpm to just git and rename the meta-pacakge to git-all.
...
Conflicts:
Documentation/git-reflog.txt
t/t1410-reflog.sh
Diffstat (limited to 'builtin-rev-parse.c')
-rw-r--r-- | builtin-rev-parse.c | 165 |
1 files changed, 161 insertions, 4 deletions
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c index 8d78b69c90..b9af1a5a55 100644 --- a/builtin-rev-parse.c +++ b/builtin-rev-parse.c @@ -8,6 +8,7 @@ #include "refs.h" #include "quote.h" #include "builtin.h" +#include "parse-options.h" #define DO_REVS 1 #define DO_NOREV 2 @@ -20,6 +21,9 @@ static const char *def; #define NORMAL 0 #define REVERSED 1 static int show_type = NORMAL; + +#define SHOW_SYMBOLIC_ASIS 1 +#define SHOW_SYMBOLIC_FULL 2 static int symbolic; static int abbrev; static int output_sq; @@ -102,8 +106,32 @@ static void show_rev(int type, const unsigned char *sha1, const char *name) if (type != show_type) putchar('^'); - if (symbolic && name) - show(name); + if (symbolic && name) { + if (symbolic == SHOW_SYMBOLIC_FULL) { + unsigned char discard[20]; + char *full; + + switch (dwim_ref(name, strlen(name), discard, &full)) { + case 0: + /* + * Not found -- not a ref. We could + * emit "name" here, but symbolic-full + * users are interested in finding the + * refs spelled in full, and they would + * need to filter non-refs if we did so. + */ + break; + case 1: /* happy */ + show(full); + break; + default: /* ambiguous */ + error("refname '%s' is ambiguous", name); + break; + } + } else { + show(name); + } + } else if (abbrev) show(find_unique_abbrev(sha1, abbrev)); else @@ -209,13 +237,138 @@ static int try_difference(const char *arg) return 0; } +static int parseopt_dump(const struct option *o, const char *arg, int unset) +{ + struct strbuf *parsed = o->value; + if (unset) + strbuf_addf(parsed, " --no-%s", o->long_name); + else if (o->short_name) + strbuf_addf(parsed, " -%c", o->short_name); + else + strbuf_addf(parsed, " --%s", o->long_name); + if (arg) { + strbuf_addch(parsed, ' '); + sq_quote_buf(parsed, arg); + } + return 0; +} + +static const char *skipspaces(const char *s) +{ + while (isspace(*s)) + s++; + return s; +} + +static int cmd_parseopt(int argc, const char **argv, const char *prefix) +{ + static int keep_dashdash = 0; + static char const * const parseopt_usage[] = { + "git-rev-parse --parseopt [options] -- [<args>...]", + NULL + }; + static struct option parseopt_opts[] = { + OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash, + "keep the `--` passed as an arg"), + OPT_END(), + }; + + struct strbuf sb, parsed; + const char **usage = NULL; + struct option *opts = NULL; + int onb = 0, osz = 0, unb = 0, usz = 0; + + strbuf_init(&parsed, 0); + strbuf_addstr(&parsed, "set --"); + argc = parse_options(argc, argv, parseopt_opts, parseopt_usage, + PARSE_OPT_KEEP_DASHDASH); + if (argc < 1 || strcmp(argv[0], "--")) + usage_with_options(parseopt_usage, parseopt_opts); + + strbuf_init(&sb, 0); + /* get the usage up to the first line with a -- on it */ + for (;;) { + if (strbuf_getline(&sb, stdin, '\n') == EOF) + die("premature end of input"); + ALLOC_GROW(usage, unb + 1, usz); + if (!strcmp("--", sb.buf)) { + if (unb < 1) + die("no usage string given before the `--' separator"); + usage[unb] = NULL; + break; + } + usage[unb++] = strbuf_detach(&sb, NULL); + } + + /* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */ + while (strbuf_getline(&sb, stdin, '\n') != EOF) { + const char *s; + struct option *o; + + if (!sb.len) + continue; + + ALLOC_GROW(opts, onb + 1, osz); + memset(opts + onb, 0, sizeof(opts[onb])); + + o = &opts[onb++]; + s = strchr(sb.buf, ' '); + if (!s || *sb.buf == ' ') { + o->type = OPTION_GROUP; + o->help = xstrdup(skipspaces(s)); + continue; + } + + o->type = OPTION_CALLBACK; + o->help = xstrdup(skipspaces(s)); + o->value = &parsed; + o->callback = &parseopt_dump; + switch (s[-1]) { + case '=': + s--; + break; + case '?': + o->flags = PARSE_OPT_OPTARG; + s--; + break; + default: + o->flags = PARSE_OPT_NOARG; + break; + } + + if (s - sb.buf == 1) /* short option only */ + o->short_name = *sb.buf; + else if (sb.buf[1] != ',') /* long option only */ + o->long_name = xmemdupz(sb.buf, s - sb.buf); + else { + o->short_name = *sb.buf; + o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2); + } + } + strbuf_release(&sb); + + /* put an OPT_END() */ + ALLOC_GROW(opts, onb + 1, osz); + memset(opts + onb, 0, sizeof(opts[onb])); + argc = parse_options(argc, argv, opts, usage, + keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0); + + strbuf_addf(&parsed, " --"); + sq_quote_argv(&parsed, argv, 0); + puts(parsed.buf); + return 0; +} + int cmd_rev_parse(int argc, const char **argv, const char *prefix) { int i, as_is = 0, verify = 0; unsigned char sha1[20]; - git_config(git_default_config); + if (argc > 1 && !strcmp("--parseopt", argv[1])) + return cmd_parseopt(argc - 1, argv + 1, prefix); + prefix = setup_git_directory(); + git_config(git_default_config); for (i = 1; i < argc; i++) { const char *arg = argv[i]; @@ -295,7 +448,11 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--symbolic")) { - symbolic = 1; + symbolic = SHOW_SYMBOLIC_ASIS; + continue; + } + if (!strcmp(arg, "--symbolic-full-name")) { + symbolic = SHOW_SYMBOLIC_FULL; continue; } if (!strcmp(arg, "--all")) { |