From: Matthias Kestenholz Date: Thu, 3 Aug 2006 15:24:35 +0000 (+0200) Subject: Make git-name-rev a builtin X-Git-Tag: v1.4.3-rc1~278^2~9 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=d6b64ed0f3549f56c4d948dc2c0f12abc52fd6c9;p=git.git Make git-name-rev a builtin Signed-off-by: Matthias Kestenholz Signed-off-by: Junio C Hamano --- diff --git a/Makefile b/Makefile index 700c77f56..132c9cf01 100644 --- a/Makefile +++ b/Makefile @@ -185,7 +185,7 @@ PROGRAMS = \ git-unpack-objects$X git-update-server-info$X \ git-upload-pack$X git-verify-pack$X \ git-symbolic-ref$X \ - git-name-rev$X git-pack-redundant$X git-var$X \ + git-pack-redundant$X git-var$X \ git-describe$X git-merge-tree$X git-blame$X git-imap-send$X BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$X \ @@ -198,7 +198,7 @@ BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$X \ git-apply$X git-show-branch$X git-diff-files$X git-update-index$X \ git-diff-index$X git-diff-stages$X git-diff-tree$X git-cat-file$X \ git-fmt-merge-msg$X git-prune$X git-mv$X git-prune-packed$X \ - git-repo-config$X + git-repo-config$X git-name-rev$X # what 'all' will build and 'install' will install, in gitexecdir ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS) @@ -255,7 +255,8 @@ BUILTIN_OBJS = \ builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \ builtin-cat-file.o builtin-mailsplit.o builtin-stripspace.o \ builtin-update-ref.o builtin-fmt-merge-msg.o builtin-prune.o \ - builtin-mv.o builtin-prune-packed.o builtin-repo-config.o + builtin-mv.o builtin-prune-packed.o builtin-repo-config.o \ + builtin-name-rev.o GITLIBS = $(LIB_FILE) $(XDIFF_LIB) LIBS = $(GITLIBS) -lz diff --git a/builtin-name-rev.c b/builtin-name-rev.c new file mode 100644 index 000000000..571bba481 --- /dev/null +++ b/builtin-name-rev.c @@ -0,0 +1,256 @@ +#include +#include "builtin.h" +#include "cache.h" +#include "commit.h" +#include "tag.h" +#include "refs.h" + +static const char name_rev_usage[] = + "git-name-rev [--tags] ( --all | --stdin | committish [committish...] )\n"; + +typedef struct rev_name { + const char *tip_name; + int merge_traversals; + int generation; +} rev_name; + +static long cutoff = LONG_MAX; + +static void name_rev(struct commit *commit, + const char *tip_name, int merge_traversals, int generation, + int deref) +{ + struct rev_name *name = (struct rev_name *)commit->util; + struct commit_list *parents; + int parent_number = 1; + + if (!commit->object.parsed) + parse_commit(commit); + + if (commit->date < cutoff) + return; + + if (deref) { + char *new_name = xmalloc(strlen(tip_name)+3); + strcpy(new_name, tip_name); + strcat(new_name, "^0"); + tip_name = new_name; + + if (generation) + die("generation: %d, but deref?", generation); + } + + if (name == NULL) { + name = xmalloc(sizeof(rev_name)); + commit->util = name; + goto copy_data; + } else if (name->merge_traversals > merge_traversals || + (name->merge_traversals == merge_traversals && + name->generation > generation)) { +copy_data: + name->tip_name = tip_name; + name->merge_traversals = merge_traversals; + name->generation = generation; + } else + return; + + for (parents = commit->parents; + parents; + parents = parents->next, parent_number++) { + if (parent_number > 1) { + char *new_name = xmalloc(strlen(tip_name)+8); + + if (generation > 0) + sprintf(new_name, "%s~%d^%d", tip_name, + generation, parent_number); + else + sprintf(new_name, "%s^%d", tip_name, parent_number); + + name_rev(parents->item, new_name, + merge_traversals + 1 , 0, 0); + } else { + name_rev(parents->item, tip_name, merge_traversals, + generation + 1, 0); + } + } +} + +static int tags_only = 0; + +static int name_ref(const char *path, const unsigned char *sha1) +{ + struct object *o = parse_object(sha1); + int deref = 0; + + if (tags_only && strncmp(path, "refs/tags/", 10)) + return 0; + + while (o && o->type == OBJ_TAG) { + struct tag *t = (struct tag *) o; + if (!t->tagged) + break; /* broken repository */ + o = parse_object(t->tagged->sha1); + deref = 1; + } + if (o && o->type == OBJ_COMMIT) { + struct commit *commit = (struct commit *)o; + + if (!strncmp(path, "refs/heads/", 11)) + path = path + 11; + else if (!strncmp(path, "refs/", 5)) + path = path + 5; + + name_rev(commit, strdup(path), 0, 0, deref); + } + return 0; +} + +/* returns a static buffer */ +static const char* get_rev_name(struct object *o) +{ + static char buffer[1024]; + struct rev_name *n; + struct commit *c; + + if (o->type != OBJ_COMMIT) + return "undefined"; + c = (struct commit *) o; + n = c->util; + if (!n) + return "undefined"; + + if (!n->generation) + return n->tip_name; + + snprintf(buffer, sizeof(buffer), "%s~%d", n->tip_name, n->generation); + + return buffer; +} + +int cmd_name_rev(int argc, const char **argv, const char *prefix) +{ + struct object_array revs = { 0, 0, NULL }; + int as_is = 0, all = 0, transform_stdin = 0; + + git_config(git_default_config); + + if (argc < 2) + usage(name_rev_usage); + + for (--argc, ++argv; argc; --argc, ++argv) { + unsigned char sha1[20]; + struct object *o; + struct commit *commit; + + if (!as_is && (*argv)[0] == '-') { + if (!strcmp(*argv, "--")) { + as_is = 1; + continue; + } else if (!strcmp(*argv, "--tags")) { + tags_only = 1; + continue; + } else if (!strcmp(*argv, "--all")) { + if (argc > 1) + die("Specify either a list, or --all, not both!"); + all = 1; + cutoff = 0; + continue; + } else if (!strcmp(*argv, "--stdin")) { + if (argc > 1) + die("Specify either a list, or --stdin, not both!"); + transform_stdin = 1; + cutoff = 0; + continue; + } + usage(name_rev_usage); + } + + if (get_sha1(*argv, sha1)) { + fprintf(stderr, "Could not get sha1 for %s. Skipping.\n", + *argv); + continue; + } + + o = deref_tag(parse_object(sha1), *argv, 0); + if (!o || o->type != OBJ_COMMIT) { + fprintf(stderr, "Could not get commit for %s. Skipping.\n", + *argv); + continue; + } + + commit = (struct commit *)o; + + if (cutoff > commit->date) + cutoff = commit->date; + + add_object_array((struct object *)commit, *argv, &revs); + } + + for_each_ref(name_ref); + + if (transform_stdin) { + char buffer[2048]; + char *p, *p_start; + + while (!feof(stdin)) { + int forty = 0; + p = fgets(buffer, sizeof(buffer), stdin); + if (!p) + break; + + for (p_start = p; *p; p++) { +#define ishex(x) (isdigit((x)) || ((x) >= 'a' && (x) <= 'f')) + if (!ishex(*p)) + forty = 0; + else if (++forty == 40 && + !ishex(*(p+1))) { + unsigned char sha1[40]; + const char *name = "undefined"; + char c = *(p+1); + + forty = 0; + + *(p+1) = 0; + if (!get_sha1(p - 39, sha1)) { + struct object *o = + lookup_object(sha1); + if (o) + name = get_rev_name(o); + } + *(p+1) = c; + + if (!strcmp(name, "undefined")) + continue; + + fwrite(p_start, p - p_start + 1, 1, + stdout); + printf(" (%s)", name); + p_start = p + 1; + } + } + + /* flush */ + if (p_start != p) + fwrite(p_start, p - p_start, 1, stdout); + } + } else if (all) { + int i, max; + + max = get_max_object_index(); + for (i = 0; i < max; i++) { + struct object * obj = get_indexed_object(i); + if (!obj) + continue; + printf("%s %s\n", sha1_to_hex(obj->sha1), get_rev_name(obj)); + } + } else { + int i; + for (i = 0; i < revs.nr; i++) + printf("%s %s\n", + revs.objects[i].name, + get_rev_name(revs.objects[i].item)); + } + + return 0; +} + diff --git a/builtin.h b/builtin.h index 26ebcaf21..d1d9dc14f 100644 --- a/builtin.h +++ b/builtin.h @@ -49,6 +49,7 @@ extern int cmd_update_ref(int argc, const char **argv, const char *prefix); extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix); extern int cmd_mv(int argc, const char **argv, const char *prefix); extern int cmd_repo_config(int argc, const char **argv, const char *prefix); +extern int cmd_name_rev(int argc, const char **argv, const char *prefix); extern int cmd_write_tree(int argc, const char **argv, const char *prefix); extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix); diff --git a/git.c b/git.c index 6e72a893b..501a7815f 100644 --- a/git.c +++ b/git.c @@ -265,6 +265,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp) { "mv", cmd_mv, NEEDS_PREFIX }, { "prune-packed", cmd_prune_packed, NEEDS_PREFIX }, { "repo-config", cmd_repo_config }, + { "name-rev", cmd_name_rev, NEEDS_PREFIX }, }; int i; diff --git a/name-rev.c b/name-rev.c deleted file mode 100644 index f92f14e32..000000000 --- a/name-rev.c +++ /dev/null @@ -1,256 +0,0 @@ -#include -#include "cache.h" -#include "commit.h" -#include "tag.h" -#include "refs.h" - -static const char name_rev_usage[] = - "git-name-rev [--tags] ( --all | --stdin | committish [committish...] )\n"; - -typedef struct rev_name { - const char *tip_name; - int merge_traversals; - int generation; -} rev_name; - -static long cutoff = LONG_MAX; - -static void name_rev(struct commit *commit, - const char *tip_name, int merge_traversals, int generation, - int deref) -{ - struct rev_name *name = (struct rev_name *)commit->util; - struct commit_list *parents; - int parent_number = 1; - - if (!commit->object.parsed) - parse_commit(commit); - - if (commit->date < cutoff) - return; - - if (deref) { - char *new_name = xmalloc(strlen(tip_name)+3); - strcpy(new_name, tip_name); - strcat(new_name, "^0"); - tip_name = new_name; - - if (generation) - die("generation: %d, but deref?", generation); - } - - if (name == NULL) { - name = xmalloc(sizeof(rev_name)); - commit->util = name; - goto copy_data; - } else if (name->merge_traversals > merge_traversals || - (name->merge_traversals == merge_traversals && - name->generation > generation)) { -copy_data: - name->tip_name = tip_name; - name->merge_traversals = merge_traversals; - name->generation = generation; - } else - return; - - for (parents = commit->parents; - parents; - parents = parents->next, parent_number++) { - if (parent_number > 1) { - char *new_name = xmalloc(strlen(tip_name)+8); - - if (generation > 0) - sprintf(new_name, "%s~%d^%d", tip_name, - generation, parent_number); - else - sprintf(new_name, "%s^%d", tip_name, parent_number); - - name_rev(parents->item, new_name, - merge_traversals + 1 , 0, 0); - } else { - name_rev(parents->item, tip_name, merge_traversals, - generation + 1, 0); - } - } -} - -static int tags_only = 0; - -static int name_ref(const char *path, const unsigned char *sha1) -{ - struct object *o = parse_object(sha1); - int deref = 0; - - if (tags_only && strncmp(path, "refs/tags/", 10)) - return 0; - - while (o && o->type == OBJ_TAG) { - struct tag *t = (struct tag *) o; - if (!t->tagged) - break; /* broken repository */ - o = parse_object(t->tagged->sha1); - deref = 1; - } - if (o && o->type == OBJ_COMMIT) { - struct commit *commit = (struct commit *)o; - - if (!strncmp(path, "refs/heads/", 11)) - path = path + 11; - else if (!strncmp(path, "refs/", 5)) - path = path + 5; - - name_rev(commit, strdup(path), 0, 0, deref); - } - return 0; -} - -/* returns a static buffer */ -static const char* get_rev_name(struct object *o) -{ - static char buffer[1024]; - struct rev_name *n; - struct commit *c; - - if (o->type != OBJ_COMMIT) - return "undefined"; - c = (struct commit *) o; - n = c->util; - if (!n) - return "undefined"; - - if (!n->generation) - return n->tip_name; - - snprintf(buffer, sizeof(buffer), "%s~%d", n->tip_name, n->generation); - - return buffer; -} - -int main(int argc, char **argv) -{ - struct object_array revs = { 0, 0, NULL }; - int as_is = 0, all = 0, transform_stdin = 0; - - setup_git_directory(); - git_config(git_default_config); - - if (argc < 2) - usage(name_rev_usage); - - for (--argc, ++argv; argc; --argc, ++argv) { - unsigned char sha1[20]; - struct object *o; - struct commit *commit; - - if (!as_is && (*argv)[0] == '-') { - if (!strcmp(*argv, "--")) { - as_is = 1; - continue; - } else if (!strcmp(*argv, "--tags")) { - tags_only = 1; - continue; - } else if (!strcmp(*argv, "--all")) { - if (argc > 1) - die("Specify either a list, or --all, not both!"); - all = 1; - cutoff = 0; - continue; - } else if (!strcmp(*argv, "--stdin")) { - if (argc > 1) - die("Specify either a list, or --stdin, not both!"); - transform_stdin = 1; - cutoff = 0; - continue; - } - usage(name_rev_usage); - } - - if (get_sha1(*argv, sha1)) { - fprintf(stderr, "Could not get sha1 for %s. Skipping.\n", - *argv); - continue; - } - - o = deref_tag(parse_object(sha1), *argv, 0); - if (!o || o->type != OBJ_COMMIT) { - fprintf(stderr, "Could not get commit for %s. Skipping.\n", - *argv); - continue; - } - - commit = (struct commit *)o; - - if (cutoff > commit->date) - cutoff = commit->date; - - add_object_array((struct object *)commit, *argv, &revs); - } - - for_each_ref(name_ref); - - if (transform_stdin) { - char buffer[2048]; - char *p, *p_start; - - while (!feof(stdin)) { - int forty = 0; - p = fgets(buffer, sizeof(buffer), stdin); - if (!p) - break; - - for (p_start = p; *p; p++) { -#define ishex(x) (isdigit((x)) || ((x) >= 'a' && (x) <= 'f')) - if (!ishex(*p)) - forty = 0; - else if (++forty == 40 && - !ishex(*(p+1))) { - unsigned char sha1[40]; - const char *name = "undefined"; - char c = *(p+1); - - forty = 0; - - *(p+1) = 0; - if (!get_sha1(p - 39, sha1)) { - struct object *o = - lookup_object(sha1); - if (o) - name = get_rev_name(o); - } - *(p+1) = c; - - if (!strcmp(name, "undefined")) - continue; - - fwrite(p_start, p - p_start + 1, 1, - stdout); - printf(" (%s)", name); - p_start = p + 1; - } - } - - /* flush */ - if (p_start != p) - fwrite(p_start, p - p_start, 1, stdout); - } - } else if (all) { - int i, max; - - max = get_max_object_index(); - for (i = 0; i < max; i++) { - struct object * obj = get_indexed_object(i); - if (!obj) - continue; - printf("%s %s\n", sha1_to_hex(obj->sha1), get_rev_name(obj)); - } - } else { - int i; - for (i = 0; i < revs.nr; i++) - printf("%s %s\n", - revs.objects[i].name, - get_rev_name(revs.objects[i].item)); - } - - return 0; -} -