Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'submodule.c')
-rw-r--r--submodule.c144
1 files changed, 78 insertions, 66 deletions
diff --git a/submodule.c b/submodule.c
index 49ab132d05..cdbecfbeaf 100644
--- a/submodule.c
+++ b/submodule.c
@@ -22,8 +22,8 @@ static int config_update_recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static int parallel_jobs = 1;
static struct string_list changed_submodule_paths = STRING_LIST_INIT_NODUP;
static int initialized_fetch_ref_tips;
-static struct sha1_array ref_tips_before_fetch;
-static struct sha1_array ref_tips_after_fetch;
+static struct oid_array ref_tips_before_fetch;
+static struct oid_array ref_tips_after_fetch;
/*
* The following flag is set if the .gitmodules file is unmerged. We then
@@ -577,6 +577,7 @@ void show_submodule_inline_diff(FILE *f, const char *path,
if (!(dirty_submodule & DIRTY_SUBMODULE_MODIFIED))
argv_array_push(&cp.args, oid_to_hex(new));
+ prepare_submodule_repo_env(&cp.env_array);
if (run_command(&cp))
fprintf(f, "(diff failed)\n");
@@ -622,35 +623,35 @@ static int has_remote(const char *refname, const struct object_id *oid,
return 1;
}
-static int append_sha1_to_argv(const unsigned char sha1[20], void *data)
+static int append_oid_to_argv(const struct object_id *oid, void *data)
{
struct argv_array *argv = data;
- argv_array_push(argv, sha1_to_hex(sha1));
+ argv_array_push(argv, oid_to_hex(oid));
return 0;
}
-static int check_has_commit(const unsigned char sha1[20], void *data)
+static int check_has_commit(const struct object_id *oid, void *data)
{
int *has_commit = data;
- if (!lookup_commit_reference(sha1))
+ if (!lookup_commit_reference(oid->hash))
*has_commit = 0;
return 0;
}
-static int submodule_has_commits(const char *path, struct sha1_array *commits)
+static int submodule_has_commits(const char *path, struct oid_array *commits)
{
int has_commit = 1;
if (add_submodule_odb(path))
return 0;
- sha1_array_for_each_unique(commits, check_has_commit, &has_commit);
+ oid_array_for_each_unique(commits, check_has_commit, &has_commit);
return has_commit;
}
-static int submodule_needs_pushing(const char *path, struct sha1_array *commits)
+static int submodule_needs_pushing(const char *path, struct oid_array *commits)
{
if (!submodule_has_commits(path, commits))
/*
@@ -672,7 +673,7 @@ static int submodule_needs_pushing(const char *path, struct sha1_array *commits)
int needs_pushing = 0;
argv_array_push(&cp.args, "rev-list");
- sha1_array_for_each_unique(commits, append_sha1_to_argv, &cp.args);
+ oid_array_for_each_unique(commits, append_oid_to_argv, &cp.args);
argv_array_pushl(&cp.args, "--not", "--remotes", "-n", "1" , NULL);
prepare_submodule_repo_env(&cp.env_array);
@@ -694,18 +695,18 @@ static int submodule_needs_pushing(const char *path, struct sha1_array *commits)
return 0;
}
-static struct sha1_array *submodule_commits(struct string_list *submodules,
+static struct oid_array *submodule_commits(struct string_list *submodules,
const char *path)
{
struct string_list_item *item;
item = string_list_insert(submodules, path);
if (item->util)
- return (struct sha1_array *) item->util;
+ return (struct oid_array *) item->util;
- /* NEEDSWORK: should we have sha1_array_init()? */
- item->util = xcalloc(1, sizeof(struct sha1_array));
- return (struct sha1_array *) item->util;
+ /* NEEDSWORK: should we have oid_array_init()? */
+ item->util = xcalloc(1, sizeof(struct oid_array));
+ return (struct oid_array *) item->util;
}
static void collect_submodules_from_diff(struct diff_queue_struct *q,
@@ -717,11 +718,11 @@ static void collect_submodules_from_diff(struct diff_queue_struct *q,
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
- struct sha1_array *commits;
+ struct oid_array *commits;
if (!S_ISGITLINK(p->two->mode))
continue;
commits = submodule_commits(submodules, p->two->path);
- sha1_array_append(commits, p->two->oid.hash);
+ oid_array_append(commits, &p->two->oid);
}
}
@@ -741,11 +742,11 @@ static void free_submodules_sha1s(struct string_list *submodules)
{
struct string_list_item *item;
for_each_string_list_item(item, submodules)
- sha1_array_clear((struct sha1_array *) item->util);
+ oid_array_clear((struct oid_array *) item->util);
string_list_clear(submodules, 1);
}
-int find_unpushed_submodules(struct sha1_array *commits,
+int find_unpushed_submodules(struct oid_array *commits,
const char *remotes_name, struct string_list *needs_pushing)
{
struct rev_info rev;
@@ -758,7 +759,7 @@ int find_unpushed_submodules(struct sha1_array *commits,
/* argv.argv[0] will be ignored by setup_revisions */
argv_array_push(&argv, "find_unpushed_submodules");
- sha1_array_for_each_unique(commits, append_sha1_to_argv, &argv);
+ oid_array_for_each_unique(commits, append_oid_to_argv, &argv);
argv_array_push(&argv, "--not");
argv_array_pushf(&argv, "--remotes=%s", remotes_name);
@@ -773,7 +774,7 @@ int find_unpushed_submodules(struct sha1_array *commits,
argv_array_clear(&argv);
for_each_string_list_item(submodule, &submodules) {
- struct sha1_array *commits = (struct sha1_array *) submodule->util;
+ struct oid_array *commits = (struct oid_array *) submodule->util;
if (submodule_needs_pushing(submodule->string, commits))
string_list_insert(needs_pushing, submodule->string);
@@ -856,7 +857,7 @@ static void submodule_push_check(const char *path, const struct remote *remote,
die("process for submodule '%s' failed", path);
}
-int push_unpushed_submodules(struct sha1_array *commits,
+int push_unpushed_submodules(struct oid_array *commits,
const struct remote *remote,
const char **refspec, int refspec_nr,
const struct string_list *push_options,
@@ -953,23 +954,23 @@ static void submodule_collect_changed_cb(struct diff_queue_struct *q,
static int add_sha1_to_array(const char *ref, const struct object_id *oid,
int flags, void *data)
{
- sha1_array_append(data, oid->hash);
+ oid_array_append(data, oid);
return 0;
}
-void check_for_new_submodule_commits(unsigned char new_sha1[20])
+void check_for_new_submodule_commits(struct object_id *oid)
{
if (!initialized_fetch_ref_tips) {
for_each_ref(add_sha1_to_array, &ref_tips_before_fetch);
initialized_fetch_ref_tips = 1;
}
- sha1_array_append(&ref_tips_after_fetch, new_sha1);
+ oid_array_append(&ref_tips_after_fetch, oid);
}
-static int add_sha1_to_argv(const unsigned char sha1[20], void *data)
+static int add_oid_to_argv(const struct object_id *oid, void *data)
{
- argv_array_push(data, sha1_to_hex(sha1));
+ argv_array_push(data, oid_to_hex(oid));
return 0;
}
@@ -985,11 +986,11 @@ static void calculate_changed_submodule_paths(void)
init_revisions(&rev, NULL);
argv_array_push(&argv, "--"); /* argv[0] program name */
- sha1_array_for_each_unique(&ref_tips_after_fetch,
- add_sha1_to_argv, &argv);
+ oid_array_for_each_unique(&ref_tips_after_fetch,
+ add_oid_to_argv, &argv);
argv_array_push(&argv, "--not");
- sha1_array_for_each_unique(&ref_tips_before_fetch,
- add_sha1_to_argv, &argv);
+ oid_array_for_each_unique(&ref_tips_before_fetch,
+ add_oid_to_argv, &argv);
setup_revisions(argv.argc, argv.argv, &rev, NULL);
if (prepare_revision_walk(&rev))
die("revision walk setup failed");
@@ -1015,8 +1016,8 @@ static void calculate_changed_submodule_paths(void)
}
argv_array_clear(&argv);
- sha1_array_clear(&ref_tips_before_fetch);
- sha1_array_clear(&ref_tips_after_fetch);
+ oid_array_clear(&ref_tips_before_fetch);
+ oid_array_clear(&ref_tips_after_fetch);
initialized_fetch_ref_tips = 0;
}
@@ -1177,67 +1178,78 @@ out:
unsigned is_submodule_modified(const char *path, int ignore_untracked)
{
- ssize_t len;
struct child_process cp = CHILD_PROCESS_INIT;
- const char *argv[] = {
- "status",
- "--porcelain",
- NULL,
- NULL,
- };
struct strbuf buf = STRBUF_INIT;
+ FILE *fp;
unsigned dirty_submodule = 0;
- const char *line, *next_line;
const char *git_dir;
+ int ignore_cp_exit_code = 0;
strbuf_addf(&buf, "%s/.git", path);
git_dir = read_gitfile(buf.buf);
if (!git_dir)
git_dir = buf.buf;
- if (!is_directory(git_dir)) {
+ if (!is_git_directory(git_dir)) {
+ if (is_directory(git_dir))
+ die(_("'%s' not recognized as a git repository"), git_dir);
strbuf_release(&buf);
/* The submodule is not checked out, so it is not modified */
return 0;
-
}
strbuf_reset(&buf);
+ argv_array_pushl(&cp.args, "status", "--porcelain=2", NULL);
if (ignore_untracked)
- argv[2] = "-uno";
+ argv_array_push(&cp.args, "-uno");
- cp.argv = argv;
prepare_submodule_repo_env(&cp.env_array);
cp.git_cmd = 1;
cp.no_stdin = 1;
cp.out = -1;
cp.dir = path;
if (start_command(&cp))
- die("Could not run 'git status --porcelain' in submodule %s", path);
+ die("Could not run 'git status --porcelain=2' in submodule %s", path);
- len = strbuf_read(&buf, cp.out, 1024);
- line = buf.buf;
- while (len > 2) {
- if ((line[0] == '?') && (line[1] == '?')) {
+ fp = xfdopen(cp.out, "r");
+ while (strbuf_getwholeline(&buf, fp, '\n') != EOF) {
+ /* regular untracked files */
+ if (buf.buf[0] == '?')
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;
+
+ if (buf.buf[0] == 'u' ||
+ buf.buf[0] == '1' ||
+ buf.buf[0] == '2') {
+ /* T = line type, XY = status, SSSS = submodule state */
+ if (buf.len < strlen("T XY SSSS"))
+ die("BUG: invalid status --porcelain=2 line %s",
+ buf.buf);
+
+ if (buf.buf[5] == 'S' && buf.buf[8] == 'U')
+ /* nested untracked file */
+ dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
+
+ if (buf.buf[0] == 'u' ||
+ buf.buf[0] == '2' ||
+ memcmp(buf.buf + 5, "S..U", 4))
+ /* other change */
+ dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
}
- next_line = strchr(line, '\n');
- if (!next_line)
+
+ if ((dirty_submodule & DIRTY_SUBMODULE_MODIFIED) &&
+ ((dirty_submodule & DIRTY_SUBMODULE_UNTRACKED) ||
+ ignore_untracked)) {
+ /*
+ * We're not interested in any further information from
+ * the child any more, neither output nor its exit code.
+ */
+ ignore_cp_exit_code = 1;
break;
- next_line++;
- len -= (next_line - line);
- line = next_line;
+ }
}
- close(cp.out);
+ fclose(fp);
- if (finish_command(&cp))
- die("'git status --porcelain' failed in submodule %s", path);
+ if (finish_command(&cp) && !ignore_cp_exit_code)
+ die("'git status --porcelain=2' failed in submodule %s", path);
strbuf_release(&buf);
return dirty_submodule;
@@ -1502,7 +1514,7 @@ static int find_first_merges(struct object_array *result, const char *path,
memset(&rev_opts, 0, sizeof(rev_opts));
/* get all revisions that merge commit a */
- snprintf(merged_revision, sizeof(merged_revision), "^%s",
+ xsnprintf(merged_revision, sizeof(merged_revision), "^%s",
oid_to_hex(&a->object.oid));
init_revisions(&revs, NULL);
rev_opts.submodule = path;