diff options
author | Jacob Keller <jacob.keller@gmail.com> | 2016-08-31 16:27:22 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-08-31 18:07:10 -0700 |
commit | 99b43a61f2daf5fe183056e5bf2a75a8a81a28bf (patch) | |
tree | 1d1b35c5f3f04c9b60c37e26ca165769ba1d922e /path.c | |
parent | 61cfbc054d8341c3276efbf1380a2be0ee435dba (diff) | |
download | git-99b43a61f2daf5fe183056e5bf2a75a8a81a28bf.tar.gz |
allow do_submodule_path to work even if submodule isn't checked out
Currently, do_submodule_path will attempt locating the .git directory by
using read_gitfile on <path>/.git. If this fails it just assumes the
<path>/.git is actually a git directory.
This is good because it allows for handling submodules which were cloned
in a regular manner first before being added to the superproject.
Unfortunately this fails if the <path> is not actually checked out any
longer, such as by removing the directory.
Fix this by checking if the directory we found is actually a gitdir. In
the case it is not, attempt to lookup the submodule configuration and
find the name of where it is stored in the .git/modules/ directory of
the superproject.
If we can't locate the submodule configuration, this might occur because
for example a submodule gitlink was added but the corresponding
.gitmodules file was not properly updated. A die() here would not be
pleasant to the users of submodule diff formats, so instead, modify
do_submodule_path() to return an error code:
- git_pathdup_submodule() returns NULL when we fail to find a path.
- strbuf_git_path_submodule() propagates the error code to the caller.
Modify the callers of these functions to check the error code and fail
properly. This ensures we don't attempt to use a bad path that doesn't
match the corresponding submodule.
Because this change fixes add_submodule_odb() to work even if the
submodule is not checked out, update the wording of the submodule log
diff format to correctly display that the submodule is "not initialized"
instead of "not checked out"
Add tests to ensure this change works as expected.
Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'path.c')
-rw-r--r-- | path.c | 39 |
1 files changed, 33 insertions, 6 deletions
@@ -6,6 +6,7 @@ #include "string-list.h" #include "dir.h" #include "worktree.h" +#include "submodule-config.h" static int get_st_mode_bits(const char *path, int *mode) { @@ -466,12 +467,16 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...) return pathname->buf; } -static void do_submodule_path(struct strbuf *buf, const char *path, - const char *fmt, va_list args) +/* Returns 0 on success, negative on failure. */ +#define SUBMODULE_PATH_ERR_NOT_CONFIGURED -1 +static int do_submodule_path(struct strbuf *buf, const char *path, + const char *fmt, va_list args) { const char *git_dir; struct strbuf git_submodule_common_dir = STRBUF_INIT; struct strbuf git_submodule_dir = STRBUF_INIT; + const struct submodule *sub; + int err = 0; strbuf_addstr(buf, path); strbuf_complete(buf, '/'); @@ -482,6 +487,17 @@ static void do_submodule_path(struct strbuf *buf, const char *path, strbuf_reset(buf); strbuf_addstr(buf, git_dir); } + if (!is_git_directory(buf->buf)) { + gitmodules_config(); + sub = submodule_from_path(null_sha1, path); + if (!sub) { + err = SUBMODULE_PATH_ERR_NOT_CONFIGURED; + goto cleanup; + } + strbuf_reset(buf); + strbuf_git_path(buf, "%s/%s", "modules", sub->name); + } + strbuf_addch(buf, '/'); strbuf_addbuf(&git_submodule_dir, buf); @@ -492,27 +508,38 @@ static void do_submodule_path(struct strbuf *buf, const char *path, strbuf_cleanup_path(buf); +cleanup: strbuf_release(&git_submodule_dir); strbuf_release(&git_submodule_common_dir); + + return err; } char *git_pathdup_submodule(const char *path, const char *fmt, ...) { + int err; va_list args; struct strbuf buf = STRBUF_INIT; va_start(args, fmt); - do_submodule_path(&buf, path, fmt, args); + err = do_submodule_path(&buf, path, fmt, args); va_end(args); + if (err) { + strbuf_release(&buf); + return NULL; + } return strbuf_detach(&buf, NULL); } -void strbuf_git_path_submodule(struct strbuf *buf, const char *path, - const char *fmt, ...) +int strbuf_git_path_submodule(struct strbuf *buf, const char *path, + const char *fmt, ...) { + int err; va_list args; va_start(args, fmt); - do_submodule_path(buf, path, fmt, args); + err = do_submodule_path(buf, path, fmt, args); va_end(args); + + return err; } static void do_git_common_path(struct strbuf *buf, |