From: Junio C Hamano <junkio@cox.net>
To: Petr Baudis <pasky@ucw.cz>
Cc: Kay Sievers <kay.sievers@vrfy.org>, git@vger.kernel.org
Subject: Re: Broken adding of cache entries
Date: Sat, 07 May 2005 18:50:34 -0700 [thread overview]
Message-ID: <7vbr7m8p05.fsf@assigned-by-dhcp.cox.net> (raw)
In-Reply-To: <7vll6q8s4o.fsf@assigned-by-dhcp.cox.net> (Junio C. Hamano's message of "Sat, 07 May 2005 17:43:03 -0700")
This patch makes git-update-cache --add refuse to create an
index where one entry is a file and another entry needs to have
that entry as its leading directory.
I am not quite sure the semantics is quite right, so I am
holding it off from putting it in git-jc repository for now, but
please review it, give it a try and tell me what you think.
Here is what I did.
$ ls -a
./ ../
$ git-init-db
defaulting to local storage area
$ date >path
$ git-update-cache --add path
$ rm -f path; mkdir path; date >path/file
$ git-update-cache --add path/file
fatal: Unable to add path/file to database
$ git-update-cache --remove path ;# *****
fatal: Unable to add path to database
$ git-update-cache --force-remove path
$ git-update-cache --add path/file
$ git-ls-files --stage
100644 3e3f5e43a8e7baa7f0b1f2d7b99ed25fcbe582d2 0 path/file
$ rm -fr path
$ git-update-cache --remove path/file
$ mkdir path; date >path/file
$ git-update-cache --add path/file
$ git-ls-files --stage
100644 1b4e067c82b90419c2d2ce80e72079f926a49cc3 0 path/file
$ rm -fr path; date >path
$ git-update-cache --add path
fatal: Unable to add path to database
$ git-update-cache --remove path/file
$ git-update-cache --add path
$ git-ls-files --stage
100644 b4509b7a4fed200befc45746061eb1d32ad6cbc9 0 path
The one marked with ***** is what I am debating myself about,
but that one would probably be an independent fix.
Not-signed-off-yet-by: Junio C Hamano <junkio@cox.net>
---
jit-diff 0:7 read-cache.c
# - HEAD: Notice tree objects with duplicate entries.
# + 7: Refuse to create file/dir conflict cache entry.
--- a/read-cache.c
+++ b/read-cache.c
@@ -123,6 +123,64 @@ int same_name(struct cache_entry *a, str
return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
}
+/* We may be in a situation where we already have
+ * path/file and path is being added, or we already
+ * have path and path/file is being added. Either one
+ * would result in a nonsense tree that has path twice
+ * when git-write-tree tries to write it out. Prevent it.
+ */
+static int check_file_directory_conflict(const char *path)
+{
+ int pos;
+ int namelen = strlen(path);
+ char *pathbuf = xmalloc(namelen + 1);
+ char *cp;
+
+ memcpy(pathbuf, path, namelen + 1);
+
+ cp = pathbuf;
+ while (1) {
+ char *ep = strchr(cp, '/');
+ if (ep == 0)
+ break;
+ *ep = 0;
+ pos = cache_name_pos(pathbuf,
+ htons(create_ce_flags(ep-cp, 0)));
+ if (0 <= pos) {
+ /* Our leading path component is registered as a file,
+ * and we are trying to make it a directory.
+ */
+ free(pathbuf);
+ return -1;
+ }
+ *ep = '/';
+ cp = ep + 1;
+ }
+ free(pathbuf);
+
+ /* Do we have an entry in the cache that makes our path a prefix
+ * of it? That is, are we creating a file where they expect a
+ * directory there?
+ */
+ pos = cache_name_pos(path,
+ htons(create_ce_flags(namelen, 0)));
+
+ /* (0 <= pos) cannot happen because add_cache_entry()
+ * should have taken care of that case.
+ */
+ pos = -pos-1;
+
+ /* pos would point at an existing entry that would come immediately
+ * after our path. Does it have our path as a leading path prefix?
+ */
+ if ((pos < active_nr) &&
+ !strncmp(active_cache[pos]->name, path, namelen) &&
+ active_cache[pos]->name[namelen] == '/')
+ return -1;
+
+ return 0;
+}
+
int add_cache_entry(struct cache_entry *ce, int ok_to_add)
{
int pos;
@@ -152,6 +210,9 @@ int add_cache_entry(struct cache_entry *
if (!ok_to_add)
return -1;
+ if (check_file_directory_conflict(ce->name))
+ return -1;
+
/* Make sure the array is big enough .. */
if (active_nr == active_alloc) {
active_alloc = alloc_nr(active_alloc);
next prev parent reply other threads:[~2005-05-08 1:44 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1115408460.32065.37.camel@localhost.localdomain>
[not found] ` <20050506231447.GG32629@pasky.ji.cz>
[not found] ` <1115421933.32065.111.camel@localhost.localdomain>
[not found] ` <20050506233003.GJ32629@pasky.ji.cz>
[not found] ` <1115423450.32065.138.camel@localhost.localdomain>
[not found] ` <20050507001409.GP32629@pasky.ji.cz>
[not found] ` <1115431767.32065.182.camel@localhost.localdomain>
2005-05-07 15:28 ` Broken adding of cache entries Petr Baudis
2005-05-07 18:42 ` Junio C Hamano
2005-05-07 19:22 ` Junio C Hamano
2005-05-07 22:41 ` Petr Baudis
2005-05-08 0:43 ` Junio C Hamano
2005-05-08 1:50 ` Junio C Hamano [this message]
2005-05-08 5:22 ` Junio C Hamano
2005-05-08 16:59 ` Petr Baudis
2005-05-08 21:06 ` Junio C Hamano
2005-05-08 21:22 ` Petr Baudis
2005-05-08 22:18 ` Junio C Hamano
2005-05-08 22:22 ` Junio C Hamano
2005-05-08 22:42 ` Junio C Hamano
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=7vbr7m8p05.fsf@assigned-by-dhcp.cox.net \
--to=junkio@cox.net \
--cc=git@vger.kernel.org \
--cc=kay.sievers@vrfy.org \
--cc=pasky@ucw.cz \
/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