aboutsummaryrefslogtreecommitdiff
path: root/read-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'read-tree.c')
-rw-r--r--read-tree.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/read-tree.c b/read-tree.c
index 49436bf96..99e7c7504 100644
--- a/read-tree.c
+++ b/read-tree.c
@@ -13,6 +13,7 @@
#include <sys/time.h>
#include <signal.h>
+static int reset = 0;
static int merge = 0;
static int update = 0;
static int index_only = 0;
@@ -408,7 +409,7 @@ static void verify_uptodate(struct cache_entry *ce)
{
struct stat st;
- if (index_only)
+ if (index_only || reset)
return;
if (!lstat(ce->name, &st)) {
@@ -417,6 +418,10 @@ static void verify_uptodate(struct cache_entry *ce)
return;
errno = 0;
}
+ if (reset) {
+ ce->ce_flags |= htons(CE_UPDATE);
+ return;
+ }
if (errno == ENOENT)
return;
die("Entry '%s' not uptodate. Cannot merge.", ce->name);
@@ -428,6 +433,21 @@ static void invalidate_ce_path(struct cache_entry *ce)
cache_tree_invalidate_path(active_cache_tree, ce->name);
}
+/*
+ * We do not want to remove or overwrite a working tree file that
+ * is not tracked.
+ */
+static void verify_absent(const char *path, const char *action)
+{
+ struct stat st;
+
+ if (index_only || reset || !update)
+ return;
+ if (!lstat(path, &st))
+ die("Untracked working tree file '%s' "
+ "would be %s by merge.", path, action);
+}
+
static int merged_entry(struct cache_entry *merge, struct cache_entry *old)
{
merge->ce_flags |= htons(CE_UPDATE);
@@ -446,8 +466,11 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old)
invalidate_ce_path(old);
}
}
- else
+ else {
+ verify_absent(merge->name, "overwritten");
invalidate_ce_path(merge);
+ }
+
merge->ce_flags &= ~htons(CE_STAGEMASK);
add_cache_entry(merge, ADD_CACHE_OK_TO_ADD);
return 1;
@@ -457,6 +480,8 @@ static int deleted_entry(struct cache_entry *ce, struct cache_entry *old)
{
if (old)
verify_uptodate(old);
+ else
+ verify_absent(ce->name, "removed");
ce->ce_mode = 0;
add_cache_entry(ce, ADD_CACHE_OK_TO_ADD);
invalidate_ce_path(ce);
@@ -493,6 +518,7 @@ static int threeway_merge(struct cache_entry **stages)
int count;
int head_match = 0;
int remote_match = 0;
+ const char *path = NULL;
int df_conflict_head = 0;
int df_conflict_remote = 0;
@@ -504,8 +530,11 @@ static int threeway_merge(struct cache_entry **stages)
for (i = 1; i < head_idx; i++) {
if (!stages[i])
any_anc_missing = 1;
- else
+ else {
+ if (!path)
+ path = stages[i]->name;
no_anc_exists = 0;
+ }
}
index = stages[0];
@@ -521,8 +550,15 @@ static int threeway_merge(struct cache_entry **stages)
remote = NULL;
}
+ if (!path && index)
+ path = index->name;
+ if (!path && head)
+ path = head->name;
+ if (!path && remote)
+ path = remote->name;
+
/* First, if there's a #16 situation, note that to prevent #13
- * and #14.
+ * and #14.
*/
if (!same(remote, head)) {
for (i = 1; i < head_idx; i++) {
@@ -581,6 +617,8 @@ static int threeway_merge(struct cache_entry **stages)
(remote_deleted && head && head_match)) {
if (index)
return deleted_entry(index, index);
+ else if (path)
+ verify_absent(path, "removed");
return 0;
}
/*
@@ -598,6 +636,8 @@ static int threeway_merge(struct cache_entry **stages)
if (index) {
verify_uptodate(index);
}
+ else if (path)
+ verify_absent(path, "overwritten");
nontrivial_merge = 1;
@@ -694,14 +734,18 @@ static int oneway_merge(struct cache_entry **src)
return error("Cannot do a oneway merge of %d trees",
merge_size);
- if (!a) {
- invalidate_ce_path(old);
- return 0;
- }
+ if (!a)
+ return deleted_entry(old, old);
if (old && same(old, a)) {
+ if (reset) {
+ struct stat st;
+ if (lstat(old->name, &st) ||
+ ce_match_stat(old, &st, 1))
+ old->ce_flags |= htons(CE_UPDATE);
+ }
return keep_entry(old);
}
- return merged_entry(a, NULL);
+ return merged_entry(a, old);
}
static int read_cache_unmerged(void)
@@ -731,7 +775,7 @@ static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
{
struct tree_entry_list *ent;
int cnt;
-
+
memcpy(it->sha1, tree->object.sha1, 20);
for (cnt = 0, ent = tree->entries; ent; ent = ent->next) {
if (!ent->directory)
@@ -766,7 +810,7 @@ static struct cache_file cache_file;
int main(int argc, char **argv)
{
- int i, newfd, reset, stage = 0;
+ int i, newfd, stage = 0;
unsigned char sha1[20];
merge_fn_t fn = NULL;
@@ -841,8 +885,8 @@ int main(int argc, char **argv)
if (1 < index_only + update)
usage(read_tree_usage);
- if (get_sha1(arg, sha1) < 0)
- usage(read_tree_usage);
+ if (get_sha1(arg, sha1))
+ die("Not a valid object name %s", arg);
if (list_tree(sha1) < 0)
die("failed to unpack tree object %s", arg);
stage++;