If a .git file contains

gitsuper: <path>
gitdir: <id>

then we set GIT_SUPER_DIR to <path> and GIT_DIR to
$GIT_SUPER_DIR/repos/<id>.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 cache.h |  1 +
 setup.c | 41 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/cache.h b/cache.h
index 823582f..f85ee70 100644
--- a/cache.h
+++ b/cache.h
@@ -410,6 +410,7 @@ extern const char *get_git_namespace(void);
 extern const char *strip_namespace(const char *namespaced_ref);
 extern const char *get_git_work_tree(void);
 extern const char *read_gitfile(const char *path);
+extern const char *read_gitfile_super(const char *path, char **super);
 extern const char *resolve_gitdir(const char *suspect);
 extern void set_git_work_tree(const char *tree);
 
diff --git a/setup.c b/setup.c
index c040981..e9f0ef6 100644
--- a/setup.c
+++ b/setup.c
@@ -299,14 +299,20 @@ static char *path_from_gitfile(const char *path, const 
char *buf, int len)
 /*
  * Try to read the location of the git directory from the .git file,
  * return path to git directory if found.
+ *
+ * If "gitsuper: " line is found and super is not NULL, *super points
+ * to the absolute path of the given path. The next line contains the
+ * repo id.
  */
-const char *read_gitfile(const char *path)
+const char *read_gitfile_super(const char *path, char **super)
 {
        char *buf, *dir;
        struct stat st;
        int fd;
        ssize_t len;
 
+       if (super)
+               *super = NULL;
        if (stat(path, &st))
                return NULL;
        if (!S_ISREG(st.st_mode))
@@ -323,9 +329,30 @@ const char *read_gitfile(const char *path)
                len--;
        buf[len] = '\0';
 
-       if (prefixcmp(buf, "gitdir: "))
-               die("Invalid gitfile format: %s", path);
-       dir = path_from_gitfile(path, buf + 8, len - 8);
+       if (super && !prefixcmp(buf, "gitsuper: ")) {
+               char *p = buf, *end = buf + len;
+               while (p < end && *p != '\n' && *p != '\r')
+                       p++;
+               if (p == end)
+                       die("Invalid gitfile format: %s", path);
+               *super = buf + strlen("gitsuper: ");
+               *p = '\0';
+               *super = path_from_gitfile(path, *super, p - *super);
+               p++;
+               while (p < end && (*p == '\n' || *p == '\r'))
+                       p++;
+               if (prefixcmp(p, "gitdir: "))
+                       die("Invalid gitfile format: %s", path);
+               p += 8;
+               if (p == end)
+                       die("Invalid gitfile format: %s", path);
+               dir = xmalloc(strlen(*super) + strlen("/repos/") + (end - p) + 
1);
+               sprintf(dir, "%s/repos/%s", *super, p);
+       } else {
+               if (prefixcmp(buf, "gitdir: "))
+                       die("Invalid gitfile format: %s", path);
+               dir = path_from_gitfile(path, buf + 8, len - 8);
+       }
 
        if (!is_git_directory(dir))
                die("Not a git repository: %s", dir);
@@ -336,6 +363,12 @@ const char *read_gitfile(const char *path)
        return path;
 }
 
+const char *read_gitfile(const char *path)
+{
+       return read_gitfile_super(path, NULL);
+}
+
+
 static const char *setup_explicit_git_dir(const char *gitdirenv,
                                          char *cwd, int len,
                                          int *nongit_ok)
-- 
1.8.5.1.77.g42c48fa

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to