diff options
Diffstat (limited to 'builtin/rev-parse.c')
-rw-r--r-- | builtin/rev-parse.c | 234 |
1 files changed, 149 insertions, 85 deletions
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index c961b74c5a..0513330910 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -12,6 +12,7 @@ #include "diff.h" #include "revision.h" #include "split-index.h" +#include "submodule.h" #define DO_REVS 1 #define DO_NOREV 2 @@ -204,21 +205,22 @@ static int anti_reference(const char *refname, const struct object_id *oid, int return 0; } -static int show_abbrev(const unsigned char *sha1, void *cb_data) +static int show_abbrev(const struct object_id *oid, void *cb_data) { - show_rev(NORMAL, sha1, NULL); + show_rev(NORMAL, oid->hash, NULL); return 0; } static void show_datestring(const char *flag, const char *datestr) { - static char buffer[100]; + char *buffer; /* date handling requires both flags and revs */ if ((filter & (DO_FLAGS | DO_REVS)) != (DO_FLAGS | DO_REVS)) return; - snprintf(buffer, sizeof(buffer), "%s%lu", flag, approxidate(datestr)); + buffer = xstrfmt("%s%lu", flag, approxidate(datestr)); show(buffer); + free(buffer); } static int show_file(const char *arg, int output_prefix) @@ -227,9 +229,9 @@ static int show_file(const char *arg, int output_prefix) if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) { if (output_prefix) { const char *prefix = startup_info->prefix; - show(prefix_filename(prefix, - prefix ? strlen(prefix) : 0, - arg)); + char *fname = prefix_filename(prefix, arg); + show(fname); + free(fname); } else show(arg); return 1; @@ -298,14 +300,30 @@ static int try_parent_shorthands(const char *arg) unsigned char sha1[20]; struct commit *commit; struct commit_list *parents; - int parents_only; - - if ((dotdot = strstr(arg, "^!"))) - parents_only = 0; - else if ((dotdot = strstr(arg, "^@"))) - parents_only = 1; - - if (!dotdot || dotdot[2]) + int parent_number; + int include_rev = 0; + int include_parents = 0; + int exclude_parent = 0; + + if ((dotdot = strstr(arg, "^!"))) { + include_rev = 1; + if (dotdot[2]) + return 0; + } else if ((dotdot = strstr(arg, "^@"))) { + include_parents = 1; + if (dotdot[2]) + return 0; + } else if ((dotdot = strstr(arg, "^-"))) { + include_rev = 1; + exclude_parent = 1; + + if (dotdot[2]) { + char *end; + exclude_parent = strtoul(dotdot + 2, &end, 10); + if (*end != '\0' || !exclude_parent) + return 0; + } + } else return 0; *dotdot = 0; @@ -314,12 +332,29 @@ static int try_parent_shorthands(const char *arg) return 0; } - if (!parents_only) - show_rev(NORMAL, sha1, arg); commit = lookup_commit_reference(sha1); - for (parents = commit->parents; parents; parents = parents->next) - show_rev(parents_only ? NORMAL : REVERSED, - parents->item->object.oid.hash, arg); + if (exclude_parent && + exclude_parent > commit_list_count(commit->parents)) { + *dotdot = '^'; + return 0; + } + + if (include_rev) + show_rev(NORMAL, sha1, arg); + for (parents = commit->parents, parent_number = 1; + parents; + parents = parents->next, parent_number++) { + char *name = NULL; + + if (exclude_parent && parent_number != exclude_parent) + continue; + + if (symbolic) + name = xstrfmt("%s^%d", arg, parent_number); + show_rev(include_parents ? NORMAL : REVERSED, + parents->item->object.oid.hash, name); + free(name); + } *dotdot = '^'; return 1; @@ -469,7 +504,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) (stop_at_non_option ? PARSE_OPT_STOP_AT_NON_OPTION : 0) | PARSE_OPT_SHELL_EVAL); - strbuf_addf(&parsed, " --"); + strbuf_addstr(&parsed, " --"); sq_quote_argv(&parsed, argv, 0); puts(parsed.buf); return 0; @@ -502,6 +537,34 @@ N_("git rev-parse --parseopt [<options>] -- [<args>...]\n" "\n" "Run \"git rev-parse --parseopt -h\" for more information on the first usage."); +/* + * Parse "opt" or "opt=<value>", setting value respectively to either + * NULL or the string after "=". + */ +static int opt_with_value(const char *arg, const char *opt, const char **value) +{ + if (skip_prefix(arg, opt, &arg)) { + if (!*arg) { + *value = NULL; + return 1; + } + if (*arg++ == '=') { + *value = arg; + return 1; + } + } + return 0; +} + +static void handle_ref_opt(const char *pattern, const char *prefix) +{ + if (pattern) + for_each_glob_ref_in(show_reference, pattern, prefix, NULL); + else + for_each_ref_in(prefix, show_reference, NULL); + clear_ref_exclusion(&ref_excludes); +} + 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; @@ -512,6 +575,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) unsigned int flags = 0; const char *name = NULL; struct object_context unused; + struct strbuf buf = STRBUF_INIT; if (argc > 1 && !strcmp("--parseopt", argv[1])) return cmd_parseopt(argc - 1, argv + 1, prefix); @@ -566,7 +630,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) if (!strcmp(arg, "--git-path")) { if (!argv[i + 1]) die("--git-path requires an argument"); - puts(git_path("%s", argv[i + 1])); + strbuf_reset(&buf); + puts(relative_path(git_path("%s", argv[i + 1]), + prefix, &buf)); i++; continue; } @@ -638,13 +704,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) flags |= GET_SHA1_QUIETLY; continue; } - if (!strcmp(arg, "--short") || - starts_with(arg, "--short=")) { + if (opt_with_value(arg, "--short", &arg)) { filter &= ~(DO_FLAGS|DO_NOREV); verify = 1; abbrev = DEFAULT_ABBREV; - if (arg[7] == '=') - abbrev = strtoul(arg + 8, NULL, 10); + if (!arg) + continue; + abbrev = strtoul(arg, NULL, 10); if (abbrev < MINIMUM_ABBREV) abbrev = MINIMUM_ABBREV; else if (40 <= abbrev) @@ -667,17 +733,17 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) symbolic = SHOW_SYMBOLIC_FULL; continue; } - if (starts_with(arg, "--abbrev-ref") && - (!arg[12] || arg[12] == '=')) { + if (opt_with_value(arg, "--abbrev-ref", &arg)) { abbrev_ref = 1; abbrev_ref_strict = warn_ambiguous_refs; - if (arg[12] == '=') { - if (!strcmp(arg + 13, "strict")) + if (arg) { + if (!strcmp(arg, "strict")) abbrev_ref_strict = 1; - else if (!strcmp(arg + 13, "loose")) + else if (!strcmp(arg, "loose")) abbrev_ref_strict = 0; else - die("unknown mode for %s", arg); + die("unknown mode for --abbrev-ref: %s", + arg); } continue; } @@ -685,8 +751,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) for_each_ref(show_reference, NULL); continue; } - if (starts_with(arg, "--disambiguate=")) { - for_each_abbrev(arg + 15, show_abbrev, NULL); + if (skip_prefix(arg, "--disambiguate=", &arg)) { + for_each_abbrev(arg, show_abbrev, NULL); continue; } if (!strcmp(arg, "--bisect")) { @@ -694,46 +760,24 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) for_each_ref_in("refs/bisect/good", anti_reference, NULL); continue; } - if (starts_with(arg, "--branches=")) { - for_each_glob_ref_in(show_reference, arg + 11, - "refs/heads/", NULL); - clear_ref_exclusion(&ref_excludes); - continue; - } - if (!strcmp(arg, "--branches")) { - for_each_branch_ref(show_reference, NULL); - clear_ref_exclusion(&ref_excludes); - continue; - } - if (starts_with(arg, "--tags=")) { - for_each_glob_ref_in(show_reference, arg + 7, - "refs/tags/", NULL); - clear_ref_exclusion(&ref_excludes); - continue; - } - if (!strcmp(arg, "--tags")) { - for_each_tag_ref(show_reference, NULL); - clear_ref_exclusion(&ref_excludes); + if (opt_with_value(arg, "--branches", &arg)) { + handle_ref_opt(arg, "refs/heads/"); continue; } - if (starts_with(arg, "--glob=")) { - for_each_glob_ref(show_reference, arg + 7, NULL); - clear_ref_exclusion(&ref_excludes); + if (opt_with_value(arg, "--tags", &arg)) { + handle_ref_opt(arg, "refs/tags/"); continue; } - if (starts_with(arg, "--remotes=")) { - for_each_glob_ref_in(show_reference, arg + 10, - "refs/remotes/", NULL); - clear_ref_exclusion(&ref_excludes); + if (skip_prefix(arg, "--glob=", &arg)) { + handle_ref_opt(arg, NULL); continue; } - if (!strcmp(arg, "--remotes")) { - for_each_remote_ref(show_reference, NULL); - clear_ref_exclusion(&ref_excludes); + if (opt_with_value(arg, "--remotes", &arg)) { + handle_ref_opt(arg, "refs/remotes/"); continue; } - if (starts_with(arg, "--exclude=")) { - add_ref_exclusion(&ref_excludes, arg + 10); + if (skip_prefix(arg, "--exclude=", &arg)) { + add_ref_exclusion(&ref_excludes, arg); continue; } if (!strcmp(arg, "--show-toplevel")) { @@ -742,6 +786,12 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) puts(work_tree); continue; } + if (!strcmp(arg, "--show-superproject-working-tree")) { + const char *superproject = get_superproject_working_tree(); + if (superproject) + puts(superproject); + continue; + } if (!strcmp(arg, "--show-prefix")) { if (prefix) puts(prefix); @@ -768,17 +818,27 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) putchar('\n'); continue; } - if (!strcmp(arg, "--git-dir")) { + if (!strcmp(arg, "--git-dir") || + !strcmp(arg, "--absolute-git-dir")) { const char *gitdir = getenv(GIT_DIR_ENVIRONMENT); char *cwd; int len; - if (gitdir) { - puts(gitdir); - continue; - } - if (!prefix) { - puts(".git"); - continue; + if (arg[2] == 'g') { /* --git-dir */ + if (gitdir) { + puts(gitdir); + continue; + } + if (!prefix) { + puts(".git"); + continue; + } + } else { /* --absolute-git-dir */ + if (!gitdir && !prefix) + gitdir = ".git"; + if (gitdir) { + puts(real_path(gitdir)); + continue; + } } cwd = xgetcwd(); len = strlen(cwd); @@ -787,8 +847,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--git-common-dir")) { - const char *pfx = prefix ? prefix : ""; - puts(prefix_filename(pfx, strlen(pfx), get_git_common_dir())); + strbuf_reset(&buf); + puts(relative_path(get_git_common_dir(), + prefix, &buf)); continue; } if (!strcmp(arg, "--is-inside-git-dir")) { @@ -811,24 +872,26 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) die(_("Could not read the index")); if (the_index.split_index) { const unsigned char *sha1 = the_index.split_index->base_sha1; - puts(git_path("sharedindex.%s", sha1_to_hex(sha1))); + const char *path = git_path("sharedindex.%s", sha1_to_hex(sha1)); + strbuf_reset(&buf); + puts(relative_path(path, prefix, &buf)); } continue; } - if (starts_with(arg, "--since=")) { - show_datestring("--max-age=", arg+8); + if (skip_prefix(arg, "--since=", &arg)) { + show_datestring("--max-age=", arg); continue; } - if (starts_with(arg, "--after=")) { - show_datestring("--max-age=", arg+8); + if (skip_prefix(arg, "--after=", &arg)) { + show_datestring("--max-age=", arg); continue; } - if (starts_with(arg, "--before=")) { - show_datestring("--min-age=", arg+9); + if (skip_prefix(arg, "--before=", &arg)) { + show_datestring("--min-age=", arg); continue; } - if (starts_with(arg, "--until=")) { - show_datestring("--min-age=", arg+8); + if (skip_prefix(arg, "--until=", &arg)) { + show_datestring("--min-age=", arg); continue; } if (show_flag(arg) && verify) @@ -863,6 +926,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; verify_filename(prefix, arg, 1); } + strbuf_release(&buf); if (verify) { if (revs_count == 1) { show_rev(type, sha1, name); |