static int prepare_submodule_summary(struct rev_info *rev, const char *path, struct commit *left, struct commit *right, int *fast_forward, int *fast_backward) { struct commit_list *merge_bases, *list; init_revisions(rev, NULL); setup_revisions(0, NULL, rev, NULL); rev->left_right = 1; rev->first_parent_only = 1; left->object.flags |= SYMMETRIC_LEFT; add_pending_object(rev, &left->object, path); add_pending_object(rev, &right->object, path); merge_bases = get_merge_bases(left, right, 1); if (merge_bases) { if (merge_bases->item == left) *fast_forward = 1; else if (merge_bases->item == right) *fast_backward = 1; } for (list = merge_bases; list; list = list->next) { list->item->object.flags |= UNINTERESTING; add_pending_object(rev, &list->item->object, sha1_to_hex(list->item->object.sha1)); } return prepare_revision_walk(rev); }
static void prepare_bases(struct base_tree_info *bases, struct commit *base, struct commit **list, int total) { struct commit *commit; struct rev_info revs; struct diff_options diffopt; int i; if (!base) return; diff_setup(&diffopt); DIFF_OPT_SET(&diffopt, RECURSIVE); diff_setup_done(&diffopt); oidcpy(&bases->base_commit, &base->object.oid); init_revisions(&revs, NULL); revs.max_parents = 1; revs.topo_order = 1; for (i = 0; i < total; i++) { list[i]->object.flags &= ~UNINTERESTING; add_pending_object(&revs, &list[i]->object, "rev_list"); list[i]->util = (void *)1; } base->object.flags |= UNINTERESTING; add_pending_object(&revs, &base->object, "base"); if (prepare_revision_walk(&revs)) die(_("revision walk setup failed")); /* * Traverse the commits list, get prerequisite patch ids * and stuff them in bases structure. */ while ((commit = get_revision(&revs)) != NULL) { unsigned char sha1[20]; struct object_id *patch_id; if (commit->util) continue; if (commit_patch_id(commit, &diffopt, sha1)) die(_("cannot get patch id")); ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id); patch_id = bases->patch_id + bases->nr_patch_id; hashcpy(patch_id->hash, sha1); bases->nr_patch_id++; } }
static int add_parents_only(struct rev_info *revs, const char *arg, int flags) { unsigned char sha1[20]; struct object *it; struct commit *commit; struct commit_list *parents; if (*arg == '^') { flags ^= UNINTERESTING; arg++; } if (get_sha1(arg, sha1)) return 0; while (1) { it = get_reference(revs, arg, sha1, 0); if (it->type != OBJ_TAG) break; if (!((struct tag*)it)->tagged) return 0; hashcpy(sha1, ((struct tag*)it)->tagged->sha1); } if (it->type != OBJ_COMMIT) return 0; commit = (struct commit *)it; for (parents = commit->parents; parents; parents = parents->next) { it = &parents->item->object; it->flags |= flags; add_pending_object(revs, it, arg); } return 1; }
static int stash_working_tree(struct stash_info *info, struct pathspec ps) { int ret = 0; struct rev_info rev; struct child_process cp_upd_index = CHILD_PROCESS_INIT; struct strbuf diff_output = STRBUF_INIT; struct index_state istate = { NULL }; init_revisions(&rev, NULL); set_alternate_index_output(stash_index_path.buf); if (reset_tree(&info->i_tree, 0, 0)) { ret = -1; goto done; } set_alternate_index_output(NULL); rev.prune_data = ps; rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = add_diff_to_buf; rev.diffopt.format_callback_data = &diff_output; if (read_cache_preload(&rev.diffopt.pathspec) < 0) { ret = -1; goto done; } add_pending_object(&rev, parse_object(the_repository, &info->b_commit), ""); if (run_diff_index(&rev, 0)) { ret = -1; goto done; } cp_upd_index.git_cmd = 1; argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add", "--remove", "--stdin", NULL); argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); if (pipe_command(&cp_upd_index, diff_output.buf, diff_output.len, NULL, 0, NULL, 0)) { ret = -1; goto done; } if (write_index_as_tree(&info->w_tree, &istate, stash_index_path.buf, 0, NULL)) { ret = -1; goto done; } done: discard_index(&istate); UNLEAK(rev); object_array_clear(&rev.pending); strbuf_release(&diff_output); remove_path(stash_index_path.buf); return ret; }
static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern) { int i; struct append_ref_cb cb; struct ref_list ref_list; memset(&ref_list, 0, sizeof(ref_list)); ref_list.kinds = kinds; ref_list.verbose = verbose; ref_list.abbrev = abbrev; ref_list.with_commit = with_commit; if (merge_filter != NO_FILTER) init_revisions(&ref_list.revs, NULL); cb.ref_list = &ref_list; cb.pattern = pattern; cb.ret = 0; for_each_rawref(append_ref, &cb); if (merge_filter != NO_FILTER) { struct commit *filter; filter = lookup_commit_reference_gently(merge_filter_ref, 0); if (!filter) die(_("object '%s' does not point to a commit"), sha1_to_hex(merge_filter_ref)); filter->object.flags |= UNINTERESTING; add_pending_object(&ref_list.revs, (struct object *) filter, ""); ref_list.revs.limited = 1; if (prepare_revision_walk(&ref_list.revs)) die(_("revision walk setup failed")); if (verbose) ref_list.maxwidth = calc_maxwidth(&ref_list); } qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp); detached = (detached && (kinds & REF_LOCAL_BRANCH)); if (detached && match_patterns(pattern, "HEAD")) show_detached(&ref_list); for (i = 0; i < ref_list.index; i++) { int current = !detached && (ref_list.list[i].kind == REF_LOCAL_BRANCH) && !strcmp(ref_list.list[i].name, head); char *prefix = (kinds != REF_REMOTE_BRANCH && ref_list.list[i].kind == REF_REMOTE_BRANCH) ? "remotes/" : ""; print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose, abbrev, current, prefix); } free_ref_list(&ref_list); if (cb.ret) error(_("some refs could not be read")); return cb.ret; }
int cmd_prune(int argc, const char **argv, const char *prefix) { struct rev_info revs; struct progress *progress = NULL; const struct option options[] = { OPT__DRY_RUN(&show_only, N_("do not remove, show only")), OPT__VERBOSE(&verbose, N_("report pruned objects")), OPT_BOOL(0, "progress", &show_progress, N_("show progress")), OPT_EXPIRY_DATE(0, "expire", &expire, N_("expire objects older than <time>")), OPT_END() }; char *s; expire = TIME_MAX; save_commit_buffer = 0; check_replace_refs = 0; ref_paranoia = 1; init_revisions(&revs, prefix); argc = parse_options(argc, argv, prefix, options, prune_usage, 0); if (repository_format_precious_objects) die(_("cannot prune in a precious-objects repo")); while (argc--) { struct object_id oid; const char *name = *argv++; if (!get_oid(name, &oid)) { struct object *object = parse_object_or_die(&oid, name); add_pending_object(&revs, object, ""); } else die("unrecognized argument: %s", name); } if (show_progress == -1) show_progress = isatty(2); if (show_progress) progress = start_progress_delay(_("Checking connectivity"), 0, 0, 2); mark_reachable_objects(&revs, 1, expire, progress); stop_progress(&progress); for_each_loose_file_in_objdir(get_object_directory(), prune_object, prune_cruft, prune_subdir, NULL); prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0); remove_temporary_files(get_object_directory()); s = mkpathdup("%s/pack", get_object_directory()); remove_temporary_files(s); free(s); if (is_repository_shallow()) prune_shallow(show_only); return 0; }
static void squash_message(struct commit *commit, struct commit_list *remoteheads) { struct rev_info rev; struct strbuf out = STRBUF_INIT; struct commit_list *j; const char *filename; int fd; struct pretty_print_context ctx = {0}; printf(_("Squash commit -- not updating HEAD\n")); filename = git_path("SQUASH_MSG"); fd = open(filename, O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not write to '%s'"), filename); init_revisions(&rev, NULL); rev.ignore_merges = 1; rev.commit_format = CMIT_FMT_MEDIUM; commit->object.flags |= UNINTERESTING; add_pending_object(&rev, &commit->object, NULL); for (j = remoteheads; j; j = j->next) add_pending_object(&rev, &j->item->object, NULL); setup_revisions(0, NULL, &rev, NULL); if (prepare_revision_walk(&rev)) die(_("revision walk setup failed")); ctx.abbrev = rev.abbrev; ctx.date_mode = rev.date_mode; ctx.fmt = rev.commit_format; strbuf_addstr(&out, "Squashed commit of the following:\n"); while ((commit = get_revision(&rev)) != NULL) { strbuf_addch(&out, '\n'); strbuf_addf(&out, "commit %s\n", sha1_to_hex(commit->object.sha1)); pretty_print_commit(&ctx, commit, &out); } if (write(fd, out.buf, out.len) < 0) die_errno(_("Writing SQUASH_MSG")); if (close(fd)) die_errno(_("Finishing SQUASH_MSG")); strbuf_release(&out); }
static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) { struct all_refs_cb *cb = cb_data; struct object *object = get_reference(cb->all_revs, path, sha1, cb->all_flags); add_pending_object(cb->all_revs, object, path); return 0; }
static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const char *prefix) { struct rev_info check_rev; struct commit *commit; struct object *o1, *o2; unsigned flags1, flags2; if (rev->pending.nr != 2) die("Need exactly one range."); o1 = rev->pending.objects[0].item; flags1 = o1->flags; o2 = rev->pending.objects[1].item; flags2 = o2->flags; if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING)) die("Not a range."); init_patch_ids(ids); /* given a range a..b get all patch ids for b..a */ init_revisions(&check_rev, prefix); o1->flags ^= UNINTERESTING; o2->flags ^= UNINTERESTING; add_pending_object(&check_rev, o1, "o1"); add_pending_object(&check_rev, o2, "o2"); if (prepare_revision_walk(&check_rev)) die("revision walk setup failed"); while ((commit = get_revision(&check_rev)) != NULL) { /* ignore merges */ if (commit->parents && commit->parents->next) continue; add_commit_patch_id(commit, ids); } /* reset for next revision walk */ clear_commit_marks((struct commit *)o1, SEEN | UNINTERESTING | SHOWN | ADDED); clear_commit_marks((struct commit *)o2, SEEN | UNINTERESTING | SHOWN | ADDED); o1->flags = flags1; o2->flags = flags2; }
static int add_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) { struct object *object = parse_object_or_die(sha1, path); struct rev_info *revs = (struct rev_info *)cb_data; add_pending_object(revs, object, ""); return 0; }
static int add_one_ref(const char *path, const struct object_id *oid, int flag, void *cb_data) { struct object *object = parse_object_or_die(oid->hash, path); struct rev_info *revs = (struct rev_info *)cb_data; add_pending_object(revs, object, ""); return 0; }
static int do_rev_list(int fd, void *create_full_pack) { int i; struct rev_info revs; pack_pipe = xfdopen(fd, "w"); init_revisions(&revs, NULL); revs.tag_objects = 1; revs.tree_objects = 1; revs.blob_objects = 1; if (use_thin_pack) revs.edge_hint = 1; if (create_full_pack) { const char *args[] = {"rev-list", "--all", NULL}; setup_revisions(2, args, &revs, NULL); } else { for (i = 0; i < want_obj.nr; i++) { struct object *o = want_obj.objects[i].item; /* why??? */ o->flags &= ~UNINTERESTING; add_pending_object(&revs, o, NULL); } for (i = 0; i < have_obj.nr; i++) { struct object *o = have_obj.objects[i].item; o->flags |= UNINTERESTING; add_pending_object(&revs, o, NULL); } setup_revisions(0, NULL, &revs, NULL); } if (prepare_revision_walk(&revs)) die("revision walk setup failed"); mark_edges_uninteresting(revs.commits, &revs, show_edge); if (use_thin_pack) for (i = 0; i < extra_edge_obj.nr; i++) fprintf(pack_pipe, "-%s\n", sha1_to_hex( extra_edge_obj.objects[i].item->sha1)); traverse_commit_list(&revs, show_commit, show_object, NULL); fflush(pack_pipe); fclose(pack_pipe); return 0; }
static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids) { struct rev_info check_rev; struct commit *commit, *c1, *c2; struct object *o1, *o2; unsigned flags1, flags2; if (rev->pending.nr != 2) die(_("Need exactly one range.")); o1 = rev->pending.objects[0].item; o2 = rev->pending.objects[1].item; flags1 = o1->flags; flags2 = o2->flags; c1 = lookup_commit_reference(o1->oid.hash); c2 = lookup_commit_reference(o2->oid.hash); if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING)) die(_("Not a range.")); init_patch_ids(ids); /* given a range a..b get all patch ids for b..a */ init_revisions(&check_rev, rev->prefix); check_rev.max_parents = 1; o1->flags ^= UNINTERESTING; o2->flags ^= UNINTERESTING; add_pending_object(&check_rev, o1, "o1"); add_pending_object(&check_rev, o2, "o2"); if (prepare_revision_walk(&check_rev)) die(_("revision walk setup failed")); while ((commit = get_revision(&check_rev)) != NULL) { add_commit_patch_id(commit, ids); } /* reset for next revision walk */ clear_commit_marks(c1, SEEN | UNINTERESTING | SHOWN | ADDED); clear_commit_marks(c2, SEEN | UNINTERESTING | SHOWN | ADDED); o1->flags = flags1; o2->flags = flags2; }
void add_head_to_pending(struct rev_info *revs) { unsigned char sha1[20]; struct object *obj; if (get_sha1("HEAD", sha1)) return; obj = parse_object(sha1); if (!obj) return; add_pending_object(revs, obj, "HEAD"); }
static void add_pending_commit_list(struct rev_info *revs, struct commit_list *commit_list, unsigned int flags) { while (commit_list) { struct object *object = &commit_list->item->object; object->flags |= flags; add_pending_object(revs, object, sha1_to_hex(object->sha1)); commit_list = commit_list->next; } }
static void squash_message(void) { struct rev_info rev; struct commit *commit; struct strbuf out; struct commit_list *j; int fd; printf("Squash commit -- not updating HEAD\n"); fd = open(git_path("SQUASH_MSG"), O_WRONLY | O_CREAT, 0666); if (fd < 0) die("Could not write to %s", git_path("SQUASH_MSG")); init_revisions(&rev, NULL); rev.ignore_merges = 1; rev.commit_format = CMIT_FMT_MEDIUM; commit = lookup_commit(head); commit->object.flags |= UNINTERESTING; add_pending_object(&rev, &commit->object, NULL); for (j = remoteheads; j; j = j->next) add_pending_object(&rev, &j->item->object, NULL); setup_revisions(0, NULL, &rev, NULL); if (prepare_revision_walk(&rev)) die("revision walk setup failed"); strbuf_init(&out, 0); strbuf_addstr(&out, "Squashed commit of the following:\n"); while ((commit = get_revision(&rev)) != NULL) { strbuf_addch(&out, '\n'); strbuf_addf(&out, "commit %s\n", sha1_to_hex(commit->object.sha1)); pretty_print_commit(rev.commit_format, commit, &out, rev.abbrev, NULL, NULL, rev.date_mode, 0); } write(fd, out.buf, out.len); close(fd); strbuf_release(&out); }
static void show_local_changes(struct object *head, const struct diff_options *opts) { struct rev_info rev; /* I think we want full paths, even if we're in a subdirectory. */ repo_init_revisions(the_repository, &rev, NULL); rev.diffopt.flags = opts->flags; rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS; diff_setup_done(&rev.diffopt); add_pending_object(&rev, head, NULL); run_diff_index(&rev, 0); }
static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { struct ref_list *ref_list = (struct ref_list*)(cb_data); struct ref_item *newitem; struct commit *commit; int kind; int len; /* Detect kind */ if (!prefixcmp(refname, "refs/heads/")) { kind = REF_LOCAL_BRANCH; refname += 11; } else if (!prefixcmp(refname, "refs/remotes/")) { kind = REF_REMOTE_BRANCH; refname += 13; } else return 0; commit = lookup_commit_reference_gently(sha1, 1); if (!commit) return error("branch '%s' does not point at a commit", refname); /* Filter with with_commit if specified */ if (!is_descendant_of(commit, ref_list->with_commit)) return 0; /* Don't add types the caller doesn't want */ if ((kind & ref_list->kinds) == 0) return 0; if (merge_filter != NO_FILTER) add_pending_object(&ref_list->revs, (struct object *)commit, refname); /* Resize buffer */ if (ref_list->index >= ref_list->alloc) { ref_list->alloc = alloc_nr(ref_list->alloc); ref_list->list = xrealloc(ref_list->list, ref_list->alloc * sizeof(struct ref_item)); } /* Record the new item */ newitem = &(ref_list->list[ref_list->index++]); newitem->name = xstrdup(refname); newitem->kind = kind; newitem->commit = commit; len = strlen(newitem->name); if (len > ref_list->maxwidth) ref_list->maxwidth = len; return 0; }
static int add_pending_commit(const char *arg, struct rev_info *revs, int flags) { unsigned char sha1[20]; if (get_sha1(arg, sha1) == 0) { struct commit *commit = lookup_commit_reference(sha1); if (commit) { commit->object.flags |= flags; add_pending_object(revs, &commit->object, arg); return 0; } } return -1; }
static void prepare_show_merge(struct rev_info *revs) { struct commit_list *bases; struct commit *head, *other; unsigned char sha1[20]; const char **prune = NULL; int i, prune_num = 1; /* counting terminating NULL */ if (get_sha1("HEAD", sha1) || !(head = lookup_commit(sha1))) die("--merge without HEAD?"); if (get_sha1("MERGE_HEAD", sha1) || !(other = lookup_commit(sha1))) die("--merge without MERGE_HEAD?"); add_pending_object(revs, &head->object, "HEAD"); add_pending_object(revs, &other->object, "MERGE_HEAD"); bases = get_merge_bases(head, other, 1); add_pending_commit_list(revs, bases, UNINTERESTING); free_commit_list(bases); head->object.flags |= SYMMETRIC_LEFT; if (!active_nr) read_cache(); for (i = 0; i < active_nr; i++) { struct cache_entry *ce = active_cache[i]; if (!ce_stage(ce)) continue; if (ce_path_match(ce, revs->prune_data)) { prune_num++; prune = xrealloc(prune, sizeof(*prune) * prune_num); prune[prune_num-2] = ce->name; prune[prune_num-1] = NULL; } while ((i+1 < active_nr) && ce_same_name(ce, active_cache[i+1])) i++; } revs->prune_data = prune; revs->limited = 1; }
int cmd_prune(int argc, const char **argv, const char *prefix) { struct rev_info revs; struct progress *progress = NULL; const struct option options[] = { OPT__DRY_RUN(&show_only, N_("do not remove, show only")), OPT__VERBOSE(&verbose, N_("report pruned objects")), OPT_BOOL(0, "progress", &show_progress, N_("show progress")), OPT_DATE(0, "expire", &expire, N_("expire objects older than <time>")), OPT_END() }; char *s; expire = ULONG_MAX; save_commit_buffer = 0; read_replace_refs = 0; init_revisions(&revs, prefix); argc = parse_options(argc, argv, prefix, options, prune_usage, 0); while (argc--) { unsigned char sha1[20]; const char *name = *argv++; if (!get_sha1(name, sha1)) { struct object *object = parse_object(sha1); if (!object) die("bad object: %s", name); add_pending_object(&revs, object, ""); } else die("unrecognized argument: %s", name); } if (show_progress == -1) show_progress = isatty(2); if (show_progress) progress = start_progress_delay("Checking connectivity", 0, 0, 2); mark_reachable_objects(&revs, 1, progress); stop_progress(&progress); prune_object_dir(get_object_directory()); prune_packed_objects(show_only); remove_temporary_files(get_object_directory()); s = xstrdup(mkpath("%s/pack", get_object_directory())); remove_temporary_files(s); free(s); return 0; }
static void squash_message(struct commit *commit, struct commit_list *remoteheads) { struct rev_info rev; struct strbuf out = STRBUF_INIT; struct commit_list *j; struct pretty_print_context ctx = {0}; printf(_("Squash commit -- not updating HEAD\n")); init_revisions(&rev, NULL); rev.ignore_merges = 1; rev.commit_format = CMIT_FMT_MEDIUM; commit->object.flags |= UNINTERESTING; add_pending_object(&rev, &commit->object, NULL); for (j = remoteheads; j; j = j->next) add_pending_object(&rev, &j->item->object, NULL); setup_revisions(0, NULL, &rev, NULL); if (prepare_revision_walk(&rev)) die(_("revision walk setup failed")); ctx.abbrev = rev.abbrev; ctx.date_mode = rev.date_mode; ctx.fmt = rev.commit_format; strbuf_addstr(&out, "Squashed commit of the following:\n"); while ((commit = get_revision(&rev)) != NULL) { strbuf_addch(&out, '\n'); strbuf_addf(&out, "commit %s\n", oid_to_hex(&commit->object.oid)); pretty_print_commit(&ctx, commit, &out); } write_file_buf(git_path_squash_msg(), out.buf, out.len); strbuf_release(&out); }
static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit) { int i; struct ref_list ref_list; struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1); memset(&ref_list, 0, sizeof(ref_list)); ref_list.kinds = kinds; ref_list.with_commit = with_commit; if (merge_filter != NO_FILTER) init_revisions(&ref_list.revs, NULL); for_each_ref(append_ref, &ref_list); if (merge_filter != NO_FILTER) { struct commit *filter; filter = lookup_commit_reference_gently(merge_filter_ref, 0); filter->object.flags |= UNINTERESTING; add_pending_object(&ref_list.revs, (struct object *) filter, ""); ref_list.revs.limited = 1; prepare_revision_walk(&ref_list.revs); if (verbose) ref_list.maxwidth = calc_maxwidth(&ref_list); } qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp); detached = (detached && (kinds & REF_LOCAL_BRANCH)); if (detached && head_commit && is_descendant_of(head_commit, with_commit)) { struct ref_item item; item.name = xstrdup("(no branch)"); item.kind = REF_LOCAL_BRANCH; item.commit = head_commit; if (strlen(item.name) > ref_list.maxwidth) ref_list.maxwidth = strlen(item.name); print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1); free(item.name); } for (i = 0; i < ref_list.index; i++) { int current = !detached && (ref_list.list[i].kind == REF_LOCAL_BRANCH) && !strcmp(ref_list.list[i].name, head); print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose, abbrev, current); } free_ref_list(&ref_list); }
static int add_one_ref(const char *path, const struct object_id *oid, int flag, void *cb_data) { struct rev_info *revs = (struct rev_info *)cb_data; struct object *object; if ((flag & REF_ISSYMREF) && (flag & REF_ISBROKEN)) { warning("symbolic ref is dangling: %s", path); return 0; } object = parse_object_or_die(oid, path); add_pending_object(revs, object, ""); return 0; }
static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data) { struct all_refs_cb *cb = cb_data; if (!is_null_sha1(sha1)) { struct object *o = parse_object(sha1); if (o) { o->flags |= cb->all_flags; add_pending_object(cb->all_revs, o, ""); } else if (!cb->warned_bad_reflog) { warning("reflog of '%s' references pruned commits", cb->name_for_errormsg); cb->warned_bad_reflog = 1; } } }
static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit) { int i; struct ref_list ref_list; memset(&ref_list, 0, sizeof(ref_list)); ref_list.kinds = kinds; ref_list.verbose = verbose; ref_list.abbrev = abbrev; ref_list.with_commit = with_commit; if (merge_filter != NO_FILTER) init_revisions(&ref_list.revs, NULL); for_each_rawref(append_ref, &ref_list); if (merge_filter != NO_FILTER) { struct commit *filter; filter = lookup_commit_reference_gently(merge_filter_ref, 0); filter->object.flags |= UNINTERESTING; add_pending_object(&ref_list.revs, (struct object *) filter, ""); ref_list.revs.limited = 1; prepare_revision_walk(&ref_list.revs); if (verbose) ref_list.maxwidth = calc_maxwidth(&ref_list); } qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp); detached = (detached && (kinds & REF_LOCAL_BRANCH)); if (detached) show_detached(&ref_list); for (i = 0; i < ref_list.index; i++) { int current = !detached && (ref_list.list[i].kind == REF_LOCAL_BRANCH) && !strcmp(ref_list.list[i].name, head); char *prefix = (kinds != REF_REMOTE_BRANCH && ref_list.list[i].kind == REF_REMOTE_BRANCH) ? "remotes/" : ""; print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose, abbrev, current, prefix); } free_ref_list(&ref_list); }
int cmd_prune(int argc, const char **argv, const char *prefix) { struct rev_info revs; const struct option options[] = { OPT_BOOLEAN('n', NULL, &show_only, "do not remove, show only"), OPT_BOOLEAN('v', NULL, &verbose, "report pruned objects"), OPT_DATE(0, "expire", &expire, "expire objects older than <time>"), OPT_END() }; char *s; expire = ULONG_MAX; save_commit_buffer = 0; read_replace_refs = 0; init_revisions(&revs, prefix); argc = parse_options(argc, argv, prefix, options, prune_usage, 0); while (argc--) { unsigned char sha1[20]; const char *name = *argv++; if (!get_sha1(name, sha1)) { struct object *object = parse_object(sha1); if (!object) die("bad object: %s", name); add_pending_object(&revs, object, ""); } else die("unrecognized argument: %s", name); } mark_reachable_objects(&revs, 1); prune_object_dir(get_object_directory()); prune_packed_objects(show_only); remove_temporary_files(get_object_directory()); s = xstrdup(mkpath("%s/pack", get_object_directory())); remove_temporary_files(s); free(s); return 0; }
static int compute_and_write_prerequisites(int bundle_fd, struct rev_info *revs, int argc, const char **argv) { struct child_process rls = CHILD_PROCESS_INIT; struct strbuf buf = STRBUF_INIT; FILE *rls_fout; int i; argv_array_pushl(&rls.args, "rev-list", "--boundary", "--pretty=oneline", NULL); for (i = 1; i < argc; i++) argv_array_push(&rls.args, argv[i]); rls.out = -1; rls.git_cmd = 1; if (start_command(&rls)) return -1; rls_fout = xfdopen(rls.out, "r"); while (strbuf_getwholeline(&buf, rls_fout, '\n') != EOF) { unsigned char sha1[20]; if (buf.len > 0 && buf.buf[0] == '-') { write_or_die(bundle_fd, buf.buf, buf.len); if (!get_sha1_hex(buf.buf + 1, sha1)) { struct object *object = parse_object_or_die(sha1, buf.buf); object->flags |= UNINTERESTING; add_pending_object(revs, object, buf.buf); } } else if (!get_sha1_hex(buf.buf, sha1)) { struct object *object = parse_object_or_die(sha1, buf.buf); object->flags |= SHOWN; } } strbuf_release(&buf); fclose(rls_fout); if (finish_command(&rls)) return error(_("rev-list died")); return 0; }
/* * We are about to leave commit that was at the tip of a detached * HEAD. If it is not reachable from any ref, this is the last chance * for the user to do so without resorting to reflog. */ static void orphaned_commit_warning(struct commit *old_commit, struct commit *new_commit) { struct rev_info revs; struct object *object = &old_commit->object; repo_init_revisions(the_repository, &revs, NULL); setup_revisions(0, NULL, &revs, NULL); object->flags &= ~UNINTERESTING; add_pending_object(&revs, object, oid_to_hex(&object->oid)); for_each_ref(add_pending_uninteresting_ref, &revs); add_pending_oid(&revs, "HEAD", &new_commit->object.oid, UNINTERESTING); if (prepare_revision_walk(&revs)) die(_("internal error in revision walk")); if (!(old_commit->object.flags & UNINTERESTING)) suggest_reattach(old_commit, &revs); else describe_detached_head(_("Previous HEAD position was"), old_commit); /* Clean up objects used, as they will be reused. */ clear_commit_marks_all(ALL_REV_FLAGS); }
static struct commit *dwim_reverse_initial(struct rev_info *revs, const char **name_p) { /* * DWIM "git blame --reverse ONE -- PATH" as * "git blame --reverse ONE..HEAD -- PATH" but only do so * when it makes sense. */ struct object *obj; struct commit *head_commit; struct object_id head_oid; if (revs->pending.nr != 1) return NULL; /* Is that sole rev a committish? */ obj = revs->pending.objects[0].item; obj = deref_tag(obj, NULL, 0); if (obj->type != OBJ_COMMIT) return NULL; /* Do we have HEAD? */ if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL)) return NULL; head_commit = lookup_commit_reference_gently(&head_oid, 1); if (!head_commit) return NULL; /* Turn "ONE" into "ONE..HEAD" then */ obj->flags |= UNINTERESTING; add_pending_object(revs, &head_commit->object, "HEAD"); if (name_p) *name_p = revs->pending.objects[0].name; return (struct commit *)obj; }