git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: "make quick-install-man" broke recently

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 17, 2009, 06:53 UTC
Message-ID
<7vhbw72ap3.fsf@alter.siamese.dyndns.org>
In-Reply-To
<8c9a060908162258ua50e34ah53c1ada9dbcd4aa0@mail.gmail.com>
Jacob Helwig <jacob.helwig@gmail.com> writes:
> I was able to reproduce this one one of the machines I have access to,
> and bisecting shows that it was introduced by b6986d8 (git-checkout: be
> careful about untracked symlinks).
Ahh..

-- >8 -- check_path(): allow symlinked directories to checkout-index --prefix

Merlyn noticed that Documentation/install-doc-quick.sh no longer correctly removes old installed documents when the target directory has a leading path that is a symlink. It turns out that "checkout-index --prefix" was broken by recent b6986d8 (git-checkout: be careful about untracked symlinks, 2009-07-29).

I suspect has_symlink_leading_path() could learn the third parameter (prefix that is allowed to be symlinked directories) to allow us to retire a similar function has_dirs_only_path().

Another avenue of fixing this I considered was to get rid of base_dir and base_dir_len from "struct checkout", and instead make "git checkout-index" when run with --prefix mkdir the leading path and chdir in there. It might be the best longer term solution to this issue, as the base_dir feature is used only by that rather obscure codepath as far as I know.

But at least this patch should fix this breakage.
SIgned-off-by: Junio C Hamano <gitster@pobox.com>
---
 cache.h                         |    3 ---
 entry.c                         |   15 ++++++++++++---
 t/t2000-checkout-cache-clash.sh |    9 +++++++++
 3 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/cache.h b/cache.h
index 9222774..e6c7f33 100644
--- a/cache.h
+++ b/cache.h
@@ -468,9 +468,6 @@ extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_obje
 extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
 extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
 
-/* "careful lstat()" */
-extern int check_path(const char *path, int len, struct stat *st);
-
 #define REFRESH_REALLY		0x0001	/* ignore_valid */
 #define REFRESH_UNMERGED	0x0002	/* allow unmerged */
 #define REFRESH_QUIET		0x0004	/* be quiet about it */
diff --git a/entry.c b/entry.c
index f276cf3..6813f8a 100644
--- a/entry.c
+++ b/entry.c
@@ -179,9 +179,18 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
  * This is like 'lstat()', except it refuses to follow symlinks
  * in the path.
  */
-int check_path(const char *path, int len, struct stat *st)
+static int check_path(const char *path, int len, struct stat *st,
+		      const struct checkout *co)
 {
-	if (has_symlink_leading_path(path, len)) {
+	if (co->base_dir_len) {
+		const char *slash = path + len;
+		while (path < slash && *slash != '/')
+			slash--;
+		if (!has_dirs_only_path(path, slash-path, co->base_dir_len)) {
+			errno = ENOENT;
+			return -1;
+		}
+	} else if (has_symlink_leading_path(path, len)) {
 		errno = ENOENT;
 		return -1;
 	}
@@ -201,7 +210,7 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t
 	strcpy(path + len, ce->name);
 	len += ce_namelen(ce);
 
-	if (!check_path(path, len, &st)) {
+	if (!check_path(path, len, &st, state)) {
 		unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID);
 		if (!changed)
 			return 0;
diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh
index f7e1a73..3edade0 100755
--- a/t/t2000-checkout-cache-clash.sh
+++ b/t/t2000-checkout-cache-clash.sh
@@ -48,4 +48,13 @@ test_expect_success \
     'git checkout-index conflicting paths.' \
     'test -f path0 && test -d path1 && test -f path1/file1'
 
+test_expect_success 'checkout-index -f twice with --prefix' '
+	mkdir -p tar/get &&
+	ln -s tar/get there &&
+	echo first &&
+	git checkout-index -a -f --prefix=there/ &&
+	echo second &&
+	git checkout-index -a -f --prefix=there/
+'
+
 test_done
Previous: Randal L. SchwartzNext: Johannes Sixt
Message 7 of 13 in “"make quick-install-man" broke recently”
  1. Randal L. SchwartzAug 17, 2009
  2. Junio C HamanoAug 17, 2009
  3. Randal L. SchwartzAug 17, 2009
  4. Junio C HamanoAug 17, 2009
  5. Jacob HelwigAug 17, 2009
  6. Randal L. SchwartzAug 17, 2009
  7. Junio C HamanoAug 17, 2009
  8. Johannes SixtAug 17, 2009
  9. Junio C HamanoAug 17, 2009
  10. Randal L. SchwartzAug 17, 2009
  11. Junio C HamanoAug 17, 2009
  12. Linus TorvaldsAug 17, 2009
  13. Junio C HamanoAug 17, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.