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

[PATCH 6/6] Teach core object handling functions about gitlinks

From
Linus Torvalds <torvalds@linux-foundation.org>
Date
Apr 10, 2007, 04:20 UTC
Message-ID
<Pine.LNX.4.64.0704092115350.6730@woody.linux-foundation.org>
In-Reply-To
<Pine.LNX.4.64.0704092100110.6730@woody.linux-foundation.org>

This teaches the really fundamental core SHA1 object handling routines about gitlinks. We can compare trees with gitlinks in them (although we can not actually generate patches for them yet - just raw git diffs), and they show up as commits in "git ls-tree".

We also know to compare gitlinks as if they were directories (ie the normal "sort as trees" rules apply).

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
Ok, that's it for now.

NOTE NOTE NOTE! I'd like to note once more that this doesn't actually get you working subproject support. Not only do I need to connect up a few more low-level helper functions (things like "git diff" don't know how to generate even rudimentary "subproject X changed" patches, nor can you actually yet *add* subprojects), but quite apart from that low-level stuff, anything more high-level (like "git fetch" and friends) will need to know about subprojects.

In general, think of this like the early git plumbing: it's the early "content-addressable filesystem" part. The actual SCM parts going on top of it are yet to be done.

I'm hoping/expecting that there are more people who have the ability and the interest to work on the higher-level interfaces once the core plumbing support is there. There's still some plumbing to be done, but after that, maybe more people (and maybe the SoC people) can start filling out the higher-level details..

Comments on the patches/approach so far?
 builtin-ls-tree.c |   20 +++++++++++++++++++-
 cache-tree.c      |    2 +-
 read-cache.c      |   35 +++++++++++++++++++++++++++++++----
 sha1_file.c       |    3 +++
 4 files changed, 54 insertions(+), 6 deletions(-)
diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c
index 6472610..1cb4dca 100644
--- a/builtin-ls-tree.c
+++ b/builtin-ls-tree.c
@@ -6,6 +6,7 @@
 #include "cache.h"
 #include "blob.h"
 #include "tree.h"
+#include "commit.h"
 #include "quote.h"
 #include "builtin.h"
 
@@ -59,7 +60,24 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
 	int retval = 0;
 	const char *type = blob_type;
 
-	if (S_ISDIR(mode)) {
+	if (S_ISDIRLNK(mode)) {
+		/*
+		 * Maybe we want to have some recursive version here?
+		 *
+		 * Something like:
+		 *
+		if (show_subprojects(base, baselen, pathname)) {
+			if (fork()) {
+				chdir(base);
+				exec ls-tree;
+			}
+			waitpid();
+		}
+		 *
+		 * ..or similar..
+		 */
+		type = commit_type;
+	} else if (S_ISDIR(mode)) {
 		if (show_recursive(base, baselen, pathname)) {
 			retval = READ_TREE_RECURSIVE;
 			if (!(ls_options & LS_SHOW_TREES))
diff --git a/cache-tree.c b/cache-tree.c
index 9b73c86..6369cc7 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -326,7 +326,7 @@ static int update_one(struct cache_tree *it,
 			mode = ntohl(ce->ce_mode);
 			entlen = pathlen - baselen;
 		}
-		if (!missing_ok && !has_sha1_file(sha1))
+		if (mode != S_IFDIRLNK && !missing_ok && !has_sha1_file(sha1))
 			return error("invalid object %s", sha1_to_hex(sha1));
 
 		if (!ce->ce_mode)
diff --git a/read-cache.c b/read-cache.c
index 54573ce..8fe94cd 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -5,6 +5,7 @@
  */
 #include "cache.h"
 #include "cache-tree.h"
+#include "refs.h"
 
 /* Index extensions.
  *
@@ -91,6 +92,23 @@ static int ce_compare_link(struct cache_entry *ce, size_t expected_size)
 	return match;
 }
 
+static int ce_compare_gitlink(struct cache_entry *ce)
+{
+	unsigned char sha1[20];
+
+	/*
+	 * We don't actually require that the .git directory
+	 * under DIRLNK directory be a valid git directory. It
+	 * might even be missing (in case nobody populated that
+	 * sub-project).
+	 *
+	 * If so, we consider it always to match.
+	 */
+	if (resolve_gitlink_ref(ce->name, "HEAD", sha1) < 0)
+		return 0;
+	return hashcmp(sha1, ce->sha1);
+}
+
 static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
 {
 	switch (st->st_mode & S_IFMT) {
@@ -102,6 +120,9 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
 		if (ce_compare_link(ce, xsize_t(st->st_size)))
 			return DATA_CHANGED;
 		break;
+	case S_IFDIRLNK:
+		/* No need to do anything, we did the exact compare in "match_stat_basic" */
+		break;
 	default:
 		return TYPE_CHANGED;
 	}
@@ -127,6 +148,12 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
 		    (has_symlinks || !S_ISREG(st->st_mode)))
 			changed |= TYPE_CHANGED;
 		break;
+	case S_IFDIRLNK:
+		if (!S_ISDIR(st->st_mode))
+			changed |= TYPE_CHANGED;
+		else if (ce_compare_gitlink(ce))
+			changed |= DATA_CHANGED;
+		break;
 	default:
 		die("internal error: ce_mode is %o", ntohl(ce->ce_mode));
 	}
@@ -250,9 +277,9 @@ int base_name_compare(const char *name1, int len1, int mode1,
 		return cmp;
 	c1 = name1[len];
 	c2 = name2[len];
-	if (!c1 && S_ISDIR(mode1))
+	if (!c1 && (S_ISDIR(mode1) || S_ISDIRLNK(mode1)))
 		c1 = '/';
-	if (!c2 && S_ISDIR(mode2))
+	if (!c2 && (S_ISDIR(mode2) || S_ISDIRLNK(mode1)))
 		c2 = '/';
 	return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
 }
@@ -334,8 +361,8 @@ int add_file_to_cache(const char *path, int verbose)
 	if (lstat(path, &st))
 		die("%s: unable to stat (%s)", path, strerror(errno));
 
-	if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
-		die("%s: can only add regular files or symbolic links", path);
+	if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
+		die("%s: can only add regular files, symbolic links or git-directories", path);
 
 	namelen = strlen(path);
 	size = cache_entry_size(namelen);
diff --git a/sha1_file.c b/sha1_file.c
index 4304fe9..ab915fa 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -13,6 +13,7 @@
 #include "commit.h"
 #include "tag.h"
 #include "tree.h"
+#include "refs.h"
 
 #ifndef O_NOATIME
 #if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
@@ -2332,6 +2333,8 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write
 				     path);
 		free(target);
 		break;
+	case S_IFDIR:
+		return resolve_gitlink_ref(path, "HEAD", sha1);
 	default:
 		return error("%s: unsupported file type", path);
 	}
-- 
1.5.1.110.g1e4c
Previous: Dana HowNext: Frank Lichtenheld
Message 37 of 98 in “Initial subproject support (RFC?)”
  1. 0/6 Initial subproject support (RFC?)Linus Torvalds, Apr 10, 2007
  2. 1/6 diff-lib: use ce_mode_from_stat() rather than messing with modes manuallyLinus Torvalds, Apr 10, 2007
  3. 2/6 Avoid overflowing name buffer in deep directory structuresLinus Torvalds, Apr 10, 2007
  4. 3/6 Add 'resolve_gitlink_ref()' helper functionLinus Torvalds, Apr 10, 2007
  5. Alex RiesenApr 10, 2007
  6. Linus TorvaldsApr 10, 2007
  7. Alex RiesenApr 10, 2007
  8. Linus TorvaldsApr 10, 2007
  9. Alex RiesenApr 10, 2007
  10. Linus TorvaldsApr 10, 2007
  11. Josef WeidendorferApr 10, 2007
  12. 4/6 Add "S_IFDIRLNK" file mode infrastructure for git linksLinus Torvalds, Apr 10, 2007
  13. 5/6 Teach "fsck" not to follow subproject linksLinus Torvalds, Apr 10, 2007
  14. Sam VilainApr 11, 2007
  15. Linus TorvaldsApr 11, 2007
  16. Sam VilainApr 11, 2007
  17. Linus TorvaldsApr 11, 2007
  18. David LangApr 11, 2007
  19. Linus TorvaldsApr 11, 2007
  20. David LangApr 11, 2007
  21. Linus TorvaldsApr 12, 2007
  22. Junio C HamanoApr 12, 2007
  23. David LangApr 12, 2007
  24. Dana HowApr 12, 2007
  25. Linus TorvaldsApr 12, 2007
  26. Rogan DawesApr 13, 2007
  27. Linus TorvaldsApr 13, 2007
  28. Dana HowApr 15, 2007
  29. Dana HowApr 12, 2007
  30. Sam VilainApr 12, 2007
  31. Junio C HamanoApr 12, 2007
  32. Linus TorvaldsApr 12, 2007
  33. Junio C HamanoApr 12, 2007
  34. Junio C HamanoApr 12, 2007
  35. Linus TorvaldsApr 12, 2007
  36. Dana HowApr 11, 2007
  37. 6/6 Teach core object handling functions about gitlinksLinus Torvalds, Apr 10, 2007
  38. Frank LichtenheldApr 10, 2007
  39. Alex RiesenApr 10, 2007
  40. Linus TorvaldsApr 10, 2007
  41. Josef WeidendorferApr 10, 2007
  42. Alex RiesenApr 10, 2007
  43. Josef WeidendorferApr 10, 2007
  44. Linus TorvaldsApr 10, 2007
  45. Andy ParkinsApr 10, 2007
  46. Linus TorvaldsApr 10, 2007
  47. Junio C HamanoApr 10, 2007
  48. Linus TorvaldsApr 10, 2007
  49. Sam VilainApr 12, 2007
  50. Martin WaitzApr 12, 2007
  51. Linus TorvaldsApr 12, 2007
  52. Sam VilainApr 12, 2007
  53. David LangApr 10, 2007
  54. Junio C HamanoApr 10, 2007
  55. Josef WeidendorferApr 10, 2007
  56. Linus TorvaldsApr 10, 2007
  57. Sam VilainApr 11, 2007
  58. Linus TorvaldsApr 12, 2007
  59. Torgil SvenssonApr 12, 2007
  60. Martin WaitzApr 12, 2007
  61. Torgil SvenssonApr 12, 2007
  62. Sam VilainApr 11, 2007
  63. Martin WaitzApr 11, 2007
  64. Alex RiesenApr 11, 2007
  65. Martin WaitzApr 11, 2007
  66. Alex RiesenApr 11, 2007
  67. Martin WaitzApr 11, 2007
  68. Junio C HamanoApr 11, 2007
  69. Martin WaitzApr 11, 2007
  70. Junio C HamanoApr 11, 2007
  71. Martin WaitzApr 11, 2007
  72. Linus TorvaldsApr 11, 2007
  73. Andy ParkinsApr 11, 2007
  74. Martin WaitzApr 11, 2007
  75. Linus TorvaldsApr 11, 2007
  76. Sam VilainApr 11, 2007
  77. Martin WaitzApr 11, 2007
  78. Brian GernhardtApr 12, 2007
  79. Josef WeidendorferApr 12, 2007
  80. Linus TorvaldsApr 10, 2007
  81. Alex RiesenApr 10, 2007
  82. Linus TorvaldsApr 10, 2007
  83. Alex RiesenApr 10, 2007
  84. Linus TorvaldsApr 10, 2007
  85. Alex RiesenApr 10, 2007
  86. Junio C HamanoApr 10, 2007
  87. Linus TorvaldsApr 10, 2007
  88. Junio C HamanoApr 10, 2007
  89. Sam RavnborgApr 10, 2007
  90. Junio C HamanoApr 10, 2007
  91. Nicolas PitreApr 10, 2007
  92. J. Bruce FieldsApr 15, 2007
  93. David KågedalApr 11, 2007
  94. Junio C HamanoApr 11, 2007
  95. J. Bruce FieldsApr 15, 2007
  96. Martin WaitzApr 11, 2007
  97. Alex RiesenApr 11, 2007
  98. Martin WaitzApr 11, 2007

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.