#include "advice.h"
#include "lockfile.h"
#include "cache-tree.h"
+#include "object-store.h"
+#include "repository.h"
#include "commit.h"
#include "blob.h"
#include "builtin.h"
#include "diff.h"
#include "diffcore.h"
#include "tag.h"
+#include "alloc.h"
#include "unpack-trees.h"
#include "string-list.h"
#include "xdiff-interface.h"
}
if (!oidcmp(&two->object.oid, &shifted))
return two;
- return lookup_tree(&shifted);
+ return lookup_tree(the_repository, &shifted);
}
static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
{
- struct commit *commit = alloc_commit_node();
+ struct commit *commit = alloc_commit_node(the_repository);
set_merge_remote_desc(commit, comment, (struct object *)commit);
commit->maybe_tree = tree;
static void output_commit_title(struct merge_options *o, struct commit *commit)
{
+ struct merge_remote_desc *desc;
+
strbuf_addchars(&o->obuf, ' ', o->call_depth * 2);
- if (commit->util)
- strbuf_addf(&o->obuf, "virtual %s\n",
- merge_remote_util(commit)->name);
+ desc = merge_remote_util(commit);
+ if (desc)
+ strbuf_addf(&o->obuf, "virtual %s\n", desc->name);
else {
strbuf_add_unique_abbrev(&o->obuf, &commit->object.oid,
DEFAULT_ABBREV);
struct cache_entry *ce;
int ret;
- ce = make_cache_entry(mode, oid ? oid->hash : null_sha1, path, stage, 0);
+ ce = make_cache_entry(&the_index, mode, oid ? oid : &null_oid, path, stage, 0);
if (!ce)
return err(o, _("add_cacheinfo failed for path '%s'; merge aborting."), path);
if (refresh) {
struct cache_entry *nce;
- nce = refresh_cache_entry(ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
+ nce = refresh_cache_entry(&the_index, ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
if (!nce)
return err(o, _("add_cacheinfo failed to refresh for path '%s'; merge aborting."), path);
if (nce != ce)
return NULL;
}
- result = lookup_tree(&active_cache_tree->oid);
+ result = lookup_tree(the_repository, &active_cache_tree->oid);
return result;
}
}
if (S_ISREG(mode)) {
struct strbuf strbuf = STRBUF_INIT;
- if (convert_to_working_tree(path, buf, size, &strbuf)) {
+ if (convert_to_working_tree(&the_index, path, buf, size, &strbuf)) {
free(buf);
size = strbuf.len;
buf = strbuf_detach(&strbuf, NULL);
return 0;
}
- if (!(commit_base = lookup_commit_reference(base)) ||
- !(commit_a = lookup_commit_reference(a)) ||
- !(commit_b = lookup_commit_reference(b))) {
+ if (!(commit_base = lookup_commit_reference(the_repository, base)) ||
+ !(commit_a = lookup_commit_reference(the_repository, a)) ||
+ !(commit_b = lookup_commit_reference(the_repository, b))) {
output(o, 1, _("Failed to merge submodule %s (commits not present)"), path);
return 0;
}
output(o, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
output_commit_title(o, commit_b);
} else if (show(o, 2))
- output(o, 2, _("Fast-forwarding submodule %s to %s"), path, oid_to_hex(b));
+ output(o, 2, _("Fast-forwarding submodule %s"), path);
else
; /* no output */
output(o, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
output_commit_title(o, commit_a);
} else if (show(o, 2))
- output(o, 2, _("Fast-forwarding submodule %s to %s"), path, oid_to_hex(a));
+ output(o, 2, _("Fast-forwarding submodule %s"), path);
else
; /* no output */
static struct dir_rename_entry *check_dir_renamed(const char *path,
struct hashmap *dir_renames)
{
- char temp[PATH_MAX];
+ char *temp = xstrdup(path);
char *end;
- struct dir_rename_entry *entry;
+ struct dir_rename_entry *entry = NULL;;
- strcpy(temp, path);
while ((end = strrchr(temp, '/'))) {
*end = '\0';
entry = dir_rename_find_entry(dir_renames, temp);
if (entry)
- return entry;
+ break;
}
- return NULL;
+ free(temp);
+ return entry;
}
static void compute_collisions(struct hashmap *collisions,
head_pairs = get_diffpairs(o, common, head);
merge_pairs = get_diffpairs(o, common, merge);
- dir_re_head = get_directory_renames(head_pairs, head);
- dir_re_merge = get_directory_renames(merge_pairs, merge);
+ if (o->detect_directory_renames) {
+ dir_re_head = get_directory_renames(head_pairs, head);
+ dir_re_merge = get_directory_renames(merge_pairs, merge);
- handle_directory_level_conflicts(o,
- dir_re_head, head,
- dir_re_merge, merge);
+ handle_directory_level_conflicts(o,
+ dir_re_head, head,
+ dir_re_merge, merge);
+ } else {
+ dir_re_head = xmalloc(sizeof(*dir_re_head));
+ dir_re_merge = xmalloc(sizeof(*dir_re_merge));
+ dir_rename_init(dir_re_head);
+ dir_rename_init(dir_re_merge);
+ }
ri->head_renames = get_renames(o, head_pairs,
dir_re_merge, dir_re_head, head,
if (mfi.clean &&
was_tracked_and_matches(o, path, &mfi.oid, mfi.mode) &&
!df_conflict_remains) {
+ int pos;
+ struct cache_entry *ce;
+
output(o, 3, _("Skipped %s (merged same as existing)"), path);
if (add_cacheinfo(o, mfi.mode, &mfi.oid, path,
0, (!o->call_depth && !is_dirty), 0))
return -1;
+ /*
+ * However, add_cacheinfo() will delete the old cache entry
+ * and add a new one. We need to copy over any skip_worktree
+ * flag to avoid making the file appear as if it were
+ * deleted by the user.
+ */
+ pos = index_name_pos(&o->orig_index, path, strlen(path));
+ ce = o->orig_index.cache[pos];
+ if (ce_skip_worktree(ce)) {
+ pos = index_name_pos(&the_index, path, strlen(path));
+ ce = the_index.cache[pos];
+ ce->ce_flags |= CE_SKIP_WORKTREE;
+ }
return mfi.clean;
}
struct tree **result)
{
int code, clean;
+ struct strbuf sb = STRBUF_INIT;
+
+ if (!o->call_depth && index_has_changes(&the_index, head, &sb)) {
+ err(o, _("Your local changes to the following files would be overwritten by merge:\n %s"),
+ sb.buf);
+ return -1;
+ }
if (o->subtree_shift) {
merge = shift_tree_object(head, merge, o->subtree_shift);
}
if (oid_eq(&common->object.oid, &merge->object.oid)) {
- struct strbuf sb = STRBUF_INIT;
-
- if (!o->call_depth && index_has_changes(&sb)) {
- err(o, _("Dirty index: cannot merge (dirty: %s)"),
- sb.buf);
- return 0;
- }
output(o, 0, _("Already up to date!"));
*result = head;
return 1;
/* if there is no common ancestor, use an empty tree */
struct tree *tree;
- tree = lookup_tree(the_hash_algo->empty_tree);
+ tree = lookup_tree(the_repository, the_repository->hash_algo->empty_tree);
merged_common_ancestors = make_virtual_commit(tree, "ancestor");
}
{
struct object *object;
- object = deref_tag(parse_object(oid), name, strlen(name));
+ object = deref_tag(the_repository, parse_object(the_repository, oid),
+ name,
+ strlen(name));
if (!object)
return NULL;
if (object->type == OBJ_TREE)
o->renormalize = 0;
o->diff_detect_rename = -1;
o->merge_detect_rename = -1;
+ o->detect_directory_renames = 1;
merge_recursive_config(o);
merge_verbosity = getenv("GIT_MERGE_VERBOSITY");
if (merge_verbosity)