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 | 40 +++++++++++++++++++++++++++++++++-------
 2 files changed, 34 insertions(+), 7 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 5432a31..84362a6 100644
--- a/setup.c
+++ b/setup.c
@@ -281,16 +281,23 @@ static int check_repository_format_gently(const char 
*gitdir, int *nongit_ok)
 /*
  * 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;
+       struct strbuf sb = STRBUF_INIT;
+       char *buf, *to_free;
        char *dir;
        const char *slash;
        struct stat st;
        int fd;
        ssize_t len;
 
+       if (super)
+               *super = NULL;
        if (stat(path, &st))
                return NULL;
        if (!S_ISREG(st.st_mode))
@@ -298,12 +305,19 @@ const char *read_gitfile(const char *path)
        fd = open(path, O_RDONLY);
        if (fd < 0)
                die_errno("Error opening '%s'", path);
-       buf = xmalloc(st.st_size + 1);
+       to_free = buf = xmalloc(st.st_size + 1);
        len = read_in_full(fd, buf, st.st_size);
        close(fd);
        if (len != st.st_size)
                die("Error reading %s", path);
        buf[len] = '\0';
+       if (super &&!prefixcmp(buf, "gitsuper: ")) {
+               char *p = strchr(buf, '\n');
+               *super = buf + strlen("gitsuper: ");
+               *p = '\0';
+               len -= (p + 1) - buf;
+               buf = p + 1;
+       }
        if (prefixcmp(buf, "gitdir: "))
                die("Invalid gitfile format: %s", path);
        while (buf[len - 1] == '\n' || buf[len - 1] == '\r')
@@ -312,6 +326,11 @@ const char *read_gitfile(const char *path)
                die("No path in gitfile: %s", path);
        buf[len] = '\0';
        dir = buf + 8;
+       if (super && *super) {
+               strbuf_addf(&sb, "%s/repos/%s", *super, dir);
+               dir = sb.buf;
+               *super = xstrdup(real_path(*super));
+       }
 
        if (!is_absolute_path(dir) && (slash = strrchr(path, '/'))) {
                size_t pathlen = slash+1 - path;
@@ -320,18 +339,25 @@ const char *read_gitfile(const char *path)
                strncpy(dir, path, pathlen);
                strncpy(dir + pathlen, buf + 8, len - 8);
                dir[dirlen] = '\0';
-               free(buf);
-               buf = dir;
+               free(to_free);
+               to_free = buf = dir;
        }
 
-       if (!is_git_directory(dir))
+       if (!is_git_directory_super(dir, super ? *super : dir))
                die("Not a git repository: %s", dir);
        path = real_path(dir);
 
-       free(buf);
+       free(to_free);
+       strbuf_release(&sb);
        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