static int show_modified(struct rev_info *revs, const struct cache_entry *old_entry, const struct cache_entry *new_entry, int report_missing, int cached, int match_missing) { unsigned int mode, oldmode; const struct object_id *oid; unsigned dirty_submodule = 0; if (get_stat_data(new_entry, &oid, &mode, cached, match_missing, &dirty_submodule, &revs->diffopt) < 0) { if (report_missing) diff_index_show_file(revs, "-", old_entry, &old_entry->oid, 1, old_entry->ce_mode, 0); return -1; } if (revs->combine_merges && !cached && (!oideq(oid, &old_entry->oid) || !oideq(&old_entry->oid, &new_entry->oid))) { struct combine_diff_path *p; int pathlen = ce_namelen(new_entry); p = xmalloc(combine_diff_path_size(2, pathlen)); p->path = (char *) &p->parent[2]; p->next = NULL; memcpy(p->path, new_entry->name, pathlen); p->path[pathlen] = 0; p->mode = mode; oidclr(&p->oid); memset(p->parent, 0, 2 * sizeof(struct combine_diff_parent)); p->parent[0].status = DIFF_STATUS_MODIFIED; p->parent[0].mode = new_entry->ce_mode; oidcpy(&p->parent[0].oid, &new_entry->oid); p->parent[1].status = DIFF_STATUS_MODIFIED; p->parent[1].mode = old_entry->ce_mode; oidcpy(&p->parent[1].oid, &old_entry->oid); show_combined_diff(p, 2, revs->dense_combined_merges, revs); free(p); return 0; } oldmode = old_entry->ce_mode; if (mode == oldmode && oideq(oid, &old_entry->oid) && !dirty_submodule && !revs->diffopt.flags.find_copies_harder) return 0; diff_change(&revs->diffopt, oldmode, mode, &old_entry->oid, oid, 1, !is_null_oid(oid), old_entry->name, 0, dirty_submodule); return 0; }
/* An empty entry never compares same, not even to another empty entry */ static int same_entry(struct name_entry *a, struct name_entry *b) { return !is_null_oid(&a->oid) && !is_null_oid(&b->oid) && oideq(&a->oid, &b->oid) && a->mode == b->mode; }
static int check_one_mergetag(struct commit *commit, struct commit_extra_header *extra, void *data) { struct check_mergetag_data *mergetag_data = (struct check_mergetag_data *)data; const char *ref = mergetag_data->argv[0]; struct object_id tag_oid; struct tag *tag; int i; hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &tag_oid); tag = lookup_tag(the_repository, &tag_oid); if (!tag) return error(_("bad mergetag in commit '%s'"), ref); if (parse_tag_buffer(the_repository, tag, extra->value, extra->len)) return error(_("malformed mergetag in commit '%s'"), ref); /* iterate over new parents */ for (i = 1; i < mergetag_data->argc; i++) { struct object_id oid; if (get_oid(mergetag_data->argv[i], &oid) < 0) return error(_("not a valid object name: '%s'"), mergetag_data->argv[i]); if (oideq(&tag->tagged->oid, &oid)) return 0; /* found */ } return error(_("original commit '%s' contains mergetag '%s' that is " "discarded; use --edit instead of --graft"), ref, oid_to_hex(&tag_oid)); }
static void stuff_change(struct diff_options *opt, unsigned old_mode, unsigned new_mode, const struct object_id *old_oid, const struct object_id *new_oid, int old_oid_valid, int new_oid_valid, const char *old_path, const char *new_path) { struct diff_filespec *one, *two; if (!is_null_oid(old_oid) && !is_null_oid(new_oid) && oideq(old_oid, new_oid) && (old_mode == new_mode)) return; if (opt->flags.reverse_diff) { SWAP(old_mode, new_mode); SWAP(old_oid, new_oid); SWAP(old_path, new_path); } if (opt->prefix && (strncmp(old_path, opt->prefix, opt->prefix_length) || strncmp(new_path, opt->prefix, opt->prefix_length))) return; one = alloc_filespec(old_path); two = alloc_filespec(new_path); fill_filespec(one, old_oid, old_oid_valid, old_mode); fill_filespec(two, new_oid, new_oid_valid, new_mode); diff_queue(&diff_queued_diff, one, two); }
static int is_unmatched_ref(const struct ref *ref) { struct object_id oid; const char *p; return ref->match_status == REF_NOT_MATCHED && !parse_oid_hex(ref->name, &oid, &p) && *p == '\0' && oideq(&oid, &ref->old_oid); }
static int config_name_cmp(const void *unused_cmp_data, const void *entry, const void *entry_or_key, const void *unused_keydata) { const struct submodule_entry *a = entry; const struct submodule_entry *b = entry_or_key; return strcmp(a->config->name, b->config->name) || !oideq(&a->config->gitmodules_oid, &b->config->gitmodules_oid); }
int cache_tree_matches_traversal(struct cache_tree *root, struct name_entry *ent, struct traverse_info *info) { struct cache_tree *it; it = find_cache_tree_from_traversal(root, info); it = cache_tree_find(it, ent->path); if (it && it->entry_count > 0 && oideq(ent->oid, &it->oid)) return it->entry_count; return 0; }
static int create_graft(int argc, const char **argv, int force, int gentle) { struct object_id old_oid, new_oid; const char *old_ref = argv[0]; struct commit *commit; struct strbuf buf = STRBUF_INIT; const char *buffer; unsigned long size; if (get_oid(old_ref, &old_oid) < 0) return error(_("not a valid object name: '%s'"), old_ref); commit = lookup_commit_reference(the_repository, &old_oid); if (!commit) return error(_("could not parse %s"), old_ref); buffer = get_commit_buffer(commit, &size); strbuf_add(&buf, buffer, size); unuse_commit_buffer(commit, buffer); if (replace_parents(&buf, argc - 1, &argv[1]) < 0) { strbuf_release(&buf); return -1; } if (remove_signature(&buf)) { warning(_("the original commit '%s' has a gpg signature"), old_ref); warning(_("the signature will be removed in the replacement commit!")); } if (check_mergetags(commit, argc, argv)) { strbuf_release(&buf); return -1; } if (write_object_file(buf.buf, buf.len, commit_type, &new_oid)) { strbuf_release(&buf); return error(_("could not write replacement commit for: '%s'"), old_ref); } strbuf_release(&buf); if (oideq(&old_oid, &new_oid)) { if (gentle) { warning(_("graft for '%s' unnecessary"), oid_to_hex(&old_oid)); return 0; } return error(_("new commit is the same as the old one: '%s'"), oid_to_hex(&old_oid)); } return replace_object_oid(old_ref, &old_oid, "replacement", &new_oid, force); }
static int process_dummy_ref(const char *line) { struct object_id oid; const char *name; if (parse_oid_hex(line, &oid, &name)) return 0; if (*name != ' ') return 0; name++; return oideq(&null_oid, &oid) && !strcmp(name, "capabilities^{}"); }
static int do_reupdate(int ac, const char **av, const char *prefix, int prefix_length) { /* Read HEAD and run update-index on paths that are * merged and already different between index and HEAD. */ int pos; int has_head = 1; struct pathspec pathspec; parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD, prefix, av + 1); if (read_ref("HEAD", &head_oid)) /* If there is no HEAD, that means it is an initial * commit. Update everything in the index. */ has_head = 0; redo: for (pos = 0; pos < active_nr; pos++) { const struct cache_entry *ce = active_cache[pos]; struct cache_entry *old = NULL; int save_nr; char *path; if (ce_stage(ce) || !ce_path_match(&the_index, ce, &pathspec, NULL)) continue; if (has_head) old = read_one_ent(NULL, &head_oid, ce->name, ce_namelen(ce), 0); if (old && ce->ce_mode == old->ce_mode && oideq(&ce->oid, &old->oid)) { discard_cache_entry(old); continue; /* unchanged */ } /* Be careful. The working tree may not have the * path anymore, in which case, under 'allow_remove', * or worse yet 'allow_replace', active_nr may decrease. */ save_nr = active_nr; path = xstrdup(ce->name); update_one(path); free(path); discard_cache_entry(old); if (save_nr != active_nr) goto redo; } clear_pathspec(&pathspec); return 0; }
/** * Given the current HEAD SHA1, the merge head returned from git-fetch and the * fork point calculated by get_rebase_fork_point(), runs git-rebase with the * appropriate arguments and returns its exit status. */ static int run_rebase(const struct object_id *curr_head, const struct object_id *merge_head, const struct object_id *fork_point) { int ret; struct object_id oct_merge_base; struct argv_array args = ARGV_ARRAY_INIT; if (!get_octopus_merge_base(&oct_merge_base, curr_head, merge_head, fork_point)) if (!is_null_oid(fork_point) && oideq(&oct_merge_base, fork_point)) fork_point = NULL; argv_array_push(&args, "rebase"); /* Shared options */ argv_push_verbosity(&args); /* Options passed to git-rebase */ if (opt_rebase == REBASE_MERGES) argv_array_push(&args, "--rebase-merges"); else if (opt_rebase == REBASE_PRESERVE) argv_array_push(&args, "--preserve-merges"); else if (opt_rebase == REBASE_INTERACTIVE) argv_array_push(&args, "--interactive"); if (opt_diffstat) argv_array_push(&args, opt_diffstat); argv_array_pushv(&args, opt_strategies.argv); argv_array_pushv(&args, opt_strategy_opts.argv); if (opt_gpg_sign) argv_array_push(&args, opt_gpg_sign); if (opt_autostash == 0) argv_array_push(&args, "--no-autostash"); else if (opt_autostash == 1) argv_array_push(&args, "--autostash"); if (opt_verify_signatures && !strcmp(opt_verify_signatures, "--verify-signatures")) warning(_("ignoring --verify-signatures for rebase")); argv_array_push(&args, "--onto"); argv_array_push(&args, oid_to_hex(merge_head)); if (fork_point && !is_null_oid(fork_point)) argv_array_push(&args, oid_to_hex(fork_point)); else argv_array_push(&args, oid_to_hex(merge_head)); ret = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); return ret; }
void read_mmblob(mmfile_t *ptr, const struct object_id *oid) { unsigned long size; enum object_type type; if (oideq(oid, &null_oid)) { ptr->ptr = xstrdup(""); ptr->size = 0; return; } ptr->ptr = read_object_file(oid, &type, &size); if (!ptr->ptr || type != OBJ_BLOB) die("unable to read blob object %s", oid_to_hex(oid)); ptr->size = size; }
/* * Emit a warning and return true iff ref1 and ref2 have the same name * and the same oid. Die if they have the same name but different * oids. */ static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2) { if (strcmp(ref1->name, ref2->name)) return 0; /* Duplicate name; make sure that they don't conflict: */ if ((ref1->flag & REF_DIR) || (ref2->flag & REF_DIR)) /* This is impossible by construction */ die("Reference directory conflict: %s", ref1->name); if (!oideq(&ref1->u.value.oid, &ref2->u.value.oid)) die("Duplicated ref, and SHA1s don't match: %s", ref1->name); warning("Duplicated ref: %s", ref1->name); return 1; }
int transport_fetch_refs(struct transport *transport, struct ref *refs) { int rc; int nr_heads = 0, nr_alloc = 0, nr_refs = 0; struct ref **heads = NULL; struct ref *rm; if (!transport->vtable->fetch_without_list) /* * Some transports (e.g. the built-in bundle transport and the * transport helper interface) do not work when fetching is * done immediately after transport creation. List the remote * refs anyway (if not already listed) as a workaround. */ transport_get_remote_refs(transport, NULL); for (rm = refs; rm; rm = rm->next) { nr_refs++; if (rm->peer_ref && !is_null_oid(&rm->old_oid) && oideq(&rm->peer_ref->old_oid, &rm->old_oid)) continue; ALLOC_GROW(heads, nr_heads + 1, nr_alloc); heads[nr_heads++] = rm; } if (!nr_heads) { /* * When deepening of a shallow repository is requested, * then local and remote refs are likely to still be equal. * Just feed them all to the fetch method in that case. * This condition shouldn't be met in a non-deepening fetch * (see builtin/fetch.c:quickfetch()). */ ALLOC_ARRAY(heads, nr_refs); for (rm = refs; rm; rm = rm->next) heads[nr_heads++] = rm; } rc = transport->vtable->fetch(transport, nr_heads, heads); free(heads); return rc; }
/* * When we cannot load the full patch-id for both commits for whatever * reason, the function returns -1 (i.e. return error(...)). Despite * the "neq" in the name of this function, the caller only cares about * the return value being zero (a and b are equivalent) or non-zero (a * and b are different), and returning non-zero would keep both in the * result, even if they actually were equivalent, in order to err on * the side of safety. The actual value being negative does not have * any significance; only that it is non-zero matters. */ static int patch_id_neq(const void *cmpfn_data, const void *entry, const void *entry_or_key, const void *unused_keydata) { /* NEEDSWORK: const correctness? */ struct diff_options *opt = (void *)cmpfn_data; struct patch_id *a = (void *)entry; struct patch_id *b = (void *)entry_or_key; if (is_null_oid(&a->patch_id) && commit_patch_id(a->commit, opt, &a->patch_id, 0)) return error("Could not get patch ID for %s", oid_to_hex(&a->commit->object.oid)); if (is_null_oid(&b->patch_id) && commit_patch_id(b->commit, opt, &b->patch_id, 0)) return error("Could not get patch ID for %s", oid_to_hex(&b->commit->object.oid)); return !oideq(&a->patch_id, &b->patch_id); }
static int edit_and_replace(const char *object_ref, int force, int raw) { char *tmpfile; enum object_type type; struct object_id old_oid, new_oid, prev; struct strbuf ref = STRBUF_INIT; if (get_oid(object_ref, &old_oid) < 0) return error(_("not a valid object name: '%s'"), object_ref); type = oid_object_info(the_repository, &old_oid, NULL); if (type < 0) return error(_("unable to get object type for %s"), oid_to_hex(&old_oid)); if (check_ref_valid(&old_oid, &prev, &ref, force)) { strbuf_release(&ref); return -1; } strbuf_release(&ref); tmpfile = git_pathdup("REPLACE_EDITOBJ"); if (export_object(&old_oid, type, raw, tmpfile)) { free(tmpfile); return -1; } if (launch_editor(tmpfile, NULL, NULL) < 0) { free(tmpfile); return error(_("editing object file failed")); } if (import_object(&new_oid, type, raw, tmpfile)) { free(tmpfile); return -1; } free(tmpfile); if (oideq(&old_oid, &new_oid)) return error(_("new object is the same as the old one: '%s'"), oid_to_hex(&old_oid)); return replace_object_oid(object_ref, &old_oid, "replacement", &new_oid, force); }
static int update_some(const struct object_id *oid, struct strbuf *base, const char *pathname, unsigned mode, int stage, void *context) { int len; struct cache_entry *ce; int pos; if (S_ISDIR(mode)) return READ_TREE_RECURSIVE; len = base->len + strlen(pathname); ce = make_empty_cache_entry(&the_index, len); oidcpy(&ce->oid, oid); memcpy(ce->name, base->buf, base->len); memcpy(ce->name + base->len, pathname, len - base->len); ce->ce_flags = create_ce_flags(0) | CE_UPDATE; ce->ce_namelen = len; ce->ce_mode = create_ce_mode(mode); /* * If the entry is the same as the current index, we can leave the old * entry in place. Whether it is UPTODATE or not, checkout_entry will * do the right thing. */ pos = cache_name_pos(ce->name, ce->ce_namelen); if (pos >= 0) { struct cache_entry *old = active_cache[pos]; if (ce->ce_mode == old->ce_mode && oideq(&ce->oid, &old->oid)) { old->ce_flags |= CE_UPDATE; discard_cache_entry(ce); return 0; } } add_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE); return 0; }
/* * To remove a leaf_node: * Search to the tree location appropriate for the given leaf_node's key: * - If location does not hold a matching entry, abort and do nothing. * - Copy the matching entry's value into the given entry. * - Replace the matching leaf_node with a NULL entry (and free the leaf_node). * - Consolidate int_nodes repeatedly, while walking up the tree towards root. */ static void note_tree_remove(struct notes_tree *t, struct int_node *tree, unsigned char n, struct leaf_node *entry) { struct leaf_node *l; struct int_node *parent_stack[GIT_SHA1_RAWSZ]; unsigned char i, j; void **p = note_tree_search(t, &tree, &n, entry->key_oid.hash); assert(GET_PTR_TYPE(entry) == 0); /* no type bits set */ if (GET_PTR_TYPE(*p) != PTR_TYPE_NOTE) return; /* type mismatch, nothing to remove */ l = (struct leaf_node *) CLR_PTR_TYPE(*p); if (!oideq(&l->key_oid, &entry->key_oid)) return; /* key mismatch, nothing to remove */ /* we have found a matching entry */ oidcpy(&entry->val_oid, &l->val_oid); free(l); *p = SET_PTR_TYPE(NULL, PTR_TYPE_NULL); /* consolidate this tree level, and parent levels, if possible */ if (!n) return; /* cannot consolidate top level */ /* first, build stack of ancestors between root and current node */ parent_stack[0] = t->root; for (i = 0; i < n; i++) { j = GET_NIBBLE(i, entry->key_oid.hash); parent_stack[i + 1] = CLR_PTR_TYPE(parent_stack[i]->a[j]); } assert(i == n && parent_stack[i] == tree); /* next, unwind stack until note_tree_consolidate() is done */ while (i > 0 && !note_tree_consolidate(parent_stack[i], parent_stack[i - 1], GET_NIBBLE(i - 1, entry->key_oid.hash))) i--; }
/* * Skip merging the trees, updating the index and working directory if and * only if we are creating a new branch via "git checkout -b <new_branch>." */ static int skip_merge_working_tree(const struct checkout_opts *opts, const struct branch_info *old_branch_info, const struct branch_info *new_branch_info) { /* * Do the merge if sparse checkout is on and the user has not opted in * to the optimized behavior */ if (core_apply_sparse_checkout && !checkout_optimize_new_branch) return 0; /* * We must do the merge if we are actually moving to a new commit. */ if (!old_branch_info->commit || !new_branch_info->commit || !oideq(&old_branch_info->commit->object.oid, &new_branch_info->commit->object.oid)) return 0; /* * opts->patch_mode cannot be used with switching branches so is * not tested here */ /* * opts->quiet only impacts output so doesn't require a merge */ /* * Honor the explicit request for a three-way merge or to throw away * local changes */ if (opts->merge || opts->force) return 0; /* * --detach is documented as "updating the index and the files in the * working tree" but this optimization skips those steps so fall through * to the regular code path. */ if (opts->force_detach) return 0; /* * opts->writeout_stage cannot be used with switching branches so is * not tested here */ /* * Honor the explicit ignore requests */ if (!opts->overwrite_ignore || opts->ignore_skipworktree || opts->ignore_other_worktrees) return 0; /* * opts->show_progress only impacts output so doesn't require a merge */ /* * opts->overlay_mode cannot be used with switching branches so is * not tested here */ /* * If we aren't creating a new branch any changes or updates will * happen in the existing branch. Since that could only be updating * the index and working directory, we don't want to skip those steps * or we've defeated any purpose in running the command. */ if (!opts->new_branch) return 0; /* * new_branch_force is defined to "create/reset and checkout a branch" * so needs to go through the merge to do the reset */ if (opts->new_branch_force) return 0; /* * A new orphaned branch requrires the index and the working tree to be * adjusted to <start_point> */ if (opts->new_orphan_branch) return 0; /* * Remaining variables are not checkout options but used to track state */ /* * Do the merge if this is the initial checkout. We cannot use * is_cache_unborn() here because the index hasn't been loaded yet * so cache_nr and timestamp.sec are always zero. */ if (!file_exists(get_index_file())) return 0; return 1; }
/* * To insert a leaf_node: * Search to the tree location appropriate for the given leaf_node's key: * - If location is unused (NULL), store the tweaked pointer directly there * - If location holds a note entry that matches the note-to-be-inserted, then * combine the two notes (by calling the given combine_notes function). * - If location holds a note entry that matches the subtree-to-be-inserted, * then unpack the subtree-to-be-inserted into the location. * - If location holds a matching subtree entry, unpack the subtree at that * location, and restart the insert operation from that level. * - Else, create a new int_node, holding both the node-at-location and the * node-to-be-inserted, and store the new int_node into the location. */ static int note_tree_insert(struct notes_tree *t, struct int_node *tree, unsigned char n, struct leaf_node *entry, unsigned char type, combine_notes_fn combine_notes) { struct int_node *new_node; struct leaf_node *l; void **p = note_tree_search(t, &tree, &n, entry->key_oid.hash); int ret = 0; assert(GET_PTR_TYPE(entry) == 0); /* no type bits set */ l = (struct leaf_node *) CLR_PTR_TYPE(*p); switch (GET_PTR_TYPE(*p)) { case PTR_TYPE_NULL: assert(!*p); if (is_null_oid(&entry->val_oid)) free(entry); else *p = SET_PTR_TYPE(entry, type); return 0; case PTR_TYPE_NOTE: switch (type) { case PTR_TYPE_NOTE: if (oideq(&l->key_oid, &entry->key_oid)) { /* skip concatenation if l == entry */ if (oideq(&l->val_oid, &entry->val_oid)) return 0; ret = combine_notes(&l->val_oid, &entry->val_oid); if (!ret && is_null_oid(&l->val_oid)) note_tree_remove(t, tree, n, entry); free(entry); return ret; } break; case PTR_TYPE_SUBTREE: if (!SUBTREE_SHA1_PREFIXCMP(l->key_oid.hash, entry->key_oid.hash)) { /* unpack 'entry' */ load_subtree(t, entry, tree, n); free(entry); return 0; } break; } break; case PTR_TYPE_SUBTREE: if (!SUBTREE_SHA1_PREFIXCMP(entry->key_oid.hash, l->key_oid.hash)) { /* unpack 'l' and restart insert */ *p = NULL; load_subtree(t, l, tree, n); free(l); return note_tree_insert(t, tree, n, entry, type, combine_notes); } break; } /* non-matching leaf_node */ assert(GET_PTR_TYPE(*p) == PTR_TYPE_NOTE || GET_PTR_TYPE(*p) == PTR_TYPE_SUBTREE); if (is_null_oid(&entry->val_oid)) { /* skip insertion of empty note */ free(entry); return 0; } new_node = (struct int_node *) xcalloc(1, sizeof(struct int_node)); ret = note_tree_insert(t, new_node, n + 1, l, GET_PTR_TYPE(*p), combine_notes); if (ret) return ret; *p = SET_PTR_TYPE(new_node, PTR_TYPE_INTERNAL); return note_tree_insert(t, new_node, n + 1, entry, type, combine_notes); }
int cmd_pull(int argc, const char **argv, const char *prefix) { const char *repo, **refspecs; struct oid_array merge_heads = OID_ARRAY_INIT; struct object_id orig_head, curr_head; struct object_id rebase_fork_point; int autostash; if (!getenv("GIT_REFLOG_ACTION")) set_reflog_message(argc, argv); git_config(git_pull_config, NULL); argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0); parse_repo_refspecs(argc, argv, &repo, &refspecs); if (!opt_ff) opt_ff = xstrdup_or_null(config_get_ff()); if (opt_rebase < 0) opt_rebase = config_get_rebase(); if (read_cache_unmerged()) die_resolve_conflict("pull"); if (file_exists(git_path_merge_head(the_repository))) die_conclude_merge(); if (get_oid("HEAD", &orig_head)) oidclr(&orig_head); if (!opt_rebase && opt_autostash != -1) die(_("--[no-]autostash option is only valid with --rebase.")); autostash = config_autostash; if (opt_rebase) { if (opt_autostash != -1) autostash = opt_autostash; if (is_null_oid(&orig_head) && !is_cache_unborn()) die(_("Updating an unborn branch with changes added to the index.")); if (!autostash) require_clean_work_tree(N_("pull with rebase"), _("please commit or stash them."), 1, 0); if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs)) oidclr(&rebase_fork_point); } if (run_fetch(repo, refspecs)) return 1; if (opt_dry_run) return 0; if (get_oid("HEAD", &curr_head)) oidclr(&curr_head); if (!is_null_oid(&orig_head) && !is_null_oid(&curr_head) && !oideq(&orig_head, &curr_head)) { /* * The fetch involved updating the current branch. * * The working tree and the index file are still based on * orig_head commit, but we are merging into curr_head. * Update the working tree to match curr_head. */ warning(_("fetch updated the current branch head.\n" "fast-forwarding your working tree from\n" "commit %s."), oid_to_hex(&orig_head)); if (checkout_fast_forward(&orig_head, &curr_head, 0)) die(_("Cannot fast-forward your working tree.\n" "After making sure that you saved anything precious from\n" "$ git diff %s\n" "output, run\n" "$ git reset --hard\n" "to recover."), oid_to_hex(&orig_head)); } get_merge_heads(&merge_heads); if (!merge_heads.nr) die_no_merge_candidates(repo, refspecs); if (is_null_oid(&orig_head)) { if (merge_heads.nr > 1) die(_("Cannot merge multiple branches into empty head.")); return pull_into_void(merge_heads.oid, &curr_head); } if (opt_rebase && merge_heads.nr > 1) die(_("Cannot rebase onto multiple branches.")); if (opt_rebase) { int ret = 0; if ((recurse_submodules == RECURSE_SUBMODULES_ON || recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) && submodule_touches_in_range(&rebase_fork_point, &curr_head)) die(_("cannot rebase with locally recorded submodule modifications")); if (!autostash) { struct commit_list *list = NULL; struct commit *merge_head, *head; head = lookup_commit_reference(the_repository, &orig_head); commit_list_insert(head, &list); merge_head = lookup_commit_reference(the_repository, &merge_heads.oid[0]); if (is_descendant_of(merge_head, list)) { /* we can fast-forward this without invoking rebase */ opt_ff = "--ff-only"; ret = run_merge(); } } ret = run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point); if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON || recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)) ret = rebase_submodules(); return ret; } else { int ret = run_merge(); if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON || recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)) ret = update_submodules(); return ret; } }
static int do_apply_stash(const char *prefix, struct stash_info *info, int index, int quiet) { int ret; int has_index = index; struct merge_options o; struct object_id c_tree; struct object_id index_tree; struct commit *result; const struct object_id *bases[1]; read_cache_preload(NULL); if (refresh_cache(REFRESH_QUIET)) return -1; if (write_cache_as_tree(&c_tree, 0, NULL)) return error(_("cannot apply a stash in the middle of a merge")); if (index) { if (oideq(&info->b_tree, &info->i_tree) || oideq(&c_tree, &info->i_tree)) { has_index = 0; } else { struct strbuf out = STRBUF_INIT; if (diff_tree_binary(&out, &info->w_commit)) { strbuf_release(&out); return error(_("could not generate diff %s^!."), oid_to_hex(&info->w_commit)); } ret = apply_cached(&out); strbuf_release(&out); if (ret) return error(_("conflicts in index." "Try without --index.")); discard_cache(); read_cache(); if (write_cache_as_tree(&index_tree, 0, NULL)) return error(_("could not save index tree")); reset_head(); } } if (info->has_u && restore_untracked(&info->u_tree)) return error(_("could not restore untracked files from stash")); init_merge_options(&o, the_repository); o.branch1 = "Updated upstream"; o.branch2 = "Stashed changes"; if (oideq(&info->b_tree, &c_tree)) o.branch1 = "Version stash was based on"; if (quiet) o.verbosity = 0; if (o.verbosity >= 3) printf_ln(_("Merging %s with %s"), o.branch1, o.branch2); bases[0] = &info->b_tree; ret = merge_recursive_generic(&o, &c_tree, &info->w_tree, 1, bases, &result); if (ret) { rerere(0); if (index) fprintf_ln(stderr, _("Index was not unstashed.")); return ret; } if (has_index) { if (reset_tree(&index_tree, 0, 0)) return -1; } else { struct strbuf out = STRBUF_INIT; if (get_newly_staged(&out, &c_tree)) { strbuf_release(&out); return -1; } if (reset_tree(&c_tree, 0, 1)) { strbuf_release(&out); return -1; } ret = update_index(&out); strbuf_release(&out); if (ret) return -1; discard_cache(); } if (quiet) { if (refresh_cache(REFRESH_QUIET)) warning("could not refresh index"); } else { struct child_process cp = CHILD_PROCESS_INIT; /* * Status is quite simple and could be replaced with calls to * wt_status in the future, but it adds complexities which may * require more tests. */ cp.git_cmd = 1; cp.dir = prefix; argv_array_push(&cp.args, "status"); run_command(&cp); } return 0; }
static void filter_refs(struct fetch_pack_args *args, struct ref **refs, struct ref **sought, int nr_sought) { struct ref *newlist = NULL; struct ref **newtail = &newlist; struct ref *unmatched = NULL; struct ref *ref, *next; struct oidset tip_oids = OIDSET_INIT; int i; i = 0; for (ref = *refs; ref; ref = next) { int keep = 0; next = ref->next; if (starts_with(ref->name, "refs/") && check_refname_format(ref->name, 0)) ; /* trash */ else { while (i < nr_sought) { int cmp = strcmp(ref->name, sought[i]->name); if (cmp < 0) break; /* definitely do not have it */ else if (cmp == 0) { keep = 1; /* definitely have it */ sought[i]->match_status = REF_MATCHED; } i++; } if (!keep && args->fetch_all && (!args->deepen || !starts_with(ref->name, "refs/tags/"))) keep = 1; } if (keep) { *newtail = ref; ref->next = NULL; newtail = &ref->next; } else { ref->next = unmatched; unmatched = ref; } } /* Append unmatched requests to the list */ for (i = 0; i < nr_sought; i++) { struct object_id oid; const char *p; ref = sought[i]; if (ref->match_status != REF_NOT_MATCHED) continue; if (parse_oid_hex(ref->name, &oid, &p) || *p != '\0' || !oideq(&oid, &ref->old_oid)) continue; if ((allow_unadvertised_object_request & (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1)) || tip_oids_contain(&tip_oids, unmatched, newlist, &ref->old_oid)) { ref->match_status = REF_MATCHED; *newtail = copy_ref(ref); newtail = &(*newtail)->next; } else { ref->match_status = REF_UNADVERTISED_NOT_ALLOWED; } } oidset_clear(&tip_oids); for (ref = unmatched; ref; ref = next) { next = ref->next; free(ref); } *refs = newlist; }
static void verify_one(struct repository *r, struct index_state *istate, struct cache_tree *it, struct strbuf *path) { int i, pos, len = path->len; struct strbuf tree_buf = STRBUF_INIT; struct object_id new_oid; for (i = 0; i < it->subtree_nr; i++) { strbuf_addf(path, "%s/", it->down[i]->name); verify_one(r, istate, it->down[i]->cache_tree, path); strbuf_setlen(path, len); } if (it->entry_count < 0 || /* no verification on tests (t7003) that replace trees */ lookup_replace_object(r, &it->oid) != &it->oid) return; if (path->len) { pos = index_name_pos(istate, path->buf, path->len); pos = -pos - 1; } else { pos = 0; } i = 0; while (i < it->entry_count) { struct cache_entry *ce = istate->cache[pos + i]; const char *slash; struct cache_tree_sub *sub = NULL; const struct object_id *oid; const char *name; unsigned mode; int entlen; if (ce->ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE)) BUG("%s with flags 0x%x should not be in cache-tree", ce->name, ce->ce_flags); name = ce->name + path->len; slash = strchr(name, '/'); if (slash) { entlen = slash - name; sub = find_subtree(it, ce->name + path->len, entlen, 0); if (!sub || sub->cache_tree->entry_count < 0) BUG("bad subtree '%.*s'", entlen, name); oid = &sub->cache_tree->oid; mode = S_IFDIR; i += sub->cache_tree->entry_count; } else { oid = &ce->oid; mode = ce->ce_mode; entlen = ce_namelen(ce) - path->len; i++; } strbuf_addf(&tree_buf, "%o %.*s%c", mode, entlen, name, '\0'); strbuf_add(&tree_buf, oid->hash, the_hash_algo->rawsz); } hash_object_file(tree_buf.buf, tree_buf.len, tree_type, &new_oid); if (!oideq(&new_oid, &it->oid)) BUG("cache-tree for path %.*s does not match. " "Expected %s got %s", len, path->buf, oid_to_hex(&new_oid), oid_to_hex(&it->oid)); strbuf_setlen(path, len); strbuf_release(&tree_buf); }
static int unresolve_one(const char *path) { int namelen = strlen(path); int pos; int ret = 0; struct cache_entry *ce_2 = NULL, *ce_3 = NULL; /* See if there is such entry in the index. */ pos = cache_name_pos(path, namelen); if (0 <= pos) { /* already merged */ pos = unmerge_cache_entry_at(pos); if (pos < active_nr) { const struct cache_entry *ce = active_cache[pos]; if (ce_stage(ce) && ce_namelen(ce) == namelen && !memcmp(ce->name, path, namelen)) return 0; } /* no resolve-undo information; fall back */ } else { /* If there isn't, either it is unmerged, or * resolved as "removed" by mistake. We do not * want to do anything in the former case. */ pos = -pos-1; if (pos < active_nr) { const struct cache_entry *ce = active_cache[pos]; if (ce_namelen(ce) == namelen && !memcmp(ce->name, path, namelen)) { fprintf(stderr, "%s: skipping still unmerged path.\n", path); goto free_return; } } } /* Grab blobs from given path from HEAD and MERGE_HEAD, * stuff HEAD version in stage #2, * stuff MERGE_HEAD version in stage #3. */ ce_2 = read_one_ent("our", &head_oid, path, namelen, 2); ce_3 = read_one_ent("their", &merge_head_oid, path, namelen, 3); if (!ce_2 || !ce_3) { ret = -1; goto free_return; } if (oideq(&ce_2->oid, &ce_3->oid) && ce_2->ce_mode == ce_3->ce_mode) { fprintf(stderr, "%s: identical in both, skipping.\n", path); goto free_return; } remove_file_from_cache(path); if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) { error("%s: cannot add our version to the index.", path); ret = -1; goto free_return; } if (!add_cache_entry(ce_3, ADD_CACHE_OK_TO_ADD)) return 0; error("%s: cannot add their version to the index.", path); ret = -1; free_return: discard_cache_entry(ce_2); discard_cache_entry(ce_3); return ret; }