git
/
shallow.c
849 строк · 22.8 Кб
1#define USE_THE_REPOSITORY_VARIABLE2
3#include "git-compat-util.h"4#include "hex.h"5#include "repository.h"6#include "tempfile.h"7#include "lockfile.h"8#include "object-store-ll.h"9#include "commit.h"10#include "tag.h"11#include "pkt-line.h"12#include "refs.h"13#include "oid-array.h"14#include "path.h"15#include "diff.h"16#include "revision.h"17#include "commit-slab.h"18#include "list-objects.h"19#include "commit-reach.h"20#include "shallow.h"21#include "statinfo.h"22#include "trace.h"23
24void set_alternate_shallow_file(struct repository *r, const char *path, int override)25{
26if (r->parsed_objects->is_shallow != -1)27BUG("is_repository_shallow must not be called before set_alternate_shallow_file");28if (r->parsed_objects->alternate_shallow_file && !override)29return;30free(r->parsed_objects->alternate_shallow_file);31r->parsed_objects->alternate_shallow_file = xstrdup_or_null(path);32}
33
34int register_shallow(struct repository *r, const struct object_id *oid)35{
36struct commit_graft *graft =37xmalloc(sizeof(struct commit_graft));38struct commit *commit = lookup_commit(r, oid);39
40oidcpy(&graft->oid, oid);41graft->nr_parent = -1;42if (commit && commit->object.parsed) {43free_commit_list(commit->parents);44commit->parents = NULL;45}46return register_commit_graft(r, graft, 0);47}
48
49int unregister_shallow(const struct object_id *oid)50{
51int pos = commit_graft_pos(the_repository, oid);52if (pos < 0)53return -1;54if (pos + 1 < the_repository->parsed_objects->grafts_nr)55MOVE_ARRAY(the_repository->parsed_objects->grafts + pos,56the_repository->parsed_objects->grafts + pos + 1,57the_repository->parsed_objects->grafts_nr - pos - 1);58the_repository->parsed_objects->grafts_nr--;59return 0;60}
61
62int is_repository_shallow(struct repository *r)63{
64FILE *fp;65char buf[1024];66const char *path = r->parsed_objects->alternate_shallow_file;67
68if (r->parsed_objects->is_shallow >= 0)69return r->parsed_objects->is_shallow;70
71if (!path)72path = git_path_shallow(r);73/*74* fetch-pack sets '--shallow-file ""' as an indicator that no
75* shallow file should be used. We could just open it and it
76* will likely fail. But let's do an explicit check instead.
77*/
78if (!*path || (fp = fopen(path, "r")) == NULL) {79stat_validity_clear(r->parsed_objects->shallow_stat);80r->parsed_objects->is_shallow = 0;81return r->parsed_objects->is_shallow;82}83stat_validity_update(r->parsed_objects->shallow_stat, fileno(fp));84r->parsed_objects->is_shallow = 1;85
86while (fgets(buf, sizeof(buf), fp)) {87struct object_id oid;88if (get_oid_hex(buf, &oid))89die("bad shallow line: %s", buf);90register_shallow(r, &oid);91}92fclose(fp);93return r->parsed_objects->is_shallow;94}
95
96static void reset_repository_shallow(struct repository *r)97{
98r->parsed_objects->is_shallow = -1;99stat_validity_clear(r->parsed_objects->shallow_stat);100reset_commit_grafts(r);101}
102
103int commit_shallow_file(struct repository *r, struct shallow_lock *lk)104{
105int res = commit_lock_file(&lk->lock);106reset_repository_shallow(r);107
108/*109* Update in-memory data structures with the new shallow information,
110* including unparsing all commits that now have grafts.
111*/
112is_repository_shallow(r);113
114return res;115}
116
117void rollback_shallow_file(struct repository *r, struct shallow_lock *lk)118{
119rollback_lock_file(&lk->lock);120reset_repository_shallow(r);121}
122
123/*
124* TODO: use "int" elemtype instead of "int *" when/if commit-slab
125* supports a "valid" flag.
126*/
127define_commit_slab(commit_depth, int *);128static void free_depth_in_slab(int **ptr)129{
130FREE_AND_NULL(*ptr);131}
132struct commit_list *get_shallow_commits(struct object_array *heads, int depth,133int shallow_flag, int not_shallow_flag)134{
135int i = 0, cur_depth = 0;136struct commit_list *result = NULL;137struct object_array stack = OBJECT_ARRAY_INIT;138struct commit *commit = NULL;139struct commit_graft *graft;140struct commit_depth depths;141
142init_commit_depth(&depths);143while (commit || i < heads->nr || stack.nr) {144struct commit_list *p;145if (!commit) {146if (i < heads->nr) {147int **depth_slot;148commit = (struct commit *)149deref_tag(the_repository,150heads->objects[i++].item,151NULL, 0);152if (!commit || commit->object.type != OBJ_COMMIT) {153commit = NULL;154continue;155}156depth_slot = commit_depth_at(&depths, commit);157if (!*depth_slot)158*depth_slot = xmalloc(sizeof(int));159**depth_slot = 0;160cur_depth = 0;161} else {162commit = (struct commit *)163object_array_pop(&stack);164cur_depth = **commit_depth_at(&depths, commit);165}166}167parse_commit_or_die(commit);168cur_depth++;169if ((depth != INFINITE_DEPTH && cur_depth >= depth) ||170(is_repository_shallow(the_repository) && !commit->parents &&171(graft = lookup_commit_graft(the_repository, &commit->object.oid)) != NULL &&172graft->nr_parent < 0)) {173commit_list_insert(commit, &result);174commit->object.flags |= shallow_flag;175commit = NULL;176continue;177}178commit->object.flags |= not_shallow_flag;179for (p = commit->parents, commit = NULL; p; p = p->next) {180int **depth_slot = commit_depth_at(&depths, p->item);181if (!*depth_slot) {182*depth_slot = xmalloc(sizeof(int));183**depth_slot = cur_depth;184} else {185if (cur_depth >= **depth_slot)186continue;187**depth_slot = cur_depth;188}189if (p->next)190add_object_array(&p->item->object,191NULL, &stack);192else {193commit = p->item;194cur_depth = **commit_depth_at(&depths, commit);195}196}197}198deep_clear_commit_depth(&depths, free_depth_in_slab);199
200return result;201}
202
203static void show_commit(struct commit *commit, void *data)204{
205commit_list_insert(commit, data);206}
207
208/*
209* Given rev-list arguments, run rev-list. All reachable commits
210* except border ones are marked with not_shallow_flag. Border commits
211* are marked with shallow_flag. The list of border/shallow commits
212* are also returned.
213*/
214struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,215int shallow_flag,216int not_shallow_flag)217{
218struct commit_list *result = NULL, *p;219struct commit_list *not_shallow_list = NULL;220struct rev_info revs;221int both_flags = shallow_flag | not_shallow_flag;222
223/*224* SHALLOW (excluded) and NOT_SHALLOW (included) should not be
225* set at this point. But better be safe than sorry.
226*/
227clear_object_flags(both_flags);228
229is_repository_shallow(the_repository); /* make sure shallows are read */230
231repo_init_revisions(the_repository, &revs, NULL);232save_commit_buffer = 0;233setup_revisions(ac, av, &revs, NULL);234
235if (prepare_revision_walk(&revs))236die("revision walk setup failed");237traverse_commit_list(&revs, show_commit, NULL, ¬_shallow_list);238
239if (!not_shallow_list)240die("no commits selected for shallow requests");241
242/* Mark all reachable commits as NOT_SHALLOW */243for (p = not_shallow_list; p; p = p->next)244p->item->object.flags |= not_shallow_flag;245
246/*247* mark border commits SHALLOW + NOT_SHALLOW.
248* We cannot clear NOT_SHALLOW right now. Imagine border
249* commit A is processed first, then commit B, whose parent is
250* A, later. If NOT_SHALLOW on A is cleared at step 1, B
251* itself is considered border at step 2, which is incorrect.
252*/
253for (p = not_shallow_list; p; p = p->next) {254struct commit *c = p->item;255struct commit_list *parent;256
257if (repo_parse_commit(the_repository, c))258die("unable to parse commit %s",259oid_to_hex(&c->object.oid));260
261for (parent = c->parents; parent; parent = parent->next)262if (!(parent->item->object.flags & not_shallow_flag)) {263c->object.flags |= shallow_flag;264commit_list_insert(c, &result);265break;266}267}268free_commit_list(not_shallow_list);269
270/*271* Now we can clean up NOT_SHALLOW on border commits. Having
272* both flags set can confuse the caller.
273*/
274for (p = result; p; p = p->next) {275struct object *o = &p->item->object;276if ((o->flags & both_flags) == both_flags)277o->flags &= ~not_shallow_flag;278}279release_revisions(&revs);280return result;281}
282
283static void check_shallow_file_for_update(struct repository *r)284{
285if (r->parsed_objects->is_shallow == -1)286BUG("shallow must be initialized by now");287
288if (!stat_validity_check(r->parsed_objects->shallow_stat,289git_path_shallow(r)))290die("shallow file has changed since we read it");291}
292
293#define SEEN_ONLY 1294#define VERBOSE 2295#define QUICK 4296
297struct write_shallow_data {298struct strbuf *out;299int use_pack_protocol;300int count;301unsigned flags;302};303
304static int write_one_shallow(const struct commit_graft *graft, void *cb_data)305{
306struct write_shallow_data *data = cb_data;307const char *hex = oid_to_hex(&graft->oid);308if (graft->nr_parent != -1)309return 0;310if (data->flags & QUICK) {311if (!repo_has_object_file(the_repository, &graft->oid))312return 0;313} else if (data->flags & SEEN_ONLY) {314struct commit *c = lookup_commit(the_repository, &graft->oid);315if (!c || !(c->object.flags & SEEN)) {316if (data->flags & VERBOSE)317printf("Removing %s from .git/shallow\n",318oid_to_hex(&c->object.oid));319return 0;320}321}322data->count++;323if (data->use_pack_protocol)324packet_buf_write(data->out, "shallow %s", hex);325else {326strbuf_addstr(data->out, hex);327strbuf_addch(data->out, '\n');328}329return 0;330}
331
332static int write_shallow_commits_1(struct strbuf *out, int use_pack_protocol,333const struct oid_array *extra,334unsigned flags)335{
336struct write_shallow_data data;337int i;338data.out = out;339data.use_pack_protocol = use_pack_protocol;340data.count = 0;341data.flags = flags;342for_each_commit_graft(write_one_shallow, &data);343if (!extra)344return data.count;345for (i = 0; i < extra->nr; i++) {346strbuf_addstr(out, oid_to_hex(extra->oid + i));347strbuf_addch(out, '\n');348data.count++;349}350return data.count;351}
352
353int write_shallow_commits(struct strbuf *out, int use_pack_protocol,354const struct oid_array *extra)355{
356return write_shallow_commits_1(out, use_pack_protocol, extra, 0);357}
358
359const char *setup_temporary_shallow(const struct oid_array *extra)360{
361struct tempfile *temp;362struct strbuf sb = STRBUF_INIT;363
364if (write_shallow_commits(&sb, 0, extra)) {365temp = xmks_tempfile(git_path("shallow_XXXXXX"));366
367if (write_in_full(temp->fd, sb.buf, sb.len) < 0 ||368close_tempfile_gently(temp) < 0)369die_errno("failed to write to %s",370get_tempfile_path(temp));371strbuf_release(&sb);372return get_tempfile_path(temp);373}374/*375* is_repository_shallow() sees empty string as "no shallow
376* file".
377*/
378return "";379}
380
381void setup_alternate_shallow(struct shallow_lock *shallow_lock,382const char **alternate_shallow_file,383const struct oid_array *extra)384{
385struct strbuf sb = STRBUF_INIT;386int fd;387
388fd = hold_lock_file_for_update(&shallow_lock->lock,389git_path_shallow(the_repository),390LOCK_DIE_ON_ERROR);391check_shallow_file_for_update(the_repository);392if (write_shallow_commits(&sb, 0, extra)) {393if (write_in_full(fd, sb.buf, sb.len) < 0)394die_errno("failed to write to %s",395get_lock_file_path(&shallow_lock->lock));396*alternate_shallow_file = get_lock_file_path(&shallow_lock->lock);397} else398/*399* is_repository_shallow() sees empty string as "no
400* shallow file".
401*/
402*alternate_shallow_file = "";403strbuf_release(&sb);404}
405
406static int advertise_shallow_grafts_cb(const struct commit_graft *graft, void *cb)407{
408int fd = *(int *)cb;409if (graft->nr_parent == -1)410packet_write_fmt(fd, "shallow %s\n", oid_to_hex(&graft->oid));411return 0;412}
413
414void advertise_shallow_grafts(int fd)415{
416if (!is_repository_shallow(the_repository))417return;418for_each_commit_graft(advertise_shallow_grafts_cb, &fd);419}
420
421/*
422* mark_reachable_objects() should have been run prior to this and all
423* reachable commits marked as "SEEN", except when quick_prune is non-zero,
424* in which case lines are excised from the shallow file if they refer to
425* commits that do not exist (any longer).
426*/
427void prune_shallow(unsigned options)428{
429struct shallow_lock shallow_lock = SHALLOW_LOCK_INIT;430struct strbuf sb = STRBUF_INIT;431unsigned flags = SEEN_ONLY;432int fd;433
434if (options & PRUNE_QUICK)435flags |= QUICK;436
437if (options & PRUNE_SHOW_ONLY) {438flags |= VERBOSE;439write_shallow_commits_1(&sb, 0, NULL, flags);440strbuf_release(&sb);441return;442}443fd = hold_lock_file_for_update(&shallow_lock.lock,444git_path_shallow(the_repository),445LOCK_DIE_ON_ERROR);446check_shallow_file_for_update(the_repository);447if (write_shallow_commits_1(&sb, 0, NULL, flags)) {448if (write_in_full(fd, sb.buf, sb.len) < 0)449die_errno("failed to write to %s",450get_lock_file_path(&shallow_lock.lock));451commit_shallow_file(the_repository, &shallow_lock);452} else {453unlink(git_path_shallow(the_repository));454rollback_shallow_file(the_repository, &shallow_lock);455}456strbuf_release(&sb);457}
458
459struct trace_key trace_shallow = TRACE_KEY_INIT(SHALLOW);460
461/*
462* Step 1, split sender shallow commits into "ours" and "theirs"
463* Step 2, clean "ours" based on .git/shallow
464*/
465void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa)466{
467int i;468trace_printf_key(&trace_shallow, "shallow: prepare_shallow_info\n");469memset(info, 0, sizeof(*info));470info->shallow = sa;471if (!sa)472return;473ALLOC_ARRAY(info->ours, sa->nr);474ALLOC_ARRAY(info->theirs, sa->nr);475for (i = 0; i < sa->nr; i++) {476if (repo_has_object_file(the_repository, sa->oid + i)) {477struct commit_graft *graft;478graft = lookup_commit_graft(the_repository,479&sa->oid[i]);480if (graft && graft->nr_parent < 0)481continue;482info->ours[info->nr_ours++] = i;483} else484info->theirs[info->nr_theirs++] = i;485}486}
487
488void clear_shallow_info(struct shallow_info *info)489{
490free(info->ours);491free(info->theirs);492}
493
494/* Step 4, remove non-existent ones in "theirs" after getting the pack */
495
496void remove_nonexistent_theirs_shallow(struct shallow_info *info)497{
498struct object_id *oid = info->shallow->oid;499int i, dst;500trace_printf_key(&trace_shallow, "shallow: remove_nonexistent_theirs_shallow\n");501for (i = dst = 0; i < info->nr_theirs; i++) {502if (i != dst)503info->theirs[dst] = info->theirs[i];504if (repo_has_object_file(the_repository, oid + info->theirs[i]))505dst++;506}507info->nr_theirs = dst;508}
509
510define_commit_slab(ref_bitmap, uint32_t *);511
512#define POOL_SIZE (512 * 1024)513
514struct paint_info {515struct ref_bitmap ref_bitmap;516unsigned nr_bits;517char **pools;518char *free, *end;519unsigned pool_count;520};521
522static uint32_t *paint_alloc(struct paint_info *info)523{
524unsigned nr = DIV_ROUND_UP(info->nr_bits, 32);525unsigned size = nr * sizeof(uint32_t);526void *p;527if (!info->pool_count || size > info->end - info->free) {528if (size > POOL_SIZE)529BUG("pool size too small for %d in paint_alloc()",530size);531info->pool_count++;532REALLOC_ARRAY(info->pools, info->pool_count);533info->free = xmalloc(POOL_SIZE);534info->pools[info->pool_count - 1] = info->free;535info->end = info->free + POOL_SIZE;536}537p = info->free;538info->free += size;539return p;540}
541
542/*
543* Given a commit SHA-1, walk down to parents until either SEEN,
544* UNINTERESTING or BOTTOM is hit. Set the id-th bit in ref_bitmap for
545* all walked commits.
546*/
547static void paint_down(struct paint_info *info, const struct object_id *oid,548unsigned int id)549{
550unsigned int i, nr;551struct commit_list *head = NULL;552int bitmap_nr = DIV_ROUND_UP(info->nr_bits, 32);553size_t bitmap_size = st_mult(sizeof(uint32_t), bitmap_nr);554struct commit *c = lookup_commit_reference_gently(the_repository, oid,5551);556uint32_t *tmp; /* to be freed before return */557uint32_t *bitmap;558
559if (!c)560return;561
562tmp = xmalloc(bitmap_size);563bitmap = paint_alloc(info);564memset(bitmap, 0, bitmap_size);565bitmap[id / 32] |= (1U << (id % 32));566commit_list_insert(c, &head);567while (head) {568struct commit_list *p;569struct commit *c = pop_commit(&head);570uint32_t **refs = ref_bitmap_at(&info->ref_bitmap, c);571
572/* XXX check "UNINTERESTING" from pack bitmaps if available */573if (c->object.flags & (SEEN | UNINTERESTING))574continue;575else576c->object.flags |= SEEN;577
578if (!*refs)579*refs = bitmap;580else {581memcpy(tmp, *refs, bitmap_size);582for (i = 0; i < bitmap_nr; i++)583tmp[i] |= bitmap[i];584if (memcmp(tmp, *refs, bitmap_size)) {585*refs = paint_alloc(info);586memcpy(*refs, tmp, bitmap_size);587}588}589
590if (c->object.flags & BOTTOM)591continue;592
593if (repo_parse_commit(the_repository, c))594die("unable to parse commit %s",595oid_to_hex(&c->object.oid));596
597for (p = c->parents; p; p = p->next) {598if (p->item->object.flags & SEEN)599continue;600commit_list_insert(p->item, &head);601}602}603
604nr = get_max_object_index();605for (i = 0; i < nr; i++) {606struct object *o = get_indexed_object(i);607if (o && o->type == OBJ_COMMIT)608o->flags &= ~SEEN;609}610
611free(tmp);612}
613
614static int mark_uninteresting(const char *refname UNUSED,615const char *referent UNUSED,616const struct object_id *oid,617int flags UNUSED,618void *cb_data UNUSED)619{
620struct commit *commit = lookup_commit_reference_gently(the_repository,621oid, 1);622if (!commit)623return 0;624commit->object.flags |= UNINTERESTING;625mark_parents_uninteresting(NULL, commit);626return 0;627}
628
629static void post_assign_shallow(struct shallow_info *info,630struct ref_bitmap *ref_bitmap,631int *ref_status);632/*
633* Step 6(+7), associate shallow commits with new refs
634*
635* info->ref must be initialized before calling this function.
636*
637* If used is not NULL, it's an array of info->shallow->nr
638* bitmaps. The n-th bit set in the m-th bitmap if ref[n] needs the
639* m-th shallow commit from info->shallow.
640*
641* If used is NULL, "ours" and "theirs" are updated. And if ref_status
642* is not NULL it's an array of ref->nr ints. ref_status[i] is true if
643* the ref needs some shallow commits from either info->ours or
644* info->theirs.
645*/
646void assign_shallow_commits_to_refs(struct shallow_info *info,647uint32_t **used, int *ref_status)648{
649struct object_id *oid = info->shallow->oid;650struct oid_array *ref = info->ref;651unsigned int i, nr;652int *shallow, nr_shallow = 0;653struct paint_info pi;654
655trace_printf_key(&trace_shallow, "shallow: assign_shallow_commits_to_refs\n");656ALLOC_ARRAY(shallow, info->nr_ours + info->nr_theirs);657for (i = 0; i < info->nr_ours; i++)658shallow[nr_shallow++] = info->ours[i];659for (i = 0; i < info->nr_theirs; i++)660shallow[nr_shallow++] = info->theirs[i];661
662/*663* Prepare the commit graph to track what refs can reach what
664* (new) shallow commits.
665*/
666nr = get_max_object_index();667for (i = 0; i < nr; i++) {668struct object *o = get_indexed_object(i);669if (!o || o->type != OBJ_COMMIT)670continue;671
672o->flags &= ~(UNINTERESTING | BOTTOM | SEEN);673}674
675memset(&pi, 0, sizeof(pi));676init_ref_bitmap(&pi.ref_bitmap);677pi.nr_bits = ref->nr;678
679/*680* "--not --all" to cut short the traversal if new refs
681* connect to old refs. If not (e.g. force ref updates) it'll
682* have to go down to the current shallow commits.
683*/
684refs_head_ref(get_main_ref_store(the_repository), mark_uninteresting,685NULL);686refs_for_each_ref(get_main_ref_store(the_repository),687mark_uninteresting, NULL);688
689/* Mark potential bottoms so we won't go out of bound */690for (i = 0; i < nr_shallow; i++) {691struct commit *c = lookup_commit(the_repository,692&oid[shallow[i]]);693c->object.flags |= BOTTOM;694}695
696for (i = 0; i < ref->nr; i++)697paint_down(&pi, ref->oid + i, i);698
699if (used) {700int bitmap_size = DIV_ROUND_UP(pi.nr_bits, 32) * sizeof(uint32_t);701memset(used, 0, sizeof(*used) * info->shallow->nr);702for (i = 0; i < nr_shallow; i++) {703const struct commit *c = lookup_commit(the_repository,704&oid[shallow[i]]);705uint32_t **map = ref_bitmap_at(&pi.ref_bitmap, c);706if (*map)707used[shallow[i]] = xmemdupz(*map, bitmap_size);708}709/*710* unreachable shallow commits are not removed from
711* "ours" and "theirs". The user is supposed to run
712* step 7 on every ref separately and not trust "ours"
713* and "theirs" any more.
714*/
715} else716post_assign_shallow(info, &pi.ref_bitmap, ref_status);717
718clear_ref_bitmap(&pi.ref_bitmap);719for (i = 0; i < pi.pool_count; i++)720free(pi.pools[i]);721free(pi.pools);722free(shallow);723}
724
725struct commit_array {726struct commit **commits;727int nr, alloc;728};729
730static int add_ref(const char *refname UNUSED,731const char *referent UNUSED,732const struct object_id *oid,733int flags UNUSED,734void *cb_data)735{
736struct commit_array *ca = cb_data;737ALLOC_GROW(ca->commits, ca->nr + 1, ca->alloc);738ca->commits[ca->nr] = lookup_commit_reference_gently(the_repository,739oid, 1);740if (ca->commits[ca->nr])741ca->nr++;742return 0;743}
744
745static void update_refstatus(int *ref_status, int nr, uint32_t *bitmap)746{
747unsigned int i;748if (!ref_status)749return;750for (i = 0; i < nr; i++)751if (bitmap[i / 32] & (1U << (i % 32)))752ref_status[i]++;753}
754
755/*
756* Step 7, reachability test on "ours" at commit level
757*/
758static void post_assign_shallow(struct shallow_info *info,759struct ref_bitmap *ref_bitmap,760int *ref_status)761{
762struct object_id *oid = info->shallow->oid;763struct commit *c;764uint32_t **bitmap;765int dst, i, j;766int bitmap_nr = DIV_ROUND_UP(info->ref->nr, 32);767struct commit_array ca;768
769trace_printf_key(&trace_shallow, "shallow: post_assign_shallow\n");770if (ref_status)771memset(ref_status, 0, sizeof(*ref_status) * info->ref->nr);772
773/* Remove unreachable shallow commits from "theirs" */774for (i = dst = 0; i < info->nr_theirs; i++) {775if (i != dst)776info->theirs[dst] = info->theirs[i];777c = lookup_commit(the_repository, &oid[info->theirs[i]]);778bitmap = ref_bitmap_at(ref_bitmap, c);779if (!*bitmap)780continue;781for (j = 0; j < bitmap_nr; j++)782if (bitmap[0][j]) {783update_refstatus(ref_status, info->ref->nr, *bitmap);784dst++;785break;786}787}788info->nr_theirs = dst;789
790memset(&ca, 0, sizeof(ca));791refs_head_ref(get_main_ref_store(the_repository), add_ref, &ca);792refs_for_each_ref(get_main_ref_store(the_repository), add_ref, &ca);793
794/* Remove unreachable shallow commits from "ours" */795for (i = dst = 0; i < info->nr_ours; i++) {796if (i != dst)797info->ours[dst] = info->ours[i];798c = lookup_commit(the_repository, &oid[info->ours[i]]);799bitmap = ref_bitmap_at(ref_bitmap, c);800if (!*bitmap)801continue;802for (j = 0; j < bitmap_nr; j++)803if (bitmap[0][j]) {804/* Step 7, reachability test at commit level */805int ret = repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1);806if (ret < 0)807exit(128);808if (!ret) {809update_refstatus(ref_status, info->ref->nr, *bitmap);810dst++;811break;812}813}814}815info->nr_ours = dst;816
817free(ca.commits);818}
819
820/* (Delayed) step 7, reachability test at commit level */
821int delayed_reachability_test(struct shallow_info *si, int c)822{
823if (si->need_reachability_test[c]) {824struct commit *commit = lookup_commit(the_repository,825&si->shallow->oid[c]);826
827if (!si->commits) {828struct commit_array ca;829
830memset(&ca, 0, sizeof(ca));831refs_head_ref(get_main_ref_store(the_repository),832add_ref, &ca);833refs_for_each_ref(get_main_ref_store(the_repository),834add_ref, &ca);835si->commits = ca.commits;836si->nr_commits = ca.nr;837}838
839si->reachable[c] = repo_in_merge_bases_many(the_repository,840commit,841si->nr_commits,842si->commits,8431);844if (si->reachable[c] < 0)845exit(128);846si->need_reachability_test[c] = 0;847}848return si->reachable[c];849}
850