summaryrefslogtreecommitdiff
path: root/builtin-rev-parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin-rev-parse.c')
-rw-r--r--builtin-rev-parse.c106
1 files changed, 96 insertions, 10 deletions
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index 9aa049ec17..a8c5043ded 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -26,6 +26,8 @@ static int show_type = NORMAL;
#define SHOW_SYMBOLIC_FULL 2
static int symbolic;
static int abbrev;
+static int abbrev_ref;
+static int abbrev_ref_strict;
static int output_sq;
/*
@@ -39,6 +41,7 @@ static int is_rev_argument(const char *arg)
"--all",
"--bisect",
"--dense",
+ "--branches=",
"--branches",
"--header",
"--max-age=",
@@ -49,8 +52,11 @@ static int is_rev_argument(const char *arg)
"--objects-edge",
"--parents",
"--pretty",
+ "--remotes=",
"--remotes",
+ "--glob=",
"--sparse",
+ "--tags=",
"--tags",
"--topo-order",
"--date-order",
@@ -109,8 +115,8 @@ static void show_rev(int type, const unsigned char *sha1, const char *name)
return;
def = NULL;
- if (symbolic && name) {
- if (symbolic == SHOW_SYMBOLIC_FULL) {
+ if ((symbolic || abbrev_ref) && name) {
+ if (symbolic == SHOW_SYMBOLIC_FULL || abbrev_ref) {
unsigned char discard[20];
char *full;
@@ -125,6 +131,9 @@ static void show_rev(int type, const unsigned char *sha1, const char *name)
*/
break;
case 1: /* happy */
+ if (abbrev_ref)
+ full = shorten_unambiguous_ref(full,
+ abbrev_ref_strict);
show_with_type(type, full);
break;
default: /* ambiguous */
@@ -175,6 +184,12 @@ static int show_reference(const char *refname, const unsigned char *sha1, int fl
return 0;
}
+static int anti_reference(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+{
+ show_rev(REVERSED, sha1, refname);
+ return 0;
+}
+
static void show_datestring(const char *flag, const char *datestr)
{
static char buffer[100];
@@ -296,7 +311,7 @@ static const char *skipspaces(const char *s)
static int cmd_parseopt(int argc, const char **argv, const char *prefix)
{
- static int keep_dashdash = 0;
+ static int keep_dashdash = 0, stop_at_non_option = 0;
static char const * const parseopt_usage[] = {
"git rev-parse --parseopt [options] -- [<args>...]",
NULL
@@ -304,22 +319,23 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
static struct option parseopt_opts[] = {
OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash,
"keep the `--` passed as an arg"),
+ OPT_BOOLEAN(0, "stop-at-non-option", &stop_at_non_option,
+ "stop parsing after the "
+ "first non-option argument"),
OPT_END(),
};
- struct strbuf sb, parsed;
+ struct strbuf sb = STRBUF_INIT, parsed = STRBUF_INIT;
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,
+ argc = parse_options(argc, argv, prefix, 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)
@@ -390,8 +406,9 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
/* 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);
+ argc = parse_options(argc, argv, prefix, opts, usage,
+ keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0 |
+ stop_at_non_option ? PARSE_OPT_STOP_AT_NON_OPTION : 0);
strbuf_addf(&parsed, " --");
sq_quote_argv(&parsed, argv, 0);
@@ -399,6 +416,18 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
return 0;
}
+static int cmd_sq_quote(int argc, const char **argv)
+{
+ struct strbuf buf = STRBUF_INIT;
+
+ if (argc)
+ sq_quote_argv(&buf, argv, 0);
+ printf("%s\n", buf.buf);
+ strbuf_release(&buf);
+
+ return 0;
+}
+
static void die_no_single_rev(int quiet)
{
if (quiet)
@@ -407,6 +436,13 @@ static void die_no_single_rev(int quiet)
die("Needed a single revision");
}
+static const char builtin_rev_parse_usage[] =
+"git rev-parse --parseopt [options] -- [<args>...]\n"
+" or: git rev-parse --sq-quote [<arg>...]\n"
+" or: git rev-parse [options] [<arg>...]\n"
+"\n"
+"Run \"git rev-parse --parseopt -h\" for more information on the first usage.";
+
int cmd_rev_parse(int argc, const char **argv, const char *prefix)
{
int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
@@ -416,6 +452,12 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
if (argc > 1 && !strcmp("--parseopt", argv[1]))
return cmd_parseopt(argc - 1, argv + 1, prefix);
+ if (argc > 1 && !strcmp("--sq-quote", argv[1]))
+ return cmd_sq_quote(argc - 2, argv + 2);
+
+ if (argc > 1 && !strcmp("-h", argv[1]))
+ usage(builtin_rev_parse_usage);
+
prefix = setup_git_directory();
git_config(git_default_config, NULL);
for (i = 1; i < argc; i++) {
@@ -508,22 +550,66 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
symbolic = SHOW_SYMBOLIC_FULL;
continue;
}
+ if (!prefixcmp(arg, "--abbrev-ref") &&
+ (!arg[12] || arg[12] == '=')) {
+ abbrev_ref = 1;
+ abbrev_ref_strict = warn_ambiguous_refs;
+ if (arg[12] == '=') {
+ if (!strcmp(arg + 13, "strict"))
+ abbrev_ref_strict = 1;
+ else if (!strcmp(arg + 13, "loose"))
+ abbrev_ref_strict = 0;
+ else
+ die("unknown mode for %s", arg);
+ }
+ continue;
+ }
if (!strcmp(arg, "--all")) {
for_each_ref(show_reference, NULL);
continue;
}
+ if (!strcmp(arg, "--bisect")) {
+ for_each_ref_in("refs/bisect/bad", show_reference, NULL);
+ for_each_ref_in("refs/bisect/good", anti_reference, NULL);
+ continue;
+ }
+ if (!prefixcmp(arg, "--branches=")) {
+ for_each_glob_ref_in(show_reference, arg + 11,
+ "refs/heads/", NULL);
+ continue;
+ }
if (!strcmp(arg, "--branches")) {
for_each_branch_ref(show_reference, NULL);
continue;
}
+ if (!prefixcmp(arg, "--tags=")) {
+ for_each_glob_ref_in(show_reference, arg + 7,
+ "refs/tags/", NULL);
+ continue;
+ }
if (!strcmp(arg, "--tags")) {
for_each_tag_ref(show_reference, NULL);
continue;
}
+ if (!prefixcmp(arg, "--glob=")) {
+ for_each_glob_ref(show_reference, arg + 7, NULL);
+ continue;
+ }
+ if (!prefixcmp(arg, "--remotes=")) {
+ for_each_glob_ref_in(show_reference, arg + 10,
+ "refs/remotes/", NULL);
+ continue;
+ }
if (!strcmp(arg, "--remotes")) {
for_each_remote_ref(show_reference, NULL);
continue;
}
+ if (!strcmp(arg, "--show-toplevel")) {
+ const char *work_tree = get_git_work_tree();
+ if (work_tree)
+ puts(work_tree);
+ continue;
+ }
if (!strcmp(arg, "--show-prefix")) {
if (prefix)
puts(prefix);
@@ -560,7 +646,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (!getcwd(cwd, PATH_MAX))
- die("unable to get current working directory");
+ die_errno("unable to get current working directory");
printf("%s/.git\n", cwd);
continue;
}