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

[PATCH 4/4] fast-import: allow moving the root tree

From
John Keeping <john@keeping.me.uk>
Date
Jun 23, 2013, 14:58 UTC
Message-ID
<08c4486c228eff5754b95708d8f5d56e95620278.1371999369.git.john@keeping.me.uk>
In-Reply-To
<cover.1371999369.git.john@keeping.me.uk>

Because fast-import.c::tree_content_remove does not check for the empty path, it is not possible to move the root tree to a subdirectory. Instead the error "Path not in branch" is produced (note the double space where the empty path has been inserted).

Fix this by explicitly checking for the empty path and handling it.
Signed-off-by: John Keeping <john@keeping.me.uk>
---
 fast-import.c          | 21 ++++++++++++++-------
 t/t9300-fast-import.sh |  2 +-
 2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index e2c9d50..21db3fc 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1568,7 +1568,8 @@ static int tree_content_set(
 static int tree_content_remove(
 	struct tree_entry *root,
 	const char *p,
-	struct tree_entry *backup_leaf)
+	struct tree_entry *backup_leaf,
+	int allow_root)
 {
 	struct tree_content *t;
 	const char *slash1;
@@ -1583,6 +1584,12 @@ static int tree_content_remove(
 
 	if (!root->tree)
 		load_tree(root);
+
+	if (!*p && allow_root) {
+		e = root;
+		goto del_entry;
+	}
+
 	t = root->tree;
 	for (i = 0; i < t->entry_count; i++) {
 		e = t->entries[i];
@@ -1599,7 +1606,7 @@ static int tree_content_remove(
 				goto del_entry;
 			if (!e->tree)
 				load_tree(e);
-			if (tree_content_remove(e, slash1 + 1, backup_leaf)) {
+			if (tree_content_remove(e, slash1 + 1, backup_leaf, 0)) {
 				for (n = 0; n < e->tree->entry_count; n++) {
 					if (e->tree->entries[n]->versions[1].mode) {
 						hashclr(root->versions[1].sha1);
@@ -2188,7 +2195,7 @@ static uintmax_t do_change_note_fanout(
 			}
 
 			/* Rename fullpath to realpath */
-			if (!tree_content_remove(orig_root, fullpath, &leaf))
+			if (!tree_content_remove(orig_root, fullpath, &leaf, 0))
 				die("Failed to remove path %s", fullpath);
 			tree_content_set(orig_root, realpath,
 				leaf.versions[1].sha1,
@@ -2323,7 +2330,7 @@ static void file_change_m(struct branch *b)
 
 	/* Git does not track empty, non-toplevel directories. */
 	if (S_ISDIR(mode) && !memcmp(sha1, EMPTY_TREE_SHA1_BIN, 20) && *p) {
-		tree_content_remove(&b->branch_tree, p, NULL);
+		tree_content_remove(&b->branch_tree, p, NULL, 0);
 		return;
 	}
 
@@ -2384,7 +2391,7 @@ static void file_change_d(struct branch *b)
 			die("Garbage after path in: %s", command_buf.buf);
 		p = uq.buf;
 	}
-	tree_content_remove(&b->branch_tree, p, NULL);
+	tree_content_remove(&b->branch_tree, p, NULL, 1);
 }
 
 static void file_change_cr(struct branch *b, int rename)
@@ -2422,7 +2429,7 @@ static void file_change_cr(struct branch *b, int rename)
 
 	memset(&leaf, 0, sizeof(leaf));
 	if (rename)
-		tree_content_remove(&b->branch_tree, s, &leaf);
+		tree_content_remove(&b->branch_tree, s, &leaf, 1);
 	else
 		tree_content_get(&b->branch_tree, s, &leaf, 1);
 	if (!leaf.versions[1].mode)
@@ -2530,7 +2537,7 @@ static void note_change_n(struct branch *b, unsigned char *old_fanout)
 	}
 
 	construct_path_with_fanout(sha1_to_hex(commit_sha1), *old_fanout, path);
-	if (tree_content_remove(&b->branch_tree, path, NULL))
+	if (tree_content_remove(&b->branch_tree, path, NULL, 0))
 		b->num_notes--;
 
 	if (is_null_sha1(sha1))
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 04385a7..31a770d 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1050,7 +1050,7 @@ cat >expect <<EOF
 :100755 100755 e74b7d465e52746be2b4bae983670711e6e66657 e74b7d465e52746be2b4bae983670711e6e66657 R100	newdir/exec.sh	sub/newdir/exec.sh
 :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100	newdir/interesting	sub/newdir/interesting
 EOF
-test_expect_failure \
+test_expect_success \
 	'M: rename root to subdirectory' \
 	'git fast-import <input &&
 	 git diff-tree -M -r M4^ M4 >actual &&
-- 
1.8.3.1.676.gaae6535
Previous: John KeepingNext: Junio C Hamano
Message 5 of 6 in “fast-import: handle empty paths better”
  1. 0/4 fast-import: handle empty paths betterJohn Keeping, Jun 23, 2013
  2. 1/4 t9300: document fast-import empty path issuesJohn Keeping, Jun 23, 2013
  3. 2/4 fast-import: set valid mode on root tree in "ls"John Keeping, Jun 23, 2013
  4. 3/4 fast-import: allow ls or filecopy of the root treeJohn Keeping, Jun 23, 2013
  5. 4/4 fast-import: allow moving the root treeJohn Keeping, Jun 23, 2013
  6. Junio C HamanoJul 1, 2013

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.