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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.