From 4ef9caf5431dbbd23f240a25b69a989aeb9840a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:26 +0700 Subject: path.c: make get_pathname() return strbuf instead of static buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We've been avoiding PATH_MAX whenever possible. This patch makes get_pathname() return a strbuf and updates the callers to take advantage of this. The code is simplified as we no longer need to worry about buffer overflow. vsnpath() behavior is changed slightly: previously it always clears the buffer before writing, now it just appends. Fortunately this is a static function and all of its callers prepare the buffer properly: git_path() gets the buffer from get_pathname() which resets the buffer, the remaining call sites start with STRBUF_INIT'd buffer. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 120 ++++++++++++++++++++++++++++------------------------------------- 1 file changed, 51 insertions(+), 69 deletions(-) (limited to 'path.c') diff --git a/path.c b/path.c index f68df0cf88..015c0e4b39 100644 --- a/path.c +++ b/path.c @@ -16,11 +16,15 @@ static int get_st_mode_bits(const char *path, int *mode) static char bad_path[] = "/bad-path/"; -static char *get_pathname(void) +static struct strbuf *get_pathname(void) { - static char pathname_array[4][PATH_MAX]; + static struct strbuf pathname_array[4] = { + STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT + }; static int index; - return pathname_array[3 & ++index]; + struct strbuf *sb = &pathname_array[3 & ++index]; + strbuf_reset(sb); + return sb; } static char *cleanup_path(char *path) @@ -34,6 +38,13 @@ static char *cleanup_path(char *path) return path; } +static void strbuf_cleanup_path(struct strbuf *sb) +{ + char *path = cleanup_path(sb->buf); + if (path > sb->buf) + strbuf_remove(sb, 0, path - sb->buf); +} + char *mksnpath(char *buf, size_t n, const char *fmt, ...) { va_list args; @@ -49,85 +60,70 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...) return cleanup_path(buf); } -static char *vsnpath(char *buf, size_t n, const char *fmt, va_list args) +static void vsnpath(struct strbuf *buf, const char *fmt, va_list args) { const char *git_dir = get_git_dir(); - size_t len; - - len = strlen(git_dir); - if (n < len + 1) - goto bad; - memcpy(buf, git_dir, len); - if (len && !is_dir_sep(git_dir[len-1])) - buf[len++] = '/'; - len += vsnprintf(buf + len, n - len, fmt, args); - if (len >= n) - goto bad; - return cleanup_path(buf); -bad: - strlcpy(buf, bad_path, n); - return buf; + strbuf_addstr(buf, git_dir); + if (buf->len && !is_dir_sep(buf->buf[buf->len - 1])) + strbuf_addch(buf, '/'); + strbuf_vaddf(buf, fmt, args); + strbuf_cleanup_path(buf); } char *git_snpath(char *buf, size_t n, const char *fmt, ...) { - char *ret; + struct strbuf sb = STRBUF_INIT; va_list args; va_start(args, fmt); - ret = vsnpath(buf, n, fmt, args); + vsnpath(&sb, fmt, args); va_end(args); - return ret; + if (sb.len >= n) + strlcpy(buf, bad_path, n); + else + memcpy(buf, sb.buf, sb.len + 1); + strbuf_release(&sb); + return buf; } char *git_pathdup(const char *fmt, ...) { - char path[PATH_MAX], *ret; + struct strbuf path = STRBUF_INIT; va_list args; va_start(args, fmt); - ret = vsnpath(path, sizeof(path), fmt, args); + vsnpath(&path, fmt, args); va_end(args); - return xstrdup(ret); + return strbuf_detach(&path, NULL); } char *mkpathdup(const char *fmt, ...) { - char *path; struct strbuf sb = STRBUF_INIT; va_list args; - va_start(args, fmt); strbuf_vaddf(&sb, fmt, args); va_end(args); - path = xstrdup(cleanup_path(sb.buf)); - - strbuf_release(&sb); - return path; + strbuf_cleanup_path(&sb); + return strbuf_detach(&sb, NULL); } char *mkpath(const char *fmt, ...) { va_list args; - unsigned len; - char *pathname = get_pathname(); - + struct strbuf *pathname = get_pathname(); va_start(args, fmt); - len = vsnprintf(pathname, PATH_MAX, fmt, args); + strbuf_vaddf(pathname, fmt, args); va_end(args); - if (len >= PATH_MAX) - return bad_path; - return cleanup_path(pathname); + return cleanup_path(pathname->buf); } char *git_path(const char *fmt, ...) { - char *pathname = get_pathname(); + struct strbuf *pathname = get_pathname(); va_list args; - char *ret; - va_start(args, fmt); - ret = vsnpath(pathname, PATH_MAX, fmt, args); + vsnpath(pathname, fmt, args); va_end(args); - return ret; + return pathname->buf; } void home_config_paths(char **global, char **xdg, char *file) @@ -160,41 +156,27 @@ void home_config_paths(char **global, char **xdg, char *file) char *git_path_submodule(const char *path, const char *fmt, ...) { - char *pathname = get_pathname(); - struct strbuf buf = STRBUF_INIT; + struct strbuf *buf = get_pathname(); const char *git_dir; va_list args; - unsigned len; - - len = strlen(path); - if (len > PATH_MAX-100) - return bad_path; - strbuf_addstr(&buf, path); - if (len && path[len-1] != '/') - strbuf_addch(&buf, '/'); - strbuf_addstr(&buf, ".git"); + strbuf_addstr(buf, path); + if (buf->len && buf->buf[buf->len - 1] != '/') + strbuf_addch(buf, '/'); + strbuf_addstr(buf, ".git"); - git_dir = read_gitfile(buf.buf); + git_dir = read_gitfile(buf->buf); if (git_dir) { - strbuf_reset(&buf); - strbuf_addstr(&buf, git_dir); + strbuf_reset(buf); + strbuf_addstr(buf, git_dir); } - strbuf_addch(&buf, '/'); - - if (buf.len >= PATH_MAX) - return bad_path; - memcpy(pathname, buf.buf, buf.len + 1); - - strbuf_release(&buf); - len = strlen(pathname); + strbuf_addch(buf, '/'); va_start(args, fmt); - len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args); + strbuf_vaddf(buf, fmt, args); va_end(args); - if (len >= PATH_MAX) - return bad_path; - return cleanup_path(pathname); + strbuf_cleanup_path(buf); + return buf->buf; } int validate_headref(const char *path) -- cgit v1.2.3 From dcf692625ac569fefbe52269061230f4fde10e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:27 +0700 Subject: path.c: make get_pathname() call sites return const char * MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before the previous commit, get_pathname returns an array of PATH_MAX length. Even if git_path() and similar functions does not use the whole array, git_path() caller can, in theory. After the commit, get_pathname() may return a buffer that has just enough room for the returned string and git_path() caller should never write beyond that. Make git_path(), mkpath() and git_path_submodule() return a const buffer to make sure callers do not write in it at all. This could have been part of the previous commit, but the "const" conversion is too much distraction from the core changes in path.c. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'path.c') diff --git a/path.c b/path.c index 015c0e4b39..a7ceea26fb 100644 --- a/path.c +++ b/path.c @@ -106,7 +106,7 @@ char *mkpathdup(const char *fmt, ...) return strbuf_detach(&sb, NULL); } -char *mkpath(const char *fmt, ...) +const char *mkpath(const char *fmt, ...) { va_list args; struct strbuf *pathname = get_pathname(); @@ -116,7 +116,7 @@ char *mkpath(const char *fmt, ...) return cleanup_path(pathname->buf); } -char *git_path(const char *fmt, ...) +const char *git_path(const char *fmt, ...) { struct strbuf *pathname = get_pathname(); va_list args; @@ -154,7 +154,7 @@ void home_config_paths(char **global, char **xdg, char *file) free(to_free); } -char *git_path_submodule(const char *path, const char *fmt, ...) +const char *git_path_submodule(const char *path, const char *fmt, ...) { struct strbuf *buf = get_pathname(); const char *git_dir; -- cgit v1.2.3 From 1a83c240f2fe7a0caa94009f066d15fa677d32cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:28 +0700 Subject: git_snpath(): retire and replace with strbuf_git_path() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the previous patch, git_snpath() is modified to allocate a new strbuf buffer because vsnpath() needs that. But that makes it awkward because git_snpath() receives a pre-allocated buffer from outside and has to copy data back. Rename it to strbuf_git_path() and make it receive strbuf directly. Using git_path() in update_refs_for_switch() which used to call git_snpath() is safe because that function and all of its callers do not keep any pointer to the round-robin buffer pool allocated by get_pathname(). Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'path.c') diff --git a/path.c b/path.c index a7ceea26fb..47753aaffc 100644 --- a/path.c +++ b/path.c @@ -70,19 +70,12 @@ static void vsnpath(struct strbuf *buf, const char *fmt, va_list args) strbuf_cleanup_path(buf); } -char *git_snpath(char *buf, size_t n, const char *fmt, ...) +void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) { - struct strbuf sb = STRBUF_INIT; va_list args; va_start(args, fmt); - vsnpath(&sb, fmt, args); + vsnpath(sb, fmt, args); va_end(args); - if (sb.len >= n) - strlcpy(buf, bad_path, n); - else - memcpy(buf, sb.buf, sb.len + 1); - strbuf_release(&sb); - return buf; } char *git_pathdup(const char *fmt, ...) -- cgit v1.2.3 From 8afdaf39e318711dc05ad52ae6c227eaedf6c7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:29 +0700 Subject: path.c: rename vsnpath() to do_git_path() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The name vsnpath() gives an impression that this is general path handling function. It's not. This is the underlying implementation of git_path(), git_pathdup() and strbuf_git_path() which will prefix $GIT_DIR in the result string. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'path.c') diff --git a/path.c b/path.c index 47753aaffc..6991103d43 100644 --- a/path.c +++ b/path.c @@ -60,7 +60,7 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...) return cleanup_path(buf); } -static void vsnpath(struct strbuf *buf, const char *fmt, va_list args) +static void do_git_path(struct strbuf *buf, const char *fmt, va_list args) { const char *git_dir = get_git_dir(); strbuf_addstr(buf, git_dir); @@ -74,7 +74,7 @@ void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) { va_list args; va_start(args, fmt); - vsnpath(sb, fmt, args); + do_git_path(sb, fmt, args); va_end(args); } @@ -83,7 +83,7 @@ char *git_pathdup(const char *fmt, ...) struct strbuf path = STRBUF_INIT; va_list args; va_start(args, fmt); - vsnpath(&path, fmt, args); + do_git_path(&path, fmt, args); va_end(args); return strbuf_detach(&path, NULL); } @@ -114,7 +114,7 @@ const char *git_path(const char *fmt, ...) struct strbuf *pathname = get_pathname(); va_list args; va_start(args, fmt); - vsnpath(pathname, fmt, args); + do_git_path(pathname, fmt, args); va_end(args); return pathname->buf; } -- cgit v1.2.3 From 57a23b770a839786f2eaae4a9dde779149bfb812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:30 +0700 Subject: path.c: group git_path(), git_pathdup() and strbuf_git_path() together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'path.c') diff --git a/path.c b/path.c index 6991103d43..df0f75ba4f 100644 --- a/path.c +++ b/path.c @@ -78,6 +78,16 @@ void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) va_end(args); } +const char *git_path(const char *fmt, ...) +{ + struct strbuf *pathname = get_pathname(); + va_list args; + va_start(args, fmt); + do_git_path(pathname, fmt, args); + va_end(args); + return pathname->buf; +} + char *git_pathdup(const char *fmt, ...) { struct strbuf path = STRBUF_INIT; @@ -109,16 +119,6 @@ const char *mkpath(const char *fmt, ...) return cleanup_path(pathname->buf); } -const char *git_path(const char *fmt, ...) -{ - struct strbuf *pathname = get_pathname(); - va_list args; - va_start(args, fmt); - do_git_path(pathname, fmt, args); - va_end(args); - return pathname->buf; -} - void home_config_paths(char **global, char **xdg, char *file) { char *xdg_home = getenv("XDG_CONFIG_HOME"); -- cgit v1.2.3 From 557bd833bb4e2bd1f109f6f911ab517b6ba3d27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:31 +0700 Subject: git_path(): be aware of file relocation in $GIT_DIR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We allow the user to relocate certain paths out of $GIT_DIR via environment variables, e.g. GIT_OBJECT_DIRECTORY, GIT_INDEX_FILE and GIT_GRAFT_FILE. Callers are not supposed to use git_path() or git_pathdup() to get those paths. Instead they must use get_object_directory(), get_index_file() and get_graft_file() respectively. This is inconvenient and could be missed in review (for example, there's git_path("objects/info/alternates") somewhere in sha1_file.c). This patch makes git_path() and git_pathdup() understand those environment variables. So if you set GIT_OBJECT_DIRECTORY to /foo/bar, git_path("objects/abc") should return /foo/bar/abc. The same is done for the two remaining env variables. "git rev-parse --git-path" is the wrapper for script use. This patch kinda reverts a0279e1 (setup_git_env: use git_pathdup instead of xmalloc + sprintf - 2014-06-19) because using git_pathdup here would result in infinite recursion: setup_git_env() -> git_pathdup("objects") -> .. -> adjust_git_path() -> get_object_directory() -> oops, git_object_directory is NOT set yet -> setup_git_env() I wanted to make git_pathdup_literal() that skips adjust_git_path(). But that won't work because later on when $GIT_COMMON_DIR is introduced, git_pathdup_literal("objects") needs adjust_git_path() to replace $GIT_DIR with $GIT_COMMON_DIR. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'path.c') diff --git a/path.c b/path.c index df0f75ba4f..4910783dbd 100644 --- a/path.c +++ b/path.c @@ -60,13 +60,58 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...) return cleanup_path(buf); } +static int dir_prefix(const char *buf, const char *dir) +{ + int len = strlen(dir); + return !strncmp(buf, dir, len) && + (is_dir_sep(buf[len]) || buf[len] == '\0'); +} + +/* $buf =~ m|$dir/+$file| but without regex */ +static int is_dir_file(const char *buf, const char *dir, const char *file) +{ + int len = strlen(dir); + if (strncmp(buf, dir, len) || !is_dir_sep(buf[len])) + return 0; + while (is_dir_sep(buf[len])) + len++; + return !strcmp(buf + len, file); +} + +static void replace_dir(struct strbuf *buf, int len, const char *newdir) +{ + int newlen = strlen(newdir); + int need_sep = (buf->buf[len] && !is_dir_sep(buf->buf[len])) && + !is_dir_sep(newdir[newlen - 1]); + if (need_sep) + len--; /* keep one char, to be replaced with '/' */ + strbuf_splice(buf, 0, len, newdir, newlen); + if (need_sep) + buf->buf[newlen] = '/'; +} + +static void adjust_git_path(struct strbuf *buf, int git_dir_len) +{ + const char *base = buf->buf + git_dir_len; + if (git_graft_env && is_dir_file(base, "info", "grafts")) + strbuf_splice(buf, 0, buf->len, + get_graft_file(), strlen(get_graft_file())); + else if (git_index_env && !strcmp(base, "index")) + strbuf_splice(buf, 0, buf->len, + get_index_file(), strlen(get_index_file())); + else if (git_db_env && dir_prefix(base, "objects")) + replace_dir(buf, git_dir_len + 7, get_object_directory()); +} + static void do_git_path(struct strbuf *buf, const char *fmt, va_list args) { - const char *git_dir = get_git_dir(); - strbuf_addstr(buf, git_dir); + int gitdir_len; + strbuf_addstr(buf, get_git_dir()); if (buf->len && !is_dir_sep(buf->buf[buf->len - 1])) strbuf_addch(buf, '/'); + gitdir_len = buf->len; strbuf_vaddf(buf, fmt, args); + adjust_git_path(buf, gitdir_len); strbuf_cleanup_path(buf); } -- cgit v1.2.3 From c7b3a3d2fe2688a30ddb8d516ed000eeda13c24e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:36 +0700 Subject: $GIT_COMMON_DIR: a new environment variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This variable is intended to support multiple working directories attached to a repository. Such a repository may have a main working directory, created by either "git init" or "git clone" and one or more linked working directories. These working directories and the main repository share the same repository directory. In linked working directories, $GIT_COMMON_DIR must be defined to point to the real repository directory and $GIT_DIR points to an unused subdirectory inside $GIT_COMMON_DIR. File locations inside the repository are reorganized from the linked worktree view point: - worktree-specific such as HEAD, logs/HEAD, index, other top-level refs and unrecognized files are from $GIT_DIR. - the rest like objects, refs, info, hooks, packed-refs, shallow... are from $GIT_COMMON_DIR (except info/sparse-checkout, but that's a separate patch) Scripts are supposed to retrieve paths in $GIT_DIR with "git rev-parse --git-path", which will take care of "$GIT_DIR vs $GIT_COMMON_DIR" business. The redirection is done by git_path(), git_pathdup() and strbuf_git_path(). The selected list of paths goes to $GIT_COMMON_DIR, not the other way around in case a developer adds a new worktree-specific file and it's accidentally promoted to be shared across repositories (this includes unknown files added by third party commands) The list of known files that belong to $GIT_DIR are: ADD_EDIT.patch BISECT_ANCESTORS_OK BISECT_EXPECTED_REV BISECT_LOG BISECT_NAMES CHERRY_PICK_HEAD COMMIT_MSG FETCH_HEAD HEAD MERGE_HEAD MERGE_MODE MERGE_RR NOTES_EDITMSG NOTES_MERGE_WORKTREE ORIG_HEAD REVERT_HEAD SQUASH_MSG TAG_EDITMSG fast_import_crash_* logs/HEAD next-index-* rebase-apply rebase-merge rsync-refs-* sequencer/* shallow_* Path mapping is NOT done for git_path_submodule(). Multi-checkouts are not supported as submodules. Helped-by: Jens Lehmann Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'path.c') diff --git a/path.c b/path.c index 4910783dbd..94db5016c4 100644 --- a/path.c +++ b/path.c @@ -90,6 +90,38 @@ static void replace_dir(struct strbuf *buf, int len, const char *newdir) buf->buf[newlen] = '/'; } +static const char *common_list[] = { + "/branches", "/hooks", "/info", "/logs", "/lost-found", "/modules", + "/objects", "/refs", "/remotes", "/rr-cache", "/svn", + "config", "gc.pid", "packed-refs", "shallow", + NULL +}; + +static void update_common_dir(struct strbuf *buf, int git_dir_len) +{ + char *base = buf->buf + git_dir_len; + const char **p; + + if (is_dir_file(base, "logs", "HEAD")) + return; /* keep this in $GIT_DIR */ + for (p = common_list; *p; p++) { + const char *path = *p; + int is_dir = 0; + if (*path == '/') { + path++; + is_dir = 1; + } + if (is_dir && dir_prefix(base, path)) { + replace_dir(buf, git_dir_len, get_git_common_dir()); + return; + } + if (!is_dir && !strcmp(base, path)) { + replace_dir(buf, git_dir_len, get_git_common_dir()); + return; + } + } +} + static void adjust_git_path(struct strbuf *buf, int git_dir_len) { const char *base = buf->buf + git_dir_len; @@ -101,6 +133,8 @@ static void adjust_git_path(struct strbuf *buf, int git_dir_len) get_index_file(), strlen(get_index_file())); else if (git_db_env && dir_prefix(base, "objects")) replace_dir(buf, git_dir_len + 7, get_object_directory()); + else if (git_common_dir_env) + update_common_dir(buf, git_dir_len); } static void do_git_path(struct strbuf *buf, const char *fmt, va_list args) -- cgit v1.2.3 From 529fef20cf94dbd5c16f7a239ffc2b06f3cf8bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:47 +0700 Subject: checkout: support checking out into a new working directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "git checkout --to" sets up a new working directory with a .git file pointing to $GIT_DIR/worktrees/. It then executes "git checkout" again on the new worktree with the same arguments except "--to" is taken out. The second checkout execution, which is not contaminated with any info from the current repository, will actually check out and everything that normal "git checkout" does. Helped-by: Marc Branchaud Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'path.c') diff --git a/path.c b/path.c index 94db5016c4..72eca6dfa5 100644 --- a/path.c +++ b/path.c @@ -92,7 +92,7 @@ static void replace_dir(struct strbuf *buf, int len, const char *newdir) static const char *common_list[] = { "/branches", "/hooks", "/info", "/logs", "/lost-found", "/modules", - "/objects", "/refs", "/remotes", "/rr-cache", "/svn", + "/objects", "/refs", "/remotes", "/worktrees", "/rr-cache", "/svn", "config", "gc.pid", "packed-refs", "shallow", NULL }; -- cgit v1.2.3 From 77a6d84045c8b558d1e08ff2ffe70347b19be6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:54 +0700 Subject: count-objects: report unused files in $GIT_DIR/worktrees/... MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In linked checkouts, borrowed parts like config is taken from $GIT_COMMON_DIR. $GIT_DIR/config is never used. Report them as garbage. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'path.c') diff --git a/path.c b/path.c index 72eca6dfa5..cd8e2d6e68 100644 --- a/path.c +++ b/path.c @@ -4,6 +4,7 @@ #include "cache.h" #include "strbuf.h" #include "string-list.h" +#include "dir.h" static int get_st_mode_bits(const char *path, int *mode) { @@ -91,9 +92,9 @@ static void replace_dir(struct strbuf *buf, int len, const char *newdir) } static const char *common_list[] = { - "/branches", "/hooks", "/info", "/logs", "/lost-found", "/modules", + "/branches", "/hooks", "/info", "!/logs", "/lost-found", "/modules", "/objects", "/refs", "/remotes", "/worktrees", "/rr-cache", "/svn", - "config", "gc.pid", "packed-refs", "shallow", + "config", "!gc.pid", "packed-refs", "shallow", NULL }; @@ -107,6 +108,8 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len) for (p = common_list; *p; p++) { const char *path = *p; int is_dir = 0; + if (*path == '!') + path++; if (*path == '/') { path++; is_dir = 1; @@ -122,6 +125,28 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len) } } +void report_linked_checkout_garbage(void) +{ + struct strbuf sb = STRBUF_INIT; + const char **p; + int len; + + if (!git_common_dir_env) + return; + strbuf_addf(&sb, "%s/", get_git_dir()); + len = sb.len; + for (p = common_list; *p; p++) { + const char *path = *p; + if (*path == '!') + continue; + strbuf_setlen(&sb, len); + strbuf_addstr(&sb, path); + if (file_exists(sb.buf)) + report_garbage("unused in linked checkout", sb.buf); + } + strbuf_release(&sb); +} + static void adjust_git_path(struct strbuf *buf, int git_dir_len) { const char *base = buf->buf + git_dir_len; -- cgit v1.2.3 From 6cfbdcb2ab70b238fca9b3811f5b58368fd077c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 30 Nov 2014 15:24:55 +0700 Subject: git_path(): keep "info/sparse-checkout" per work-tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently git_path("info/sparse-checkout") resolves to $GIT_COMMON_DIR/info/sparse-checkout in multiple worktree mode. It makes more sense for the sparse checkout patterns to be per worktree, so you can have multiple checkouts with different parts of the tree. With this, "git checkout --to " on a sparse checkout will create as a full checkout. Which is expected, it's how a new checkout is made. The user can reshape the worktree afterwards. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'path.c') diff --git a/path.c b/path.c index cd8e2d6e68..35d498e9bc 100644 --- a/path.c +++ b/path.c @@ -103,7 +103,8 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len) char *base = buf->buf + git_dir_len; const char **p; - if (is_dir_file(base, "logs", "HEAD")) + if (is_dir_file(base, "logs", "HEAD") || + is_dir_file(base, "info", "sparse-checkout")) return; /* keep this in $GIT_DIR */ for (p = common_list; *p; p++) { const char *path = *p; -- cgit v1.2.3 From df56607dff2d656043a1f77a647f97a0a6b5aec9 Mon Sep 17 00:00:00 2001 From: Max Kirillov Date: Sun, 30 Nov 2014 15:24:59 +0700 Subject: git-common-dir: make "modules/" per-working-directory directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each working directory of main repository has its own working directory of submodule, and in most cases they should be checked out to different revisions. So they should be separated. It looks logical to make submodule instances in different working directories to reuse the submodule directory in the common dir of the main repository, and probably this is how "checkout --to" should initialize them called on the main repository, but they also should work fine being completely separated clones. Testfile t7410-submodule-checkout-to.sh demostrates the behavior. Signed-off-by: Max Kirillov Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- path.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'path.c') diff --git a/path.c b/path.c index 35d498e9bc..a5c51a33bd 100644 --- a/path.c +++ b/path.c @@ -92,7 +92,7 @@ static void replace_dir(struct strbuf *buf, int len, const char *newdir) } static const char *common_list[] = { - "/branches", "/hooks", "/info", "!/logs", "/lost-found", "/modules", + "/branches", "/hooks", "/info", "!/logs", "/lost-found", "/objects", "/refs", "/remotes", "/worktrees", "/rr-cache", "/svn", "config", "!gc.pid", "packed-refs", "shallow", NULL -- cgit v1.2.3