From 895f10c3b596ef955c7f252717e5b4668530c569 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 3 Jun 2006 18:45:43 +0200 Subject: Builtin git-rev-parse. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano diff --git a/Makefile b/Makefile index b6fce39..004c216 100644 --- a/Makefile +++ b/Makefile @@ -154,8 +154,7 @@ PROGRAMS = \ git-hash-object$X git-index-pack$X git-local-fetch$X \ git-mailinfo$X git-merge-base$X \ git-merge-index$X git-mktag$X git-mktree$X git-pack-objects$X git-patch-id$X \ - git-peek-remote$X git-prune-packed$X \ - git-receive-pack$X git-rev-parse$X \ + git-peek-remote$X git-prune-packed$X git-receive-pack$X \ git-send-pack$X git-shell$X \ git-show-index$X git-ssh-fetch$X \ git-ssh-upload$X git-unpack-file$X \ @@ -168,7 +167,7 @@ PROGRAMS = \ BUILT_INS = git-log$X git-whatchanged$X git-show$X \ git-count-objects$X git-diff$X git-push$X \ git-grep$X git-add$X git-rm$X git-rev-list$X \ - git-check-ref-format$X \ + git-check-ref-format$X git-rev-parse$X \ git-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \ git-ls-files$X git-ls-tree$X \ git-read-tree$X git-commit-tree$X \ @@ -222,7 +221,7 @@ LIB_OBJS = \ BUILTIN_OBJS = \ builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \ builtin-grep.o builtin-add.o builtin-rev-list.o builtin-check-ref-format.o \ - builtin-rm.o builtin-init-db.o \ + builtin-rm.o builtin-init-db.o builtin-rev-parse.o \ builtin-tar-tree.o builtin-upload-tar.o \ builtin-ls-files.o builtin-ls-tree.o \ builtin-read-tree.o builtin-commit-tree.o \ diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c new file mode 100644 index 0000000..c353a48 --- /dev/null +++ b/builtin-rev-parse.c @@ -0,0 +1,365 @@ +/* + * rev-parse.c + * + * Copyright (C) Linus Torvalds, 2005 + */ +#include "cache.h" +#include "commit.h" +#include "refs.h" +#include "quote.h" +#include "builtin.h" + +#define DO_REVS 1 +#define DO_NOREV 2 +#define DO_FLAGS 4 +#define DO_NONFLAGS 8 +static int filter = ~0; + +static char *def = NULL; + +#define NORMAL 0 +#define REVERSED 1 +static int show_type = NORMAL; +static int symbolic = 0; +static int abbrev = 0; +static int output_sq = 0; + +static int revs_count = 0; + +/* + * Some arguments are relevant "revision" arguments, + * others are about output format or other details. + * This sorts it all out. + */ +static int is_rev_argument(const char *arg) +{ + static const char *rev_args[] = { + "--all", + "--bisect", + "--dense", + "--branches", + "--header", + "--max-age=", + "--max-count=", + "--min-age=", + "--no-merges", + "--objects", + "--objects-edge", + "--parents", + "--pretty", + "--remotes", + "--sparse", + "--tags", + "--topo-order", + "--date-order", + "--unpacked", + NULL + }; + const char **p = rev_args; + + /* accept -, like traditional "head" */ + if ((*arg == '-') && isdigit(arg[1])) + return 1; + + for (;;) { + const char *str = *p++; + int len; + if (!str) + return 0; + len = strlen(str); + if (!strcmp(arg, str) || + (str[len-1] == '=' && !strncmp(arg, str, len))) + return 1; + } +} + +/* Output argument as a string, either SQ or normal */ +static void show(const char *arg) +{ + if (output_sq) { + int sq = '\'', ch; + + putchar(sq); + while ((ch = *arg++)) { + if (ch == sq) + fputs("'\\'", stdout); + putchar(ch); + } + putchar(sq); + putchar(' '); + } + else + puts(arg); +} + +/* Output a revision, only if filter allows it */ +static void show_rev(int type, const unsigned char *sha1, const char *name) +{ + if (!(filter & DO_REVS)) + return; + def = NULL; + revs_count++; + + if (type != show_type) + putchar('^'); + if (symbolic && name) + show(name); + else if (abbrev) + show(find_unique_abbrev(sha1, abbrev)); + else + show(sha1_to_hex(sha1)); +} + +/* Output a flag, only if filter allows it. */ +static int show_flag(char *arg) +{ + if (!(filter & DO_FLAGS)) + return 0; + if (filter & (is_rev_argument(arg) ? DO_REVS : DO_NOREV)) { + show(arg); + return 1; + } + return 0; +} + +static void show_default(void) +{ + char *s = def; + + if (s) { + unsigned char sha1[20]; + + def = NULL; + if (!get_sha1(s, sha1)) { + show_rev(NORMAL, sha1, s); + return; + } + } +} + +static int show_reference(const char *refname, const unsigned char *sha1) +{ + show_rev(NORMAL, sha1, refname); + return 0; +} + +static void show_datestring(const char *flag, const char *datestr) +{ + static char buffer[100]; + + /* 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)); + show(buffer); +} + +static int show_file(const char *arg) +{ + show_default(); + if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) { + show(arg); + return 1; + } + return 0; +} + +int cmd_rev_parse(int argc, const char **argv, char **envp) +{ + int i, as_is = 0, verify = 0; + unsigned char sha1[20]; + const char *prefix = setup_git_directory(); + + git_config(git_default_config); + + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + char *dotdot; + + if (as_is) { + if (show_file(arg) && as_is < 2) + verify_filename(prefix, arg); + continue; + } + if (!strcmp(arg,"-n")) { + if (++i >= argc) + die("-n requires an argument"); + if ((filter & DO_FLAGS) && (filter & DO_REVS)) { + show(arg); + show(argv[i]); + } + continue; + } + if (!strncmp(arg,"-n",2)) { + if ((filter & DO_FLAGS) && (filter & DO_REVS)) + show(arg); + continue; + } + + if (*arg == '-') { + if (!strcmp(arg, "--")) { + as_is = 2; + /* Pass on the "--" if we show anything but files.. */ + if (filter & (DO_FLAGS | DO_REVS)) + show_file(arg); + continue; + } + if (!strcmp(arg, "--default")) { + def = argv[i+1]; + i++; + continue; + } + if (!strcmp(arg, "--revs-only")) { + filter &= ~DO_NOREV; + continue; + } + if (!strcmp(arg, "--no-revs")) { + filter &= ~DO_REVS; + continue; + } + if (!strcmp(arg, "--flags")) { + filter &= ~DO_NONFLAGS; + continue; + } + if (!strcmp(arg, "--no-flags")) { + filter &= ~DO_FLAGS; + continue; + } + if (!strcmp(arg, "--verify")) { + filter &= ~(DO_FLAGS|DO_NOREV); + verify = 1; + continue; + } + if (!strcmp(arg, "--short") || + !strncmp(arg, "--short=", 8)) { + filter &= ~(DO_FLAGS|DO_NOREV); + verify = 1; + abbrev = DEFAULT_ABBREV; + if (arg[7] == '=') + abbrev = strtoul(arg + 8, NULL, 10); + if (abbrev < MINIMUM_ABBREV) + abbrev = MINIMUM_ABBREV; + else if (40 <= abbrev) + abbrev = 40; + continue; + } + if (!strcmp(arg, "--sq")) { + output_sq = 1; + continue; + } + if (!strcmp(arg, "--not")) { + show_type ^= REVERSED; + continue; + } + if (!strcmp(arg, "--symbolic")) { + symbolic = 1; + continue; + } + if (!strcmp(arg, "--all")) { + for_each_ref(show_reference); + continue; + } + if (!strcmp(arg, "--branches")) { + for_each_branch_ref(show_reference); + continue; + } + if (!strcmp(arg, "--tags")) { + for_each_tag_ref(show_reference); + continue; + } + if (!strcmp(arg, "--remotes")) { + for_each_remote_ref(show_reference); + continue; + } + if (!strcmp(arg, "--show-prefix")) { + if (prefix) + puts(prefix); + continue; + } + if (!strcmp(arg, "--show-cdup")) { + const char *pfx = prefix; + while (pfx) { + pfx = strchr(pfx, '/'); + if (pfx) { + pfx++; + printf("../"); + } + } + putchar('\n'); + continue; + } + if (!strcmp(arg, "--git-dir")) { + const char *gitdir = getenv(GIT_DIR_ENVIRONMENT); + static char cwd[PATH_MAX]; + if (gitdir) { + puts(gitdir); + continue; + } + if (!prefix) { + puts(".git"); + continue; + } + if (!getcwd(cwd, PATH_MAX)) + die("unable to get current working directory"); + printf("%s/.git\n", cwd); + continue; + } + if (!strncmp(arg, "--since=", 8)) { + show_datestring("--max-age=", arg+8); + continue; + } + if (!strncmp(arg, "--after=", 8)) { + show_datestring("--max-age=", arg+8); + continue; + } + if (!strncmp(arg, "--before=", 9)) { + show_datestring("--min-age=", arg+9); + continue; + } + if (!strncmp(arg, "--until=", 8)) { + show_datestring("--min-age=", arg+8); + continue; + } + if (show_flag(arg) && verify) + die("Needed a single revision"); + continue; + } + + /* Not a flag argument */ + dotdot = strstr(arg, ".."); + if (dotdot) { + unsigned char end[20]; + char *next = dotdot + 2; + char *this = arg; + *dotdot = 0; + if (!*next) + next = "HEAD"; + if (dotdot == arg) + this = "HEAD"; + if (!get_sha1(this, sha1) && !get_sha1(next, end)) { + show_rev(NORMAL, end, next); + show_rev(REVERSED, sha1, this); + continue; + } + *dotdot = '.'; + } + if (!get_sha1(arg, sha1)) { + show_rev(NORMAL, sha1, arg); + continue; + } + if (*arg == '^' && !get_sha1(arg+1, sha1)) { + show_rev(REVERSED, sha1, arg+1); + continue; + } + as_is = 1; + if (!show_file(arg)) + continue; + if (verify) + die("Needed a single revision"); + verify_filename(prefix, arg); + } + show_default(); + if (verify && revs_count != 1) + die("Needed a single revision"); + return 0; +} diff --git a/builtin.h b/builtin.h index 738ec3d..ffa9340 100644 --- a/builtin.h +++ b/builtin.h @@ -43,5 +43,6 @@ extern int cmd_diff_index(int argc, const char **argv, char **envp); extern int cmd_diff_stages(int argc, const char **argv, char **envp); extern int cmd_diff_tree(int argc, const char **argv, char **envp); extern int cmd_cat_file(int argc, const char **argv, char **envp); +extern int cmd_rev_parse(int argc, const char **argv, char **envp); #endif diff --git a/git.c b/git.c index 10ea934..bc463c9 100644 --- a/git.c +++ b/git.c @@ -69,7 +69,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp) { "diff-index", cmd_diff_index }, { "diff-stages", cmd_diff_stages }, { "diff-tree", cmd_diff_tree }, - { "cat-file", cmd_cat_file } + { "cat-file", cmd_cat_file }, + { "rev-parse", cmd_rev_parse } }; int i; diff --git a/rev-parse.c b/rev-parse.c deleted file mode 100644 index 4e2d9fb..0000000 --- a/rev-parse.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * rev-parse.c - * - * Copyright (C) Linus Torvalds, 2005 - */ -#include "cache.h" -#include "commit.h" -#include "refs.h" -#include "quote.h" - -#define DO_REVS 1 -#define DO_NOREV 2 -#define DO_FLAGS 4 -#define DO_NONFLAGS 8 -static int filter = ~0; - -static char *def = NULL; - -#define NORMAL 0 -#define REVERSED 1 -static int show_type = NORMAL; -static int symbolic = 0; -static int abbrev = 0; -static int output_sq = 0; - -static int revs_count = 0; - -/* - * Some arguments are relevant "revision" arguments, - * others are about output format or other details. - * This sorts it all out. - */ -static int is_rev_argument(const char *arg) -{ - static const char *rev_args[] = { - "--all", - "--bisect", - "--dense", - "--branches", - "--header", - "--max-age=", - "--max-count=", - "--min-age=", - "--no-merges", - "--objects", - "--objects-edge", - "--parents", - "--pretty", - "--remotes", - "--sparse", - "--tags", - "--topo-order", - "--date-order", - "--unpacked", - NULL - }; - const char **p = rev_args; - - /* accept -, like traditional "head" */ - if ((*arg == '-') && isdigit(arg[1])) - return 1; - - for (;;) { - const char *str = *p++; - int len; - if (!str) - return 0; - len = strlen(str); - if (!strcmp(arg, str) || - (str[len-1] == '=' && !strncmp(arg, str, len))) - return 1; - } -} - -/* Output argument as a string, either SQ or normal */ -static void show(const char *arg) -{ - if (output_sq) { - int sq = '\'', ch; - - putchar(sq); - while ((ch = *arg++)) { - if (ch == sq) - fputs("'\\'", stdout); - putchar(ch); - } - putchar(sq); - putchar(' '); - } - else - puts(arg); -} - -/* Output a revision, only if filter allows it */ -static void show_rev(int type, const unsigned char *sha1, const char *name) -{ - if (!(filter & DO_REVS)) - return; - def = NULL; - revs_count++; - - if (type != show_type) - putchar('^'); - if (symbolic && name) - show(name); - else if (abbrev) - show(find_unique_abbrev(sha1, abbrev)); - else - show(sha1_to_hex(sha1)); -} - -/* Output a flag, only if filter allows it. */ -static int show_flag(char *arg) -{ - if (!(filter & DO_FLAGS)) - return 0; - if (filter & (is_rev_argument(arg) ? DO_REVS : DO_NOREV)) { - show(arg); - return 1; - } - return 0; -} - -static void show_default(void) -{ - char *s = def; - - if (s) { - unsigned char sha1[20]; - - def = NULL; - if (!get_sha1(s, sha1)) { - show_rev(NORMAL, sha1, s); - return; - } - } -} - -static int show_reference(const char *refname, const unsigned char *sha1) -{ - show_rev(NORMAL, sha1, refname); - return 0; -} - -static void show_datestring(const char *flag, const char *datestr) -{ - static char buffer[100]; - - /* 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)); - show(buffer); -} - -static int show_file(const char *arg) -{ - show_default(); - if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) { - show(arg); - return 1; - } - return 0; -} - -int main(int argc, char **argv) -{ - int i, as_is = 0, verify = 0; - unsigned char sha1[20]; - const char *prefix = setup_git_directory(); - - git_config(git_default_config); - - for (i = 1; i < argc; i++) { - char *arg = argv[i]; - char *dotdot; - - if (as_is) { - if (show_file(arg) && as_is < 2) - verify_filename(prefix, arg); - continue; - } - if (!strcmp(arg,"-n")) { - if (++i >= argc) - die("-n requires an argument"); - if ((filter & DO_FLAGS) && (filter & DO_REVS)) { - show(arg); - show(argv[i]); - } - continue; - } - if (!strncmp(arg,"-n",2)) { - if ((filter & DO_FLAGS) && (filter & DO_REVS)) - show(arg); - continue; - } - - if (*arg == '-') { - if (!strcmp(arg, "--")) { - as_is = 2; - /* Pass on the "--" if we show anything but files.. */ - if (filter & (DO_FLAGS | DO_REVS)) - show_file(arg); - continue; - } - if (!strcmp(arg, "--default")) { - def = argv[i+1]; - i++; - continue; - } - if (!strcmp(arg, "--revs-only")) { - filter &= ~DO_NOREV; - continue; - } - if (!strcmp(arg, "--no-revs")) { - filter &= ~DO_REVS; - continue; - } - if (!strcmp(arg, "--flags")) { - filter &= ~DO_NONFLAGS; - continue; - } - if (!strcmp(arg, "--no-flags")) { - filter &= ~DO_FLAGS; - continue; - } - if (!strcmp(arg, "--verify")) { - filter &= ~(DO_FLAGS|DO_NOREV); - verify = 1; - continue; - } - if (!strcmp(arg, "--short") || - !strncmp(arg, "--short=", 8)) { - filter &= ~(DO_FLAGS|DO_NOREV); - verify = 1; - abbrev = DEFAULT_ABBREV; - if (arg[7] == '=') - abbrev = strtoul(arg + 8, NULL, 10); - if (abbrev < MINIMUM_ABBREV) - abbrev = MINIMUM_ABBREV; - else if (40 <= abbrev) - abbrev = 40; - continue; - } - if (!strcmp(arg, "--sq")) { - output_sq = 1; - continue; - } - if (!strcmp(arg, "--not")) { - show_type ^= REVERSED; - continue; - } - if (!strcmp(arg, "--symbolic")) { - symbolic = 1; - continue; - } - if (!strcmp(arg, "--all")) { - for_each_ref(show_reference); - continue; - } - if (!strcmp(arg, "--branches")) { - for_each_branch_ref(show_reference); - continue; - } - if (!strcmp(arg, "--tags")) { - for_each_tag_ref(show_reference); - continue; - } - if (!strcmp(arg, "--remotes")) { - for_each_remote_ref(show_reference); - continue; - } - if (!strcmp(arg, "--show-prefix")) { - if (prefix) - puts(prefix); - continue; - } - if (!strcmp(arg, "--show-cdup")) { - const char *pfx = prefix; - while (pfx) { - pfx = strchr(pfx, '/'); - if (pfx) { - pfx++; - printf("../"); - } - } - putchar('\n'); - continue; - } - if (!strcmp(arg, "--git-dir")) { - const char *gitdir = getenv(GIT_DIR_ENVIRONMENT); - static char cwd[PATH_MAX]; - if (gitdir) { - puts(gitdir); - continue; - } - if (!prefix) { - puts(".git"); - continue; - } - if (!getcwd(cwd, PATH_MAX)) - die("unable to get current working directory"); - printf("%s/.git\n", cwd); - continue; - } - if (!strncmp(arg, "--since=", 8)) { - show_datestring("--max-age=", arg+8); - continue; - } - if (!strncmp(arg, "--after=", 8)) { - show_datestring("--max-age=", arg+8); - continue; - } - if (!strncmp(arg, "--before=", 9)) { - show_datestring("--min-age=", arg+9); - continue; - } - if (!strncmp(arg, "--until=", 8)) { - show_datestring("--min-age=", arg+8); - continue; - } - if (show_flag(arg) && verify) - die("Needed a single revision"); - continue; - } - - /* Not a flag argument */ - dotdot = strstr(arg, ".."); - if (dotdot) { - unsigned char end[20]; - char *next = dotdot + 2; - char *this = arg; - *dotdot = 0; - if (!*next) - next = "HEAD"; - if (dotdot == arg) - this = "HEAD"; - if (!get_sha1(this, sha1) && !get_sha1(next, end)) { - show_rev(NORMAL, end, next); - show_rev(REVERSED, sha1, this); - continue; - } - *dotdot = '.'; - } - if (!get_sha1(arg, sha1)) { - show_rev(NORMAL, sha1, arg); - continue; - } - if (*arg == '^' && !get_sha1(arg+1, sha1)) { - show_rev(REVERSED, sha1, arg+1); - continue; - } - as_is = 1; - if (!show_file(arg)) - continue; - if (verify) - die("Needed a single revision"); - verify_filename(prefix, arg); - } - show_default(); - if (verify && revs_count != 1) - die("Needed a single revision"); - return 0; -} -- cgit v0.10.2-6-g49f6