From: Junio C Hamano <junkio@cox.net>
To: "Shawn O. Pearce" <spearce@spearce.org>
Cc: git@vger.kernel.org
Subject: Re: bug in read-tree -m on A -> A/A
Date: Thu, 15 Mar 2007 23:25:22 -0700 [thread overview]
Message-ID: <7v6491yab1.fsf@assigned-by-dhcp.cox.net> (raw)
In-Reply-To: <7v4polzsrn.fsf@assigned-by-dhcp.cox.net> (Junio C. Hamano's message of "Thu, 15 Mar 2007 22:01:16 -0700")
Junio C Hamano <junkio@cox.net> writes:
> "Shawn O. Pearce" <spearce@spearce.org> writes:
>
>> .... The following test appears to
>> trigger the same failure,...
>
> You have file "A" on one branch, and file "A/A" on another
> branch. You are on the latter branch and switching to the
> former one.
>
> The following patch illustrates where you need to implement an
> alternate, loosened check, but should not be applied to your
> tree as-is. If you have local modification to path "A/A", this
> will lose it.
This does not do the bottom-up merge, but tries to catch the
lossy case within the limit of the current framework.
Only lightly tested, and I won't be applying it as-is yet as I
am not thinking very clearly tonight (no, I am not drunk, just
under the weather a bit).
Testing and improvements are very much appreciated.
---
unpack-trees.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 74 insertions(+), 1 deletions(-)
diff --git a/unpack-trees.c b/unpack-trees.c
index 2e2232c..2288762 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -468,6 +468,60 @@ static void invalidate_ce_path(struct cache_entry *ce)
cache_tree_invalidate_path(active_cache_tree, ce->name);
}
+static void verify_clean_subdirectory(const char *path, const char *action,
+ struct unpack_trees_options *o)
+{
+ /*
+ * we are about to extract "path"; we would not want to lose
+ * anything in the existing directory there.
+ */
+ int namelen;
+ int pos, i;
+ struct dir_struct d;
+ char *pathbuf;
+
+ /*
+ * First let's make sure we do not have a local modification
+ * in that directory.
+ */
+ namelen = strlen(path);
+ pos = cache_name_pos(path, namelen);
+ if (0 <= pos)
+ return; /* we have it as nondirectory */
+ pos = -pos - 1;
+ for (i = pos; i < active_nr; i++) {
+ struct cache_entry *ce = active_cache[i];
+ int len = ce_namelen(ce);
+ if (len < namelen ||
+ strncmp(path, ce->name, namelen) ||
+ ce->name[namelen] != '/')
+ break;
+ /*
+ * ce->name is an entry in the subdirectory.
+ */
+ verify_uptodate(ce, o);
+ }
+
+ /*
+ * Then we need to make sure that we do not lose a locally
+ * present file that is not ignored.
+ */
+ if (!o->dir)
+ return;
+
+ pathbuf = xmalloc(namelen + 2);
+ memcpy(pathbuf, path, namelen);
+ strcpy(pathbuf+namelen, "/");
+
+ memset(&d, 0, sizeof(d));
+ d.exclude_per_dir = o->dir->exclude_per_dir;
+ i = read_directory(&d, path, pathbuf, namelen+1);
+ if (i)
+ die("Updating '%s' would lose untracked files in it",
+ path);
+ free(pathbuf);
+}
+
/*
* We do not want to remove or overwrite a working tree file that
* is not tracked, unless it is ignored.
@@ -479,9 +533,28 @@ static void verify_absent(const char *path, const char *action,
if (o->index_only || o->reset || !o->update)
return;
- if (!lstat(path, &st) && !(o->dir && excluded(o->dir, path)))
+
+ if (!lstat(path, &st)) {
+ if (o->dir && excluded(o->dir, path))
+ /*
+ * path is explicitly excluded, so it is Ok to
+ * overwrite it.
+ */
+ return;
+ if (S_ISDIR(st.st_mode))
+ /*
+ * We are checking out path "foo" and
+ * found "foo/." in the working tree.
+ * This is tricky -- if we have modified
+ * files that are in "foo/" we would lose
+ * it.
+ */
+ verify_clean_subdirectory(path, action, o);
+ return;
+
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,
prev parent reply other threads:[~2007-03-16 6:25 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-03-16 4:19 bug in read-tree -m on A -> A/A Shawn O. Pearce
2007-03-16 5:01 ` Junio C Hamano
2007-03-16 6:25 ` Junio C Hamano [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7v6491yab1.fsf@assigned-by-dhcp.cox.net \
--to=junkio@cox.net \
--cc=git@vger.kernel.org \
--cc=spearce@spearce.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox