static int process_ref(int len, struct ref ***list, unsigned int flags, struct oid_array *extra_have) { struct object_id old_oid; const char *name; if (parse_oid_hex(packet_buffer, &old_oid, &name)) return 0; if (*name != ' ') return 0; name++; if (extra_have && !strcmp(name, ".have")) { oid_array_append(extra_have, &old_oid); } else if (!strcmp(name, "capabilities^{}")) { die("protocol error: unexpected capabilities^{}"); } else if (check_ref(name, flags)) { struct ref *ref = alloc_ref(name); oidcpy(&ref->old_oid, &old_oid); **list = ref; *list = &ref->next; } check_no_capabilities(len); return 1; }
static int parse_have(const char *line, struct oid_array *haves) { const char *arg; if (skip_prefix(line, "have ", &arg)) { struct object_id oid; if (get_oid_hex(arg, &oid)) die("git upload-pack: expected SHA1 object, got '%s'", arg); oid_array_append(haves, &oid); return 1; } return 0; }
int parse_opt_object_name(const struct option *opt, const char *arg, int unset) { struct object_id oid; if (unset) { oid_array_clear(opt->value); return 0; } if (!arg) return -1; if (get_oid(arg, &oid)) return error(_("malformed object name '%s'"), arg); oid_array_append(opt->value, &oid); return 0; }
static int process_shallow(int len, struct oid_array *shallow_points) { const char *arg; struct object_id old_oid; if (!skip_prefix(packet_buffer, "shallow ", &arg)) return 0; if (get_oid_hex(arg, &old_oid)) die("protocol error: expected shallow sha-1, got '%s'", arg); if (!shallow_points) die("repository on the other end cannot be shallow"); oid_array_append(shallow_points, &old_oid); check_no_capabilities(len); return 1; }
/** * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge * into merge_heads. */ static void get_merge_heads(struct oid_array *merge_heads) { const char *filename = git_path_fetch_head(the_repository); FILE *fp; struct strbuf sb = STRBUF_INIT; struct object_id oid; fp = xfopen(filename, "r"); while (strbuf_getline_lf(&sb, fp) != EOF) { if (get_oid_hex(sb.buf, &oid)) continue; /* invalid line: does not start with SHA1 */ if (starts_with(sb.buf + GIT_SHA1_HEXSZ, "\tnot-for-merge\t")) continue; /* ref is not-for-merge */ oid_array_append(merge_heads, &oid); } fclose(fp); strbuf_release(&sb); }
static void add_ref_to_island(const char *island_name, const struct object_id *oid) { uint64_t sha_core; struct remote_island *rl = NULL; int hash_ret; khiter_t pos = kh_put_str(remote_islands, island_name, &hash_ret); if (hash_ret) { kh_key(remote_islands, pos) = xstrdup(island_name); kh_value(remote_islands, pos) = xcalloc(1, sizeof(struct remote_island)); } rl = kh_value(remote_islands, pos); oid_array_append(&rl->oids, oid); memcpy(&sha_core, oid->hash, sizeof(uint64_t)); rl->hash += sha_core; }
static int builtin_diff_combined(struct rev_info *revs, int argc, const char **argv, struct object_array_entry *ent, int ents) { struct oid_array parents = OID_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++) oid_array_append(&parents, &ent[i].item->oid); diff_tree_combined(&ent[0].item->oid, &parents, revs->dense_combined_merges, revs); oid_array_clear(&parents); return 0; }
static int process_haves(struct oid_array *haves, struct oid_array *common) { int i; /* Process haves */ for (i = 0; i < haves->nr; i++) { const struct object_id *oid = &haves->oid[i]; struct object *o; int we_knew_they_have = 0; if (!has_object_file(oid)) continue; oid_array_append(common, oid); o = parse_object(oid); if (!o) die("oops (%s)", oid_to_hex(oid)); if (o->type == OBJ_COMMIT) { struct commit_list *parents; struct commit *commit = (struct commit *)o; if (o->flags & THEY_HAVE) we_knew_they_have = 1; else o->flags |= THEY_HAVE; if (!oldest_have || (commit->date < oldest_have)) oldest_have = commit->date; for (parents = commit->parents; parents; parents = parents->next) parents->item->object.flags |= THEY_HAVE; } if (!we_knew_they_have) add_object_array(o, NULL, &have_obj); } return 0; }
static void init_skiplist(struct fsck_options *options, const char *path) { static struct oid_array skiplist = OID_ARRAY_INIT; int sorted, fd; char buffer[GIT_MAX_HEXSZ + 1]; struct object_id oid; if (options->skiplist) sorted = options->skiplist->sorted; else { sorted = 1; options->skiplist = &skiplist; } fd = open(path, O_RDONLY); if (fd < 0) die("Could not open skip list: %s", path); for (;;) { const char *p; int result = read_in_full(fd, buffer, sizeof(buffer)); if (result < 0) die_errno("Could not read '%s'", path); if (!result) break; if (parse_oid_hex(buffer, &oid, &p) || *p != '\n') die("Invalid SHA-1: %s", buffer); oid_array_append(&skiplist, &oid); if (sorted && skiplist.nr > 1 && oidcmp(&skiplist.oid[skiplist.nr - 2], &oid) > 0) sorted = 0; } close(fd); if (sorted) skiplist.sorted = 1; }
int transport_push(struct transport *transport, struct refspec *rs, int flags, unsigned int *reject_reasons) { *reject_reasons = 0; if (transport_color_config() < 0) return -1; if (transport->vtable->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; struct argv_array ref_prefixes = ARGV_ARRAY_INIT; if (check_push_refs(local_refs, rs) < 0) return -1; refspec_ref_prefixes(rs, &ref_prefixes); remote_refs = transport->vtable->get_refs_list(transport, 1, &ref_prefixes); argv_array_clear(&ref_prefixes); 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, rs, 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 oid_array commits = OID_ARRAY_INIT; for (; ref; ref = ref->next) if (!is_null_oid(&ref->new_oid)) oid_array_append(&commits, &ref->new_oid); if (!push_unpushed_submodules(&the_index, &commits, transport->remote, rs, transport->push_options, pretend)) { oid_array_clear(&commits); die(_("failed to push all needed submodules")); } oid_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 oid_array commits = OID_ARRAY_INIT; for (; ref; ref = ref->next) if (!is_null_oid(&ref->new_oid)) oid_array_append(&commits, &ref->new_oid); if (find_unpushed_submodules(&the_index, &commits, transport->remote->name, &needs_pushing)) { oid_array_clear(&commits); die_with_unpushed_submodules(&needs_pushing); } string_list_clear(&needs_pushing, 0); oid_array_clear(&commits); } if (!(flags & TRANSPORT_RECURSE_SUBMODULES_ONLY)) push_ret = transport->vtable->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; }
static void update_shallow(struct fetch_pack_args *args, struct ref **sought, int nr_sought, struct shallow_info *si) { struct oid_array ref = OID_ARRAY_INIT; int *status; int i; if (args->deepen && alternate_shallow_file) { if (*alternate_shallow_file == '\0') { /* --unshallow */ unlink_or_warn(git_path_shallow(the_repository)); 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 oid_array extra = OID_ARRAY_INIT; struct object_id *oid = si->shallow->oid; for (i = 0; i < si->shallow->nr; i++) if (has_object_file(&oid[i])) oid_array_append(&extra, &oid[i]); if (extra.nr) { setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, &extra); commit_lock_file(&shallow_lock); } oid_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++) oid_array_append(&ref, &sought[i]->old_oid); 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 oid_array extra = OID_ARRAY_INIT; struct object_id *oid = si->shallow->oid; assign_shallow_commits_to_refs(si, NULL, NULL); if (!si->nr_ours && !si->nr_theirs) { oid_array_clear(&ref); return; } for (i = 0; i < si->nr_ours; i++) oid_array_append(&extra, &oid[si->ours[i]]); for (i = 0; i < si->nr_theirs; i++) oid_array_append(&extra, &oid[si->theirs[i]]); setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, &extra); commit_lock_file(&shallow_lock); oid_array_clear(&extra); oid_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); oid_array_clear(&ref); }