static void add_alternate_refs(void) { struct sha1_array sa = SHA1_ARRAY_INIT; for_each_alternate_ref(collect_one_alternate_ref, &sa); sha1_array_for_each_unique(&sa, add_one_alternate_sha1, NULL); sha1_array_clear(&sa); }
int main(int argc, char **argv) { struct sha1_array array = SHA1_ARRAY_INIT; struct strbuf line = STRBUF_INIT; while (strbuf_getline_lf(&line, stdin) != EOF) { const char *arg; unsigned char sha1[20]; if (skip_prefix(line.buf, "append ", &arg)) { if (get_sha1_hex(arg, sha1)) die("not a hexadecimal SHA1: %s", arg); sha1_array_append(&array, sha1); } else if (skip_prefix(line.buf, "lookup ", &arg)) { if (get_sha1_hex(arg, sha1)) die("not a hexadecimal SHA1: %s", arg); printf("%d\n", sha1_array_lookup(&array, sha1)); } else if (!strcmp(line.buf, "clear")) sha1_array_clear(&array); else if (!strcmp(line.buf, "for_each_unique")) sha1_array_for_each_unique(&array, print_sha1, NULL); else die("unknown command: %s", line.buf); } return 0; }
static void calculate_changed_submodule_paths(void) { struct rev_info rev; struct commit *commit; struct argv_array argv = ARGV_ARRAY_INIT; /* No need to check if there are no submodules configured */ if (!config_name_for_path.nr) return; init_revisions(&rev, NULL); argv_array_push(&argv, "--"); /* argv[0] program name */ sha1_array_for_each_unique(&ref_tips_after_fetch, add_sha1_to_argv, &argv); argv_array_push(&argv, "--not"); sha1_array_for_each_unique(&ref_tips_before_fetch, add_sha1_to_argv, &argv); setup_revisions(argv.argc, argv.argv, &rev, NULL); if (prepare_revision_walk(&rev)) die("revision walk setup failed"); /* * Collect all submodules (whether checked out or not) for which new * commits have been recorded upstream in "changed_submodule_paths". */ while ((commit = get_revision(&rev))) { struct commit_list *parent = commit->parents; while (parent) { struct diff_options diff_opts; diff_setup(&diff_opts); DIFF_OPT_SET(&diff_opts, RECURSIVE); diff_opts.output_format |= DIFF_FORMAT_CALLBACK; diff_opts.format_callback = submodule_collect_changed_cb; if (diff_setup_done(&diff_opts) < 0) die("diff_setup_done failed"); diff_tree_sha1(parent->item->object.sha1, commit->object.sha1, "", &diff_opts); diffcore_std(&diff_opts); diff_flush(&diff_opts); parent = parent->next; } } argv_array_clear(&argv); sha1_array_clear(&ref_tips_before_fetch); sha1_array_clear(&ref_tips_after_fetch); initialized_fetch_ref_tips = 0; }
static void write_head_info(void) { struct sha1_array sa = SHA1_ARRAY_INIT; for_each_alternate_ref(collect_one_alternate_ref, &sa); sha1_array_for_each_unique(&sa, show_one_alternate_sha1, NULL); sha1_array_clear(&sa); for_each_ref(show_ref_cb, NULL); if (!sent_capabilities) show_ref("capabilities^{}", null_sha1); /* EOF */ packet_flush(1); }
static int update_shallow_ref(struct command *cmd, struct shallow_info *si) { static struct lock_file shallow_lock; struct sha1_array extra = SHA1_ARRAY_INIT; const char *alt_file; uint32_t mask = 1 << (cmd->index % 32); int i; trace_printf_key(&trace_shallow, "shallow: update_shallow_ref %s\n", cmd->ref_name); for (i = 0; i < si->shallow->nr; i++) if (si->used_shallow[i] && (si->used_shallow[i][cmd->index / 32] & mask) && !delayed_reachability_test(si, i)) sha1_array_append(&extra, si->shallow->sha1[i]); setup_alternate_shallow(&shallow_lock, &alt_file, &extra); if (check_shallow_connected(command_singleton_iterator, 0, cmd, alt_file)) { rollback_lock_file(&shallow_lock); sha1_array_clear(&extra); return -1; } commit_lock_file(&shallow_lock); /* * Make sure setup_alternate_shallow() for the next ref does * not lose these new roots.. */ for (i = 0; i < extra.nr; i++) register_shallow(extra.sha1[i]); si->shallow_ref[cmd->index] = 0; sha1_array_clear(&extra); return 0; }
int parse_opt_object_name(const struct option *opt, const char *arg, int unset) { unsigned char sha1[20]; if (unset) { sha1_array_clear(opt->value); return 0; } if (!arg) return -1; if (get_sha1(arg, sha1)) return error(_("malformed object name '%s'"), arg); sha1_array_append(opt->value, sha1); return 0; }
static int builtin_diff_combined(struct rev_info *revs, int argc, const char **argv, struct object_array_entry *ent, int ents) { struct sha1_array parents = SHA1_ARRAY_INIT; int i; if (argc > 1) usage(builtin_diff_usage); if (!revs->dense_combined_merges && !revs->combine_merges) revs->dense_combined_merges = revs->combine_merges = 1; for (i = 1; i < ents; i++) sha1_array_append(&parents, ent[i].item->sha1); diff_tree_combined(ent[0].item->sha1, &parents, revs->dense_combined_merges, revs); sha1_array_clear(&parents); return 0; }
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); }
int transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags, unsigned int *reject_reasons) { *reject_reasons = 0; transport_verify_remote_names(refspec_nr, refspec); if (transport->push) { /* Maybe FIXME. But no important transport uses this case. */ if (flags & TRANSPORT_PUSH_SET_UPSTREAM) die("This transport does not support using --set-upstream"); return transport->push(transport, refspec_nr, refspec, flags); } else if (transport->push_refs) { struct ref *remote_refs; struct ref *local_refs = get_local_heads(); int match_flags = MATCH_REFS_NONE; int verbose = (transport->verbose > 0); int quiet = (transport->verbose < 0); int porcelain = flags & TRANSPORT_PUSH_PORCELAIN; int pretend = flags & TRANSPORT_PUSH_DRY_RUN; int push_ret, ret, err; if (check_push_refs(local_refs, refspec_nr, refspec) < 0) return -1; remote_refs = transport->get_refs_list(transport, 1); if (flags & TRANSPORT_PUSH_ALL) match_flags |= MATCH_REFS_ALL; if (flags & TRANSPORT_PUSH_MIRROR) match_flags |= MATCH_REFS_MIRROR; if (flags & TRANSPORT_PUSH_PRUNE) match_flags |= MATCH_REFS_PRUNE; if (flags & TRANSPORT_PUSH_FOLLOW_TAGS) match_flags |= MATCH_REFS_FOLLOW_TAGS; if (match_push_refs(local_refs, &remote_refs, refspec_nr, refspec, match_flags)) { return -1; } if (transport->smart_options && transport->smart_options->cas && !is_empty_cas(transport->smart_options->cas)) apply_push_cas(transport->smart_options->cas, transport->remote, remote_refs); set_ref_status_for_push(remote_refs, flags & TRANSPORT_PUSH_MIRROR, flags & TRANSPORT_PUSH_FORCE); if (!(flags & TRANSPORT_PUSH_NO_HOOK)) if (run_pre_push_hook(transport, remote_refs)) return -1; if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND | TRANSPORT_RECURSE_SUBMODULES_ONLY)) && !is_bare_repository()) { struct ref *ref = remote_refs; struct sha1_array commits = SHA1_ARRAY_INIT; for (; ref; ref = ref->next) if (!is_null_oid(&ref->new_oid)) sha1_array_append(&commits, ref->new_oid.hash); if (!push_unpushed_submodules(&commits, transport->remote->name, pretend)) { sha1_array_clear(&commits); die("Failed to push all needed submodules!"); } sha1_array_clear(&commits); } if (((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) || ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND | TRANSPORT_RECURSE_SUBMODULES_ONLY)) && !pretend)) && !is_bare_repository()) { struct ref *ref = remote_refs; struct string_list needs_pushing = STRING_LIST_INIT_DUP; struct sha1_array commits = SHA1_ARRAY_INIT; for (; ref; ref = ref->next) if (!is_null_oid(&ref->new_oid)) sha1_array_append(&commits, ref->new_oid.hash); if (find_unpushed_submodules(&commits, transport->remote->name, &needs_pushing)) { sha1_array_clear(&commits); die_with_unpushed_submodules(&needs_pushing); } string_list_clear(&needs_pushing, 0); sha1_array_clear(&commits); } if (!(flags & TRANSPORT_RECURSE_SUBMODULES_ONLY)) push_ret = transport->push_refs(transport, remote_refs, flags); else push_ret = 0; err = push_had_errors(remote_refs); ret = push_ret | err; if (!quiet || err) transport_print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain, reject_reasons); if (flags & TRANSPORT_PUSH_SET_UPSTREAM) set_upstreams(transport, remote_refs, pretend); if (!(flags & (TRANSPORT_PUSH_DRY_RUN | TRANSPORT_RECURSE_SUBMODULES_ONLY))) { struct ref *ref; for (ref = remote_refs; ref; ref = ref->next) transport_update_tracking_ref(transport->remote, ref, verbose); } if (porcelain && !push_ret) puts("Done"); else if (!quiet && !ret && !transport_refs_pushed(remote_refs)) fprintf(stderr, "Everything up-to-date\n"); return ret; } return 1; }
int cmd_receive_pack(int argc, const char **argv, const char *prefix) { int advertise_refs = 0; struct command *commands; struct sha1_array shallow = SHA1_ARRAY_INIT; struct sha1_array ref = SHA1_ARRAY_INIT; struct shallow_info si; struct option options[] = { OPT__QUIET(&quiet, N_("quiet")), OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL), OPT_HIDDEN_BOOL(0, "advertise-refs", &advertise_refs, NULL), OPT_HIDDEN_BOOL(0, "reject-thin-pack-for-testing", &reject_thin, NULL), OPT_END() }; packet_trace_identity("receive-pack"); argc = parse_options(argc, argv, prefix, options, receive_pack_usage, 0); if (argc > 1) usage_msg_opt(_("Too many arguments."), receive_pack_usage, options); if (argc == 0) usage_msg_opt(_("You must specify a directory."), receive_pack_usage, options); service_dir = argv[0]; setup_path(); if (!enter_repo(service_dir, 0)) die("'%s' does not appear to be a git repository", service_dir); git_config(receive_pack_config, NULL); if (cert_nonce_seed) push_cert_nonce = prepare_push_cert_nonce(service_dir, time(NULL)); if (0 <= transfer_unpack_limit) unpack_limit = transfer_unpack_limit; else if (0 <= receive_unpack_limit) unpack_limit = receive_unpack_limit; if (advertise_refs || !stateless_rpc) { write_head_info(); } if (advertise_refs) return 0; if ((commands = read_head_info(&shallow)) != NULL) { const char *unpack_status = NULL; struct string_list push_options = STRING_LIST_INIT_DUP; if (use_push_options) read_push_options(&push_options); prepare_shallow_info(&si, &shallow); if (!si.nr_ours && !si.nr_theirs) shallow_update = 0; if (!delete_only(commands)) { unpack_status = unpack_with_sideband(&si); update_shallow_info(commands, &si, &ref); } use_keepalive = KEEPALIVE_ALWAYS; execute_commands(commands, unpack_status, &si, &push_options); if (pack_lockfile) unlink_or_warn(pack_lockfile); if (report_status) report(commands, unpack_status); run_receive_hook(commands, "post-receive", 1, &push_options); run_update_post_hook(commands); if (push_options.nr) string_list_clear(&push_options, 0); if (auto_gc) { const char *argv_gc_auto[] = { "gc", "--auto", "--quiet", NULL, }; struct child_process proc = CHILD_PROCESS_INIT; proc.no_stdin = 1; proc.stdout_to_stderr = 1; proc.err = use_sideband ? -1 : 0; proc.git_cmd = 1; proc.argv = argv_gc_auto; close_all_packs(); if (!start_command(&proc)) { if (use_sideband) copy_to_sideband(proc.err, -1, NULL); finish_command(&proc); } } if (auto_update_server_info) update_server_info(0); clear_shallow_info(&si); } if (use_sideband) packet_flush(1); sha1_array_clear(&shallow); sha1_array_clear(&ref); free((void *)push_cert_nonce); return 0; }
int cmd_receive_pack(int argc, const char **argv, const char *prefix) { int advertise_refs = 0; int i; struct command *commands; struct sha1_array shallow = SHA1_ARRAY_INIT; struct sha1_array ref = SHA1_ARRAY_INIT; struct shallow_info si; packet_trace_identity("receive-pack"); argv++; for (i = 1; i < argc; i++) { const char *arg = *argv++; if (*arg == '-') { if (!strcmp(arg, "--quiet")) { quiet = 1; continue; } if (!strcmp(arg, "--advertise-refs")) { advertise_refs = 1; continue; } if (!strcmp(arg, "--stateless-rpc")) { stateless_rpc = 1; continue; } if (!strcmp(arg, "--reject-thin-pack-for-testing")) { fix_thin = 0; continue; } usage(receive_pack_usage); } if (service_dir) usage(receive_pack_usage); service_dir = arg; } if (!service_dir) usage(receive_pack_usage); setup_path(); if (!enter_repo(service_dir, 0)) die("'%s' does not appear to be a git repository", service_dir); git_config(receive_pack_config, NULL); if (cert_nonce_seed) push_cert_nonce = prepare_push_cert_nonce(service_dir, time(NULL)); if (0 <= transfer_unpack_limit) unpack_limit = transfer_unpack_limit; else if (0 <= receive_unpack_limit) unpack_limit = receive_unpack_limit; if (advertise_refs || !stateless_rpc) { write_head_info(); } if (advertise_refs) return 0; if ((commands = read_head_info(&shallow)) != NULL) { const char *unpack_status = NULL; prepare_shallow_info(&si, &shallow); if (!si.nr_ours && !si.nr_theirs) shallow_update = 0; if (!delete_only(commands)) { unpack_status = unpack_with_sideband(&si); update_shallow_info(commands, &si, &ref); } execute_commands(commands, unpack_status, &si); if (pack_lockfile) unlink_or_warn(pack_lockfile); if (report_status) report(commands, unpack_status); run_receive_hook(commands, "post-receive", 1); run_update_post_hook(commands); if (auto_gc) { const char *argv_gc_auto[] = { "gc", "--auto", "--quiet", NULL, }; int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR; run_command_v_opt(argv_gc_auto, opt); } if (auto_update_server_info) update_server_info(0); clear_shallow_info(&si); } if (use_sideband) packet_flush(1); sha1_array_clear(&shallow); sha1_array_clear(&ref); free((void *)push_cert_nonce); return 0; }