static void prepare_shallow_update(struct command *commands, struct shallow_info *si) { int i, j, k, bitmap_size = (si->ref->nr + 31) / 32; si->used_shallow = xmalloc(sizeof(*si->used_shallow) * si->shallow->nr); assign_shallow_commits_to_refs(si, si->used_shallow, NULL); si->need_reachability_test = xcalloc(si->shallow->nr, sizeof(*si->need_reachability_test)); si->reachable = xcalloc(si->shallow->nr, sizeof(*si->reachable)); si->shallow_ref = xcalloc(si->ref->nr, sizeof(*si->shallow_ref)); for (i = 0; i < si->nr_ours; i++) si->need_reachability_test[si->ours[i]] = 1; for (i = 0; i < si->shallow->nr; i++) { if (!si->used_shallow[i]) continue; for (j = 0; j < bitmap_size; j++) { if (!si->used_shallow[i][j]) continue; si->need_reachability_test[i]++; for (k = 0; k < 32; k++) if (si->used_shallow[i][j] & (1 << k)) si->shallow_ref[j * 32 + k]++; } /* * true for those associated with some refs and belong * in "ours" list aka "step 7 not done yet" */ si->need_reachability_test[i] = si->need_reachability_test[i] > 1; } /* * keep hooks happy by forcing a temporary shallow file via * env variable because we can't add --shallow-file to every * command. check_everything_connected() will be done with * true .git/shallow though. */ setenv(GIT_SHALLOW_FILE_ENVIRONMENT, alt_shallow_file, 1); }
static void update_shallow_info(struct command *commands, struct shallow_info *si, struct sha1_array *ref) { struct command *cmd; int *ref_status; remove_nonexistent_theirs_shallow(si); if (!si->nr_ours && !si->nr_theirs) { shallow_update = 0; return; } for (cmd = commands; cmd; cmd = cmd->next) { if (is_null_sha1(cmd->new_sha1)) continue; sha1_array_append(ref, cmd->new_sha1); cmd->index = ref->nr - 1; } si->ref = ref; if (shallow_update) { prepare_shallow_update(commands, si); return; } ALLOC_ARRAY(ref_status, ref->nr); assign_shallow_commits_to_refs(si, NULL, ref_status); for (cmd = commands; cmd; cmd = cmd->next) { if (is_null_sha1(cmd->new_sha1)) continue; if (ref_status[cmd->index]) { cmd->error_string = "shallow update not allowed"; cmd->skip_update = 1; } } free(ref_status); }
static void update_shallow(struct fetch_pack_args *args, struct ref **sought, int nr_sought, struct shallow_info *si) { struct sha1_array ref = SHA1_ARRAY_INIT; int *status; int i; if (args->depth > 0 && alternate_shallow_file) { if (*alternate_shallow_file == '\0') { /* --unshallow */ unlink_or_warn(git_path("shallow")); rollback_lock_file(&shallow_lock); } else commit_lock_file(&shallow_lock); return; } if (!si->shallow || !si->shallow->nr) return; if (args->cloning) { /* * remote is shallow, but this is a clone, there are * no objects in repo to worry about. Accept any * shallow points that exist in the pack (iow in repo * after get_pack() and reprepare_packed_git()) */ struct sha1_array extra = SHA1_ARRAY_INIT; unsigned char (*sha1)[20] = si->shallow->sha1; for (i = 0; i < si->shallow->nr; i++) if (has_sha1_file(sha1[i])) sha1_array_append(&extra, sha1[i]); if (extra.nr) { setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, &extra); commit_lock_file(&shallow_lock); } sha1_array_clear(&extra); return; } if (!si->nr_ours && !si->nr_theirs) return; remove_nonexistent_theirs_shallow(si); if (!si->nr_ours && !si->nr_theirs) return; for (i = 0; i < nr_sought; i++) sha1_array_append(&ref, sought[i]->old_sha1); si->ref = &ref; if (args->update_shallow) { /* * remote is also shallow, .git/shallow may be updated * so all refs can be accepted. Make sure we only add * shallow roots that are actually reachable from new * refs. */ struct sha1_array extra = SHA1_ARRAY_INIT; unsigned char (*sha1)[20] = si->shallow->sha1; assign_shallow_commits_to_refs(si, NULL, NULL); if (!si->nr_ours && !si->nr_theirs) { sha1_array_clear(&ref); return; } for (i = 0; i < si->nr_ours; i++) sha1_array_append(&extra, sha1[si->ours[i]]); for (i = 0; i < si->nr_theirs; i++) sha1_array_append(&extra, sha1[si->theirs[i]]); setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, &extra); commit_lock_file(&shallow_lock); sha1_array_clear(&extra); sha1_array_clear(&ref); return; } /* * remote is also shallow, check what ref is safe to update * without updating .git/shallow */ status = xcalloc(nr_sought, sizeof(*status)); assign_shallow_commits_to_refs(si, NULL, status); if (si->nr_ours || si->nr_theirs) { for (i = 0; i < nr_sought; i++) if (status[i]) sought[i]->status = REF_STATUS_REJECT_SHALLOW; } free(status); sha1_array_clear(&ref); }