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

Re: [PATCH] optionally disable overwriting of ignored files

From
Clemens Buchacher <drizzd@aon.at>
Date
Aug 21, 2010, 13:23 UTC
Message-ID
<20100821132356.GA31998@localhost>
In-Reply-To
<7v4oepaup7.fsf@alter.siamese.dyndns.org>
On Fri, Aug 20, 2010 at 01:35:32PM -0700, Junio C Hamano wrote:
Show 7 quoted lines
>
>     $ echo foo >po
>     $ git checkout pu
> 
> should error out, as "po" is a directory that has tracked contents, and we
> never said the untracked regular file "po" is trashable, but the above
> sequence happily checks the branch out.

Looks like this case is simply overlooked in verify_absent_1(). The following takes the existing lstat_cache() code and deals with the FL_ERR case, which is when there is a file in the way of the leading path.

The patch below fixes the issue and passes the test suite, but it's lacking in various ways and I am probably breaking something in lstat_cache(), which I do not completely understand yet.

So it's going to take some more work to fix this properly.
Clemens
 cache.h        |    1 +
 symlinks.c     |   20 ++++++++++++++++++--
 unpack-trees.c |   25 ++++++++++++++++++++++++-
 3 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/cache.h b/cache.h
index dd1b8f7..5a8a99d 100644
--- a/cache.h
+++ b/cache.h
@@ -850,6 +850,7 @@ struct cache_def {
 extern int has_symlink_leading_path(const char *name, int len);
 extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
 extern int has_symlink_or_noent_leading_path(const char *name, int len);
+extern int find_leading_path(const char *name, int len, const char **path, int *path_len);
 extern int has_dirs_only_path(const char *name, int len, int prefix_len);
 extern void schedule_dir_for_removal(const char *name, int len);
 extern void remove_scheduled_dirs(void);
diff --git a/symlinks.c b/symlinks.c
index 8860120..3f78168 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -152,7 +152,7 @@ static int lstat_cache(struct cache_def *cache, const char *name, int len,
 	 * path types, FL_NOENT, FL_SYMLINK and FL_DIR, can be cached
 	 * for the moment!
 	 */
-	save_flags = ret_flags & track_flags & (FL_NOENT|FL_SYMLINK);
+	save_flags = ret_flags & track_flags & (FL_NOENT|FL_SYMLINK|FL_ERR);
 	if (save_flags && last_slash > 0 && last_slash <= PATH_MAX) {
 		cache->path[last_slash] = '\0';
 		cache->len = last_slash;
@@ -199,7 +199,7 @@ int has_symlink_leading_path(const char *name, int len)
 
 /*
  * Return non-zero if path 'name' has a leading symlink component or
- * if some leading path component does not exists.
+ * if some leading path component does not exist.
  */
 int has_symlink_or_noent_leading_path(const char *name, int len)
 {
@@ -210,6 +210,22 @@ int has_symlink_or_noent_leading_path(const char *name, int len)
 }
 
 /*
+ * Stat for leading path.
+ */
+int find_leading_path(const char *name, int len, const char **path, int *path_len)
+{
+	struct cache_def *cache = &default_cache;	/* FIXME */
+	int flags = lstat_cache(cache, name, len,
+			   FL_SYMLINK|FL_NOENT|FL_DIR|FL_ERR, USE_ONLY_LSTAT);
+	*path = cache->path;
+	*path_len = cache->len;
+	if (flags & FL_ERR)
+		return -1;
+	else
+		return flags & (FL_SYMLINK|FL_NOENT);
+}
+
+/*
  * Return non-zero if all path components of 'name' exists as a
  * directory.  If prefix_len > 0, we will test with the stat()
  * function instead of the lstat() function for a prefix length of
diff --git a/unpack-trees.c b/unpack-trees.c
index 8cf0da3..250ed7c 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1016,12 +1016,35 @@ static int verify_absent_1(struct cache_entry *ce, const char *action,
 				 const char *error_msg)
 {
 	struct stat st;
+	const char *path;
+	int path_len;
+	int ret;
 
 	if (o->index_only || o->reset || !o->update)
 		return 0;
 
-	if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce)))
+	ret = find_leading_path(ce->name, ce_namelen(ce), &path, &path_len);
+	if (ret > 0)
 		return 0;
+	else if (ret < 0) {
+		struct cache_entry *result;
+
+		/* FIXME: respect ignores etc. as below */
+
+		/*
+		 * The previous round may already have decided to
+		 * delete this path, which is in a subdirectory that
+		 * is being replaced with a blob.
+		 */
+		result = index_name_exists(&o->result, path, path_len, 0);
+		if (result) {
+			if (result->ce_flags & CE_REMOVE)
+				return 0;
+		}
+
+		return o->gently ? -1 :
+			error(ERRORMSG(o, would_lose_untracked), path, action);
+	}
 
 	if (!lstat(ce->name, &st)) {
 		int dtype = ce_to_dtype(ce);
-- 
1.7.2.1.1.g202c
Previous: Kevin BallardNext: Clemens Buchacher
Message 12 of 39 in “git merge, .gitignore, and silently overwriting untracked files”
  1. Joshua JensenAug 17, 2010
  2. Junio C HamanoAug 17, 2010
  3. optionally disable overwriting of ignored filesClemens Buchacher, Aug 18, 2010
  4. Jakub NarebskiAug 19, 2010
  5. Clemens BuchacherAug 20, 2010
  6. Joshua JensenAug 20, 2010
  7. Junio C HamanoAug 20, 2010
  8. Clemens BuchacherAug 21, 2010
  9. Junio C HamanoAug 22, 2010
  10. Clemens BuchacherAug 22, 2010
  11. Kevin BallardOct 9, 2010
  12. Clemens BuchacherAug 21, 2010
  13. 0/5 do not overwrite untracked files in leading pathClemens Buchacher, Oct 9, 2010
  14. 1/5 t7607: use test_commit and test_must_failClemens Buchacher, Oct 9, 2010
  15. Jonathan NiederOct 10, 2010
  16. 1/5 t7607: use test-lib functions and check MERGE_HEADClemens Buchacher, Oct 10, 2010
  17. Junio C HamanoOct 13, 2010
  18. Junio C HamanoOct 13, 2010
  19. 2/5 t7607: add leading-path testsClemens Buchacher, Oct 9, 2010
  20. Johannes SixtOct 9, 2010
  21. 2/5 t7607: add leading-path testsClemens Buchacher, Oct 10, 2010
  22. 3/5 add function check_ok_to_remove()Clemens Buchacher, Oct 9, 2010
  23. Junio C HamanoOct 13, 2010
  24. 4/5 lstat_cache: optionally return match_lenClemens Buchacher, Oct 9, 2010
  25. 5/5 do not overwrite files in leading pathClemens Buchacher, Oct 9, 2010
  26. Junio C HamanoOct 13, 2010
  27. Clemens BuchacherOct 13, 2010
  28. Clemens BuchacherOct 15, 2010
  29. Junio C HamanoOct 15, 2010
  30. Junio C HamanoAug 20, 2010
  31. optionally disable overwriting of ignored filesClemens Buchacher, Aug 21, 2010
  32. Matthieu MoyAug 23, 2010
  33. Heiko VoigtAug 31, 2010
  34. Matthieu MoyAug 23, 2010
  35. Holger HellmuthAug 23, 2010
  36. Clemens BuchacherAug 23, 2010
  37. Junio C HamanoAug 23, 2010
  38. Clemens BuchacherAug 24, 2010
  39. Junio C HamanoAug 24, 2010

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.