I finished the refactoring and picked up suggestions from Eric and Junio. Stefan Beller (3): submodule: Reimplement `module_list` shell function in C submodule: Reimplement `module_name` shell function in C submodule: Reimplement `module_clone` shell function in C .gitignore | 1 + Makefile | 1 + builtin.h | 1 + builtin/submodule--helper.c | 282 ++++++++++++++++++++++++++++++++++++++++++++ git-submodule.sh | 166 +++----------------------- git.c | 1 + 6 files changed, 302 insertions(+), 150 deletions(-) create mode 100644 builtin/submodule--helper.c diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 63f535a..4e30d8e 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -38,17 +38,16 @@ static int module_list_compute(int argc, const char **argv, for (i = 0; i < active_nr; i++) { const struct cache_entry *ce = active_cache[i]; - if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), + if (!S_ISGITLINK(ce->ce_mode) || + !match_pathspec(pathspec, ce->name, ce_namelen(ce), max_prefix_len, ps_matched, S_ISGITLINK(ce->ce_mode) | S_ISDIR(ce->ce_mode))) continue; - if (S_ISGITLINK(ce->ce_mode)) { - ALLOC_GROW(ce_entries, ce_used + 1, ce_alloc); - ce_entries[ce_used++] = ce; - } - - while (i + 1 < active_nr && !strcmp(ce->name, active_cache[i + 1]->name)) + ALLOC_GROW(ce_entries, ce_used + 1, ce_alloc); + ce_entries[ce_used++] = ce; + while (i + 1 < active_nr && + !strcmp(ce->name, active_cache[i + 1]->name)) /* * Skip entries with the same name in different stages * to make sure an entry is returned only once. @@ -69,10 +68,9 @@ static int module_list(int argc, const char **argv, const char *prefix) { int i; struct pathspec pathspec; - const char *alternative_path; struct option module_list_options[] = { - OPT_STRING(0, "prefix", &alternative_path, + OPT_STRING(0, "prefix", &prefix, N_("path"), N_("alternative anchor for relative paths")), OPT_END() @@ -86,9 +84,7 @@ static int module_list(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, module_list_options, git_submodule_helper_usage, 0); - if (module_list_compute(argc, argv, alternative_path - ? alternative_path - : prefix, &pathspec) < 0) { + if (module_list_compute(argc, argv, prefix, &pathspec) < 0) { printf("#unmatched\n"); return 1; } @@ -111,13 +107,13 @@ static int module_name(int argc, const char **argv, const char *prefix) const struct submodule *sub; if (argc != 2) - usage("git submodule--helper module_name <path>\n"); + usage(_("git submodule--helper name <path>")); gitmodules_config(); sub = submodule_from_path(null_sha1, argv[1]); if (!sub) - die(N_("No submodule mapping found in .gitmodules for path '%s'"), + die(_("no submodule mapping found in .gitmodules for path '%s'"), argv[1]); printf("%s\n", sub->name); @@ -158,15 +154,14 @@ static int module_clone(int argc, const char **argv, const char *prefix) { const char *path = NULL, *name = NULL, *url = NULL; const char *reference = NULL, *depth = NULL; - const char *alternative_path = NULL, *p; int quiet = 0; FILE *submodule_dot_git; - char *sm_gitdir; + char *sm_gitdir, *cwd, *p; struct strbuf rel_path = STRBUF_INIT; struct strbuf sb = STRBUF_INIT; struct option module_clone_options[] = { - OPT_STRING(0, "prefix", &alternative_path, + OPT_STRING(0, "prefix", &prefix, N_("path"), N_("alternative anchor for relative paths")), OPT_STRING(0, "path", &path, @@ -188,7 +183,7 @@ static int module_clone(int argc, const char **argv, const char *prefix) OPT_END() }; - const char * const git_submodule_helper_usage[] = { + const char *const git_submodule_helper_usage[] = { N_("git submodule--helper clone [--prefix=<path>] [--quiet] " "[--reference <repository>] [--name <name>] [--url <url>]" "[--depth <depth>] [--] [<path>...]"), @@ -205,67 +200,64 @@ static int module_clone(int argc, const char **argv, const char *prefix) if (safe_create_leading_directories_const(sm_gitdir) < 0) die(_("could not create directory '%s'"), sm_gitdir); if (clone_submodule(path, sm_gitdir, url, depth, reference, quiet)) - die(N_("clone of '%s' into submodule path '%s' failed"), + die(_("clone of '%s' into submodule path '%s' failed"), url, path); } else { if (safe_create_leading_directories_const(path) < 0) die(_("could not create directory '%s'"), path); - if (unlink(sm_gitdir) < 0) + strbuf_addf(&sb, "%s/index", sm_gitdir); + if (unlink(sb.buf) < 0) die_errno(_("failed to delete '%s'"), sm_gitdir); + strbuf_reset(&sb); } /* Write a .git file in the submodule to redirect to the superproject. */ - if (alternative_path && *alternative_path)) { - p = relative_path(path, alternative_path, &sb); - strbuf_reset(&sb); - } else - p = path; + if (safe_create_leading_directories_const(path) < 0) + die(_("could not create directory '%s'"), path); - if (safe_create_leading_directories_const(p) < 0) - die(_("could not create directory '%s'"), p); - - strbuf_addf(&sb, "%s/.git", p); + if (path && *path) + strbuf_addf(&sb, "%s/.git", path); + else + strbuf_addf(&sb, ".git"); if (safe_create_leading_directories_const(sb.buf) < 0) die(_("could not create leading directories of '%s'"), sb.buf); submodule_dot_git = fopen(sb.buf, "w"); if (!submodule_dot_git) - die (_("cannot open file '%s': %s"), sb.buf, strerror(errno)); + die_errno(_("cannot open file '%s'"), sb.buf); fprintf(submodule_dot_git, "gitdir: %s\n", relative_path(sm_gitdir, path, &rel_path)); if (fclose(submodule_dot_git)) die(_("could not close file %s"), sb.buf); strbuf_reset(&sb); + strbuf_reset(&rel_path); + cwd = xgetcwd(); /* Redirect the worktree of the submodule in the superproject's config */ - if (strbuf_getcwd(&sb)) - die_errno(_("unable to get current working directory")); - if (!is_absolute_path(sm_gitdir)) { - if (strbuf_getcwd(&sb)) - die_errno(_("unable to get current working directory")); - strbuf_addf(&sb, "/%s", sm_gitdir); + strbuf_addf(&sb, "%s/%s", cwd, sm_gitdir); free(sm_gitdir); sm_gitdir = strbuf_detach(&sb, NULL); } - - strbuf_addf(&sb, "/%s", path); - + strbuf_addf(&sb, "%s/%s", cwd, path); p = git_pathdup_submodule(path, "config"); if (!p) die(_("could not get submodule directory for '%s'"), path); git_config_set_in_file(p, "core.worktree", relative_path(sb.buf, sm_gitdir, &rel_path)); strbuf_release(&sb); + strbuf_release(&rel_path); free(sm_gitdir); + free(cwd); + free(p); return 0; } struct cmd_struct { const char *cmd; - int (*fct)(int, const char **, const char *); + int (*fn)(int, const char **, const char *); }; static struct cmd_struct commands[] = { @@ -278,22 +270,13 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix) { int i; if (argc < 2) - goto out; + die(_("fatal: submodule--helper subcommand must be " + "called with a subcommand")); for (i = 0; i < ARRAY_SIZE(commands); i++) if (!strcmp(argv[1], commands[i].cmd)) - return commands[i].fct(argc - 1, argv + 1, prefix); - -out: - if (argc > 1) - fprintf(stderr, _("fatal: '%s' is not a valid submodule--helper " - "subcommand, which are:\n"), argv[1]); - else - fprintf(stderr, _("fatal: submodule--helper subcommand must be " - "called with a subcommand, which are:\n")); - - for (i = 0; i < ARRAY_SIZE(commands); i++) - fprintf(stderr, "\t%s\n", commands[i].cmd); + return commands[i].fn(argc - 1, argv + 1, prefix); - exit(129); + die(_("fatal: '%s' is not a valid submodule--helper " + "subcommand"), argv[1]); } -- 2.5.0.256.g89f8063.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html