diff options
Diffstat (limited to 'submodule.c')
-rw-r--r-- | submodule.c | 104 |
1 files changed, 99 insertions, 5 deletions
diff --git a/submodule.c b/submodule.c index 3007f7d5a6..b3b8bc1479 100644 --- a/submodule.c +++ b/submodule.c @@ -4,22 +4,26 @@ #include "diff.h" #include "commit.h" #include "revision.h" +#include "run-command.h" +#include "diffcore.h" static int add_submodule_odb(const char *path) { struct strbuf objects_directory = STRBUF_INIT; struct alternate_object_database *alt_odb; + int ret = 0; strbuf_addf(&objects_directory, "%s/.git/objects/", path); - if (!is_directory(objects_directory.buf)) - return -1; - + if (!is_directory(objects_directory.buf)) { + ret = -1; + goto done; + } /* avoid adding it twice */ for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next) if (alt_odb->name - alt_odb->base == objects_directory.len && !strncmp(alt_odb->base, objects_directory.buf, objects_directory.len)) - return 0; + goto done; alt_odb = xmalloc(objects_directory.len + 42 + sizeof(*alt_odb)); alt_odb->next = alt_odb_list; @@ -30,11 +34,14 @@ static int add_submodule_odb(const char *path) alt_odb->name[41] = '\0'; alt_odb_list = alt_odb; prepare_alt_odb(); - return 0; +done: + strbuf_release(&objects_directory); + return ret; } void show_submodule_summary(FILE *f, const char *path, unsigned char one[20], unsigned char two[20], + unsigned dirty_submodule, const char *del, const char *add, const char *reset) { struct rev_info rev; @@ -79,6 +86,16 @@ void show_submodule_summary(FILE *f, const char *path, message = "(revision walker failed)"; } + if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED) + fprintf(f, "Submodule %s contains untracked content\n", path); + if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED) + fprintf(f, "Submodule %s contains modified content\n", path); + + if (!hashcmp(one, two)) { + strbuf_release(&sb); + return; + } + strbuf_addf(&sb, "Submodule %s %s..", path, find_unique_abbrev(one, DEFAULT_ABBREV)); if (!fast_backward && !fast_forward) @@ -112,3 +129,80 @@ void show_submodule_summary(FILE *f, const char *path, } strbuf_release(&sb); } + +unsigned is_submodule_modified(const char *path, int ignore_untracked) +{ + int i; + ssize_t len; + struct child_process cp; + const char *argv[] = { + "status", + "--porcelain", + NULL, + NULL, + }; + const char *env[LOCAL_REPO_ENV_SIZE + 3]; + struct strbuf buf = STRBUF_INIT; + unsigned dirty_submodule = 0; + const char *line, *next_line; + + for (i = 0; i < LOCAL_REPO_ENV_SIZE; i++) + env[i] = local_repo_env[i]; + + strbuf_addf(&buf, "%s/.git/", path); + if (!is_directory(buf.buf)) { + strbuf_release(&buf); + /* The submodule is not checked out, so it is not modified */ + return 0; + + } + strbuf_reset(&buf); + + strbuf_addf(&buf, "GIT_WORK_TREE=%s", path); + env[i++] = strbuf_detach(&buf, NULL); + strbuf_addf(&buf, "GIT_DIR=%s/.git", path); + env[i++] = strbuf_detach(&buf, NULL); + env[i] = NULL; + + if (ignore_untracked) + argv[2] = "-uno"; + + memset(&cp, 0, sizeof(cp)); + cp.argv = argv; + cp.env = env; + cp.git_cmd = 1; + cp.no_stdin = 1; + cp.out = -1; + if (start_command(&cp)) + die("Could not run git status --porcelain"); + + len = strbuf_read(&buf, cp.out, 1024); + line = buf.buf; + while (len > 2) { + if ((line[0] == '?') && (line[1] == '?')) { + dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED; + if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED) + break; + } else { + dirty_submodule |= DIRTY_SUBMODULE_MODIFIED; + if (ignore_untracked || + (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)) + break; + } + next_line = strchr(line, '\n'); + if (!next_line) + break; + next_line++; + len -= (next_line - line); + line = next_line; + } + close(cp.out); + + if (finish_command(&cp)) + die("git status --porcelain failed"); + + for (i = LOCAL_REPO_ENV_SIZE; env[i]; i++) + free((char *)env[i]); + strbuf_release(&buf); + return dirty_submodule; +} |