int git_open_log(GIT_LOG * handle, char * arg) { struct rev_info *p_Rev; char ** argv=0; int argc=0; unsigned int i=0; struct setup_revision_opt opt; /* clear flags */ unsigned int obj_size = get_max_object_index(); for(i =0; i<obj_size; i++) { struct object *ob= get_indexed_object(i); if(ob) { ob->flags=0; if (ob->parsed && ob->type == OBJ_COMMIT) { struct commit* commit = (struct commit*)ob; free_commit_list(commit->parents); commit->parents = NULL; if (commit->tree) free_tree_buffer(commit->tree); commit->tree = NULL; ob->parsed = 0; } } } if(arg != NULL) argv = strtoargv(arg,&argc); if (!argv) return -1; p_Rev = malloc(sizeof(struct rev_info)); if (p_Rev == NULL) { free(argv); return -1; } memset(p_Rev,0,sizeof(struct rev_info)); invalidate_ref_cache(NULL); init_revisions(p_Rev, g_prefix); p_Rev->diff = 1; memset(&opt, 0, sizeof(opt)); opt.def = "HEAD"; cmd_log_init(argc, argv, g_prefix,p_Rev,&opt); p_Rev->pPrivate = argv; *handle = p_Rev; return 0; }
static void check_objects(void) { unsigned i, max; max = get_max_object_index(); for (i = 0; i < max; i++) check_object(get_indexed_object(i)); }
int git_open_log(GIT_LOG * handle, char * arg) { struct rev_info *p_Rev; char ** argv=0; int argc=0; unsigned int i=0; struct setup_revision_opt opt; /* clear flags */ unsigned int obj_size = get_max_object_index(); for(i =0; i<obj_size; i++) { struct object *ob= get_indexed_object(i); if(ob) ob->flags=0; } if(arg != NULL) argv = strtoargv(arg,&argc); if (!argv) return -1; p_Rev = malloc(sizeof(struct rev_info)); if (p_Rev == NULL) { free(argv); return -1; } memset(p_Rev,0,sizeof(struct rev_info)); invalidate_ref_cache(NULL); init_revisions(p_Rev, g_prefix); p_Rev->diff = 1; memset(&opt, 0, sizeof(opt)); opt.def = "HEAD"; cmd_log_init(argc, argv, g_prefix,p_Rev,&opt); p_Rev->pPrivate = argv; *handle = p_Rev; return 0; }
static void check_connectivity(void) { int i, max; /* Traverse the pending reachable objects */ traverse_reachable(); /* Look up all the requirements, warn about missing objects.. */ max = get_max_object_index(); if (verbose) fprintf(stderr, "Checking connectivity (%d objects)\n", max); for (i = 0; i < max; i++) { struct object *obj = get_indexed_object(i); if (obj) check_object(obj); } }
static int get_reachable_list(struct object_array *src, struct object_array *reachable) { struct child_process cmd = CHILD_PROCESS_INIT; int i; struct object *o; char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */ const unsigned hexsz = the_hash_algo->hexsz; if (do_reachable_revlist(&cmd, src, reachable) < 0) return -1; while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) { struct object_id sha1; const char *p; if (parse_oid_hex(namebuf, &sha1, &p) || *p != '\n') break; o = lookup_object(sha1.hash); if (o && o->type == OBJ_COMMIT) { o->flags &= ~TMP_MARK; } } for (i = get_max_object_index(); 0 < i; i--) { o = get_indexed_object(i - 1); if (o && o->type == OBJ_COMMIT && (o->flags & TMP_MARK)) { add_object_array(o, NULL, reachable); o->flags &= ~TMP_MARK; } } close(cmd.out); if (finish_command(&cmd)) return -1; return 0; }
static int get_reachable_list(struct object_array *src, struct object_array *reachable) { struct child_process cmd = CHILD_PROCESS_INIT; int i; struct object *o; char namebuf[42]; /* ^ + SHA-1 + LF */ if (do_reachable_revlist(&cmd, src, reachable) < 0) return -1; while ((i = read_in_full(cmd.out, namebuf, 41)) == 41) { struct object_id sha1; if (namebuf[40] != '\n' || get_oid_hex(namebuf, &sha1)) break; o = lookup_object(sha1.hash); if (o && o->type == OBJ_COMMIT) { o->flags &= ~TMP_MARK; } } for (i = get_max_object_index(); 0 < i; i--) { o = get_indexed_object(i - 1); if (o && o->type == OBJ_COMMIT && (o->flags & TMP_MARK)) { add_object_array(o, NULL, reachable); o->flags &= ~TMP_MARK; } } close(cmd.out); if (finish_command(&cmd)) return -1; return 0; }
static void check_non_tip(void) { static const char *argv[] = { "rev-list", "--stdin", NULL, }; static struct child_process cmd = CHILD_PROCESS_INIT; struct object *o; char namebuf[42]; /* ^ + SHA-1 + LF */ int i; /* In the normal in-process case non-tip request can never happen */ if (!stateless_rpc) goto error; cmd.argv = argv; cmd.git_cmd = 1; cmd.no_stderr = 1; cmd.in = -1; cmd.out = -1; if (start_command(&cmd)) goto error; /* * If rev-list --stdin encounters an unknown commit, it * terminates, which will cause SIGPIPE in the write loop * below. */ sigchain_push(SIGPIPE, SIG_IGN); namebuf[0] = '^'; namebuf[41] = '\n'; for (i = get_max_object_index(); 0 < i; ) { o = get_indexed_object(--i); if (!o) continue; if (!is_our_ref(o)) continue; memcpy(namebuf + 1, sha1_to_hex(o->sha1), 40); if (write_in_full(cmd.in, namebuf, 42) < 0) goto error; } namebuf[40] = '\n'; for (i = 0; i < want_obj.nr; i++) { o = want_obj.objects[i].item; if (is_our_ref(o)) continue; memcpy(namebuf, sha1_to_hex(o->sha1), 40); if (write_in_full(cmd.in, namebuf, 41) < 0) goto error; } close(cmd.in); sigchain_pop(SIGPIPE); /* * The commits out of the rev-list are not ancestors of * our ref. */ i = read_in_full(cmd.out, namebuf, 1); if (i) goto error; close(cmd.out); /* * rev-list may have died by encountering a bad commit * in the history, in which case we do want to bail out * even when it showed no commit. */ if (finish_command(&cmd)) goto error; /* All the non-tip ones are ancestors of what we advertised */ return; error: /* Pick one of them (we know there at least is one) */ for (i = 0; i < want_obj.nr; i++) { o = want_obj.objects[i].item; if (!is_our_ref(o)) die("git upload-pack: not our ref %s", sha1_to_hex(o->sha1)); } }
int cmd_name_rev(int argc, const char **argv, const char *prefix) { struct object_array revs = OBJECT_ARRAY_INIT; int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0; struct name_ref_data data = { 0, 0, NULL }; struct option opts[] = { OPT_BOOL(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")), OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")), OPT_STRING(0, "refs", &data.ref_filter, N_("pattern"), N_("only use refs matching <pattern>")), OPT_GROUP(""), OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")), OPT_BOOL(0, "stdin", &transform_stdin, N_("read from stdin")), OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")), OPT_BOOL(0, "always", &always, N_("show abbreviated commit object as fallback")), { /* A Hidden OPT_BOOL */ OPTION_SET_INT, 0, "peel-tag", &peel_tag, NULL, N_("dereference tags in the input (internal use)"), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1, }, OPT_END(), }; git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0); if (all + transform_stdin + !!argc > 1) { error("Specify either a list, or --all, not both!"); usage_with_options(name_rev_usage, opts); } if (all || transform_stdin) cutoff = 0; for (; argc; argc--, argv++) { unsigned char sha1[20]; struct object *object; struct commit *commit; if (get_sha1(*argv, sha1)) { fprintf(stderr, "Could not get sha1 for %s. Skipping.\n", *argv); continue; } commit = NULL; object = parse_object(sha1); if (object) { struct object *peeled = deref_tag(object, *argv, 0); if (peeled && peeled->type == OBJ_COMMIT) commit = (struct commit *)peeled; } if (!object) { fprintf(stderr, "Could not get object for %s. Skipping.\n", *argv); continue; } if (commit) { if (cutoff > commit->date) cutoff = commit->date; } if (peel_tag) { if (!commit) { fprintf(stderr, "Could not get commit for %s. Skipping.\n", *argv); continue; } object = (struct object *)commit; } add_object_array(object, *argv, &revs); } if (cutoff) cutoff = cutoff - CUTOFF_DATE_SLOP; for_each_ref(name_ref, &data); if (transform_stdin) { char buffer[2048]; while (!feof(stdin)) { char *p = fgets(buffer, sizeof(buffer), stdin); if (!p) break; name_rev_line(p, &data); } } 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 || obj->type != OBJ_COMMIT) continue; show_name(obj, NULL, always, allow_undefined, data.name_only); } } else { int i; for (i = 0; i < revs.nr; i++) show_name(revs.objects[i].item, revs.objects[i].name, always, allow_undefined, data.name_only); } return 0; }
int cmd_name_rev(int argc, const char **argv, const char *prefix) { struct object_array revs = { 0, 0, NULL }; int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0; struct name_ref_data data = { 0, 0, NULL }; struct option opts[] = { OPT_BOOLEAN(0, "name-only", &data.name_only, "print only names (no SHA-1)"), OPT_BOOLEAN(0, "tags", &data.tags_only, "only use tags to name the commits"), OPT_STRING(0, "refs", &data.ref_filter, "pattern", "only use refs matching <pattern>"), OPT_GROUP(""), OPT_BOOLEAN(0, "all", &all, "list all commits reachable from all refs"), OPT_BOOLEAN(0, "stdin", &transform_stdin, "read from stdin"), OPT_BOOLEAN(0, "undefined", &allow_undefined, "allow to print `undefined` names"), OPT_BOOLEAN(0, "always", &always, "show abbreviated commit object as fallback"), OPT_END(), }; git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0); if (!!all + !!transform_stdin + !!argc > 1) { error("Specify either a list, or --all, not both!"); usage_with_options(name_rev_usage, opts); } if (all || transform_stdin) cutoff = 0; for (; argc; argc--, argv++) { unsigned char sha1[20]; struct object *o; struct commit *commit; 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); } if (cutoff) cutoff = cutoff - CUTOFF_DATE_SLOP; for_each_ref(name_ref, &data); if (transform_stdin) { char buffer[2048]; while (!feof(stdin)) { char *p = fgets(buffer, sizeof(buffer), stdin); if (!p) break; name_rev_line(p, &data); } } 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; show_name(obj, NULL, always, allow_undefined, data.name_only); } } else { int i; for (i = 0; i < revs.nr; i++) show_name(revs.objects[i].item, revs.objects[i].name, always, allow_undefined, data.name_only); } return 0; }
/* * on successful case, it's up to the caller to close cmd->out */ static int do_reachable_revlist(struct child_process *cmd, struct object_array *src, struct object_array *reachable) { static const char *argv[] = { "rev-list", "--stdin", NULL, }; struct object *o; char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */ int i; cmd->argv = argv; cmd->git_cmd = 1; cmd->no_stderr = 1; cmd->in = -1; cmd->out = -1; /* * If the next rev-list --stdin encounters an unknown commit, * it terminates, which will cause SIGPIPE in the write loop * below. */ sigchain_push(SIGPIPE, SIG_IGN); if (start_command(cmd)) goto error; namebuf[0] = '^'; namebuf[GIT_SHA1_HEXSZ + 1] = '\n'; for (i = get_max_object_index(); 0 < i; ) { o = get_indexed_object(--i); if (!o) continue; if (reachable && o->type == OBJ_COMMIT) o->flags &= ~TMP_MARK; if (!is_our_ref(o)) continue; memcpy(namebuf + 1, oid_to_hex(&o->oid), GIT_SHA1_HEXSZ); if (write_in_full(cmd->in, namebuf, GIT_SHA1_HEXSZ + 2) < 0) goto error; } namebuf[GIT_SHA1_HEXSZ] = '\n'; for (i = 0; i < src->nr; i++) { o = src->objects[i].item; if (is_our_ref(o)) { if (reachable) add_object_array(o, NULL, reachable); continue; } if (reachable && o->type == OBJ_COMMIT) o->flags |= TMP_MARK; memcpy(namebuf, oid_to_hex(&o->oid), GIT_SHA1_HEXSZ); if (write_in_full(cmd->in, namebuf, GIT_SHA1_HEXSZ + 1) < 0) goto error; } close(cmd->in); cmd->in = -1; sigchain_pop(SIGPIPE); return 0; error: sigchain_pop(SIGPIPE); if (cmd->in >= 0) close(cmd->in); if (cmd->out >= 0) close(cmd->out); return -1; }