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

[PATCH 13/17] commit: add narrow's commit_tree version

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Sep 5, 2010, 06:47 UTC
Message-ID
<1283669264-15759-14-git-send-email-pclouds@gmail.com>
In-Reply-To
<1283669264-15759-1-git-send-email-pclouds@gmail.com>

As stated somewhere, the index in narrow repo is also narrowed. When a users are done with his changes and about to commit, the new narrow tree created from index will be grafted back to a base toplevel tree (usually from parent commit). The result is a new toplevel tree with user's changes and suitable for commits.

The narrow version uses join_narrow_tree() to recreate a full tree from a base toplevel tree (typically commit parent's tree) and a tree created from index.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Equivalence to Elijah's 07/15 and 08/15. My way generates some throw away
 trees at write_cache_as_tree(), not good.
 commit.c      |   16 +++++++++
 commit.h      |    5 +++
 narrow-tree.c |  101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 narrow-tree.h |    4 ++
 4 files changed, 126 insertions(+), 0 deletions(-)
diff --git a/commit.c b/commit.c
index 0094ec1..c7fe7fc 100644
--- a/commit.c
+++ b/commit.c
@@ -6,6 +6,7 @@
 #include "diff.h"
 #include "revision.h"
 #include "notes.h"
+#include "narrow-tree.h"
 
 int save_commit_buffer = 1;
 
@@ -864,3 +865,18 @@ int commit_tree(const char *msg, unsigned char *tree,
 	strbuf_release(&buffer);
 	return result;
 }
+
+int commit_narrow_tree(const char *msg, unsigned char *tree,
+		       const unsigned char *narrow_base,
+		       struct commit_list *parents, unsigned char *ret,
+		       const char *author)
+{
+	unsigned char sha1[20];
+
+	if (get_narrow_prefix()) {
+		if (join_narrow_tree(sha1, narrow_base, tree, get_narrow_prefix()))
+			die("Failed to join tree");
+		tree = sha1;
+	}
+	return commit_tree(msg, tree, parents, ret, author);
+}
diff --git a/commit.h b/commit.h
index 9113bbe..c718439 100644
--- a/commit.h
+++ b/commit.h
@@ -170,5 +170,10 @@ struct commit_list *reduce_heads(struct commit_list *heads);
 extern int commit_tree(const char *msg, unsigned char *tree,
 		struct commit_list *parents, unsigned char *ret,
 		const char *author);
+extern int commit_narrow_tree(const char *msg, unsigned char *tree,
+			      const unsigned char *narrow_base,
+			      struct commit_list *parents,
+			      unsigned char *ret,
+			      const char *author);
 
 #endif /* COMMIT_H */
diff --git a/narrow-tree.c b/narrow-tree.c
index 85dbab4..110fac2 100644
--- a/narrow-tree.c
+++ b/narrow-tree.c
@@ -1,4 +1,14 @@
 #include "cache.h"
+#include "commit.h"
+#include "tree.h"
+#include "diff.h"
+#include "revision.h"
+#include "refs.h"
+#include "tag.h"
+#include "progress.h"
+#include "pack.h"
+#include "sha1-lookup.h"
+#include "csum-file.h"
 #include "narrow-tree.h"
 
 static const char **narrow_prefix;
@@ -104,3 +114,94 @@ char *get_narrow_string()
 	}
 	return strbuf_detach(&sb, NULL);
 }
+
+/*
+ * The opposite of narrow_tree(). Put the subtree back to the original tree.
+ */
+static int join_narrow_tree_rec(unsigned char *result,
+				const unsigned char *basetree,
+				const unsigned char *newtree,
+				const char **prefix,
+				char *base,
+				int baselen)
+{
+	struct tree_desc desc;
+	struct name_entry entry;
+	struct strbuf buffer;
+	enum object_type type;
+	unsigned long size;
+	const char **p;
+	int len, found;
+	char *buf;
+
+	buf = read_sha1_file(basetree, &type, &size);
+	if (!buf || type != OBJ_TREE)
+		die("Bad tree %s", sha1_to_hex(basetree));
+
+	if (baselen)
+		base[baselen++] = '/';
+
+	init_tree_desc(&desc, buf, size);
+	strbuf_init(&buffer, 8192);
+	while (tree_entry(&desc, &entry)) {
+		strbuf_addf(&buffer, "%o %.*s%c", entry.mode, strlen(entry.path), entry.path, '\0');
+
+		if (!S_ISDIR(entry.mode)) {
+			strbuf_add(&buffer, entry.sha1, 20);
+			continue;
+		}
+
+		p = prefix;
+		len = strlen(entry.path);
+		found = 0;
+
+		while (*p) {
+			if (!strcmp(entry.path, *p)) {
+				found = 2;
+				break;
+			}
+			if (!prefixcmp(*p, entry.path)) {
+				found = 1;
+				break;
+			}
+			p++;
+		}
+		switch (found) {
+		case 1:
+			memcpy(base+baselen, entry.path, len+1);
+			join_narrow_tree_rec(result, entry.sha1, newtree,
+					     prefix, base, baselen+len+1);
+			break;
+		case 2:
+			if (!path_to_tree_sha1(result, newtree, *p))
+				die("Could not find tree %s in the new tree", *p);
+			break;
+		case 0:
+			hashcpy(result, entry.sha1);
+			break;
+		}
+
+		/* FIXME, what if placeholder tree does not exist? */
+
+		strbuf_add(&buffer, result, 20);
+	}
+
+	free(buf);
+	if (write_sha1_file(buffer.buf, buffer.len, tree_type, result)) {
+		base[baselen] = '\0';
+		error("Could not write tree %s", base);
+		strbuf_release(&buffer);
+		return 1;
+	}
+	strbuf_release(&buffer);
+	return 0;
+}
+
+int join_narrow_tree(unsigned char *result,
+		     const unsigned char *basetree,
+		     const unsigned char *newtree,
+		     const char **prefix)
+{
+	char path[PATH_MAX];
+	return join_narrow_tree_rec(result, basetree, newtree, prefix, path, 0);
+}
diff --git a/narrow-tree.h b/narrow-tree.h
index 2097436..e7d84c4 100644
--- a/narrow-tree.h
+++ b/narrow-tree.h
@@ -1,3 +1,7 @@
 extern int valid_narrow_prefix(const char *prefix, const char *prev_prefix, int quiet);
 extern int check_narrow_prefix();
 extern char *get_narrow_string();
+extern int join_narrow_tree(unsigned char *result,
+			    const unsigned char *base,
+			    const unsigned char *newtree,
+			    const char **prefix);
-- 
1.7.1.rc1.69.g24c2f7
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 14 of 25 in “Narrow clone v3 (was subtree clone)”
  1. 00/17 Narrow clone v3 (was subtree clone)Nguyễn Thái Ngọc Duy, Sep 5, 2010
  2. 01/17 rev-list: do not do commit simplification if simplify_history = 0Nguyễn Thái Ngọc Duy, Sep 5, 2010
  3. 02/17 tree.c: add path_to_sha1()Nguyễn Thái Ngọc Duy, Sep 5, 2010
  4. 03/17 Introduce $GIT_DIR/narrowNguyễn Thái Ngọc Duy, Sep 5, 2010
  5. 04/17 index: make narrow index incompatible with older gitNguyễn Thái Ngọc Duy, Sep 5, 2010
  6. 05/17 pack-objects: support narrow packs with pathspecsNguyễn Thái Ngọc Duy, Sep 5, 2010
  7. 06/17 {fetch,upload}-pack: support narrow repositoryNguyễn Thái Ngọc Duy, Sep 5, 2010
  8. 07/17 unpack-trees: split traverse_trees() code into a separate functionNguyễn Thái Ngọc Duy, Sep 5, 2010
  9. 08/17 unpack-trees: support unpack trees in narrow repositoryNguyễn Thái Ngọc Duy, Sep 5, 2010
  10. 09/17 cache-tree: only cache tree within narrow areaNguyễn Thái Ngọc Duy, Sep 5, 2010
  11. 10/17 get_pathspec(): support narrow pathspec rewritingNguyễn Thái Ngọc Duy, Sep 5, 2010
  12. 11/17 pathspec retrieval fixNguyễn Thái Ngọc Duy, Sep 5, 2010
  13. 12/17 clone: support --narrow optionNguyễn Thái Ngọc Duy, Sep 5, 2010
  14. 13/17 commit: add narrow's commit_tree versionNguyễn Thái Ngọc Duy, Sep 5, 2010
  15. 14/17 commit: use commit_narrow_tree() to support narrow repoNguyễn Thái Ngọc Duy, Sep 5, 2010
  16. 15/17 write-tree: requires --narrow-base in narrow repositoryNguyễn Thái Ngọc Duy, Sep 5, 2010
  17. 16/17 merge: try to do local merge if possible in narrow repoNguyễn Thái Ngọc Duy, Sep 5, 2010
  18. 17/17 Add narrow clone demonstration testNguyễn Thái Ngọc Duy, Sep 5, 2010
  19. Sverre RabbelierSep 5, 2010
  20. Nguyen Thai Ngoc DuySep 5, 2010
  21. Elijah NewrenSep 5, 2010
  22. Elijah NewrenSep 6, 2010
  23. Nguyen Thai Ngoc DuySep 6, 2010
  24. Sverre RabbelierSep 6, 2010
  25. Elijah NewrenSep 6, 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.