Skip to content

Commit a98b02c

Browse files
tfidfwastakengitster
authored andcommitted
submodule--helper: refactor module_clone()
Separate out the core logic of module_clone() from the flag parsing---this way we can call the equivalent of the `submodule--helper clone` subcommand directly within C, without needing to push arguments in a strvec. Signed-off-by: Atharva Raykar <[email protected]> Mentored-by: Christian Couder <[email protected]> Mentored-by: Shourya Shukla <[email protected]> Suggested-by: Junio C Hamano <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0008d12 commit a98b02c

File tree

1 file changed

+128
-113
lines changed

1 file changed

+128
-113
lines changed

builtin/submodule--helper.c

Lines changed: 128 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,45 +1658,20 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
16581658
return 0;
16591659
}
16601660

1661-
static int clone_submodule(const char *path, const char *gitdir, const char *url,
1662-
const char *depth, struct string_list *reference, int dissociate,
1663-
int quiet, int progress, int single_branch)
1664-
{
1665-
struct child_process cp = CHILD_PROCESS_INIT;
1666-
1667-
strvec_push(&cp.args, "clone");
1668-
strvec_push(&cp.args, "--no-checkout");
1669-
if (quiet)
1670-
strvec_push(&cp.args, "--quiet");
1671-
if (progress)
1672-
strvec_push(&cp.args, "--progress");
1673-
if (depth && *depth)
1674-
strvec_pushl(&cp.args, "--depth", depth, NULL);
1675-
if (reference->nr) {
1676-
struct string_list_item *item;
1677-
for_each_string_list_item(item, reference)
1678-
strvec_pushl(&cp.args, "--reference",
1679-
item->string, NULL);
1680-
}
1681-
if (dissociate)
1682-
strvec_push(&cp.args, "--dissociate");
1683-
if (gitdir && *gitdir)
1684-
strvec_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
1685-
if (single_branch >= 0)
1686-
strvec_push(&cp.args, single_branch ?
1687-
"--single-branch" :
1688-
"--no-single-branch");
1689-
1690-
strvec_push(&cp.args, "--");
1691-
strvec_push(&cp.args, url);
1692-
strvec_push(&cp.args, path);
1693-
1694-
cp.git_cmd = 1;
1695-
prepare_submodule_repo_env(&cp.env_array);
1696-
cp.no_stdin = 1;
1697-
1698-
return run_command(&cp);
1699-
}
1661+
struct module_clone_data {
1662+
const char *prefix;
1663+
const char *path;
1664+
const char *name;
1665+
const char *url;
1666+
const char *depth;
1667+
struct string_list reference;
1668+
unsigned int quiet: 1;
1669+
unsigned int progress: 1;
1670+
unsigned int dissociate: 1;
1671+
unsigned int require_init: 1;
1672+
int single_branch;
1673+
};
1674+
#define MODULE_CLONE_DATA_INIT { .reference = STRING_LIST_INIT_NODUP, .single_branch = -1 }
17001675

17011676
struct submodule_alternate_setup {
17021677
const char *submodule_name;
@@ -1802,45 +1777,136 @@ static void prepare_possible_alternates(const char *sm_name,
18021777
free(error_strategy);
18031778
}
18041779

1805-
static int module_clone(int argc, const char **argv, const char *prefix)
1780+
static int clone_submodule(struct module_clone_data *clone_data)
18061781
{
1807-
const char *name = NULL, *url = NULL, *depth = NULL;
1808-
int quiet = 0;
1809-
int progress = 0;
1810-
char *p, *path = NULL, *sm_gitdir;
1811-
struct strbuf sb = STRBUF_INIT;
1812-
struct string_list reference = STRING_LIST_INIT_NODUP;
1813-
int dissociate = 0, require_init = 0;
1782+
char *p, *sm_gitdir;
18141783
char *sm_alternate = NULL, *error_strategy = NULL;
1815-
int single_branch = -1;
1784+
struct strbuf sb = STRBUF_INIT;
1785+
struct child_process cp = CHILD_PROCESS_INIT;
1786+
1787+
strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), clone_data->name);
1788+
sm_gitdir = absolute_pathdup(sb.buf);
1789+
strbuf_reset(&sb);
1790+
1791+
if (!is_absolute_path(clone_data->path)) {
1792+
strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
1793+
clone_data->path = strbuf_detach(&sb, NULL);
1794+
} else {
1795+
clone_data->path = xstrdup(clone_data->path);
1796+
}
1797+
1798+
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
1799+
die(_("refusing to create/use '%s' in another submodule's "
1800+
"git dir"), sm_gitdir);
1801+
1802+
if (!file_exists(sm_gitdir)) {
1803+
if (safe_create_leading_directories_const(sm_gitdir) < 0)
1804+
die(_("could not create directory '%s'"), sm_gitdir);
1805+
1806+
prepare_possible_alternates(clone_data->name, &clone_data->reference);
1807+
1808+
strvec_push(&cp.args, "clone");
1809+
strvec_push(&cp.args, "--no-checkout");
1810+
if (clone_data->quiet)
1811+
strvec_push(&cp.args, "--quiet");
1812+
if (clone_data->progress)
1813+
strvec_push(&cp.args, "--progress");
1814+
if (clone_data->depth && *(clone_data->depth))
1815+
strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
1816+
if (clone_data->reference.nr) {
1817+
struct string_list_item *item;
1818+
for_each_string_list_item(item, &clone_data->reference)
1819+
strvec_pushl(&cp.args, "--reference",
1820+
item->string, NULL);
1821+
}
1822+
if (clone_data->dissociate)
1823+
strvec_push(&cp.args, "--dissociate");
1824+
if (sm_gitdir && *sm_gitdir)
1825+
strvec_pushl(&cp.args, "--separate-git-dir", sm_gitdir, NULL);
1826+
if (clone_data->single_branch >= 0)
1827+
strvec_push(&cp.args, clone_data->single_branch ?
1828+
"--single-branch" :
1829+
"--no-single-branch");
1830+
1831+
strvec_push(&cp.args, "--");
1832+
strvec_push(&cp.args, clone_data->url);
1833+
strvec_push(&cp.args, clone_data->path);
1834+
1835+
cp.git_cmd = 1;
1836+
prepare_submodule_repo_env(&cp.env_array);
1837+
cp.no_stdin = 1;
1838+
1839+
if(run_command(&cp))
1840+
die(_("clone of '%s' into submodule path '%s' failed"),
1841+
clone_data->url, clone_data->path);
1842+
} else {
1843+
if (clone_data->require_init && !access(clone_data->path, X_OK) &&
1844+
!is_empty_dir(clone_data->path))
1845+
die(_("directory not empty: '%s'"), clone_data->path);
1846+
if (safe_create_leading_directories_const(clone_data->path) < 0)
1847+
die(_("could not create directory '%s'"), clone_data->path);
1848+
strbuf_addf(&sb, "%s/index", sm_gitdir);
1849+
unlink_or_warn(sb.buf);
1850+
strbuf_reset(&sb);
1851+
}
1852+
1853+
connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
1854+
1855+
p = git_pathdup_submodule(clone_data->path, "config");
1856+
if (!p)
1857+
die(_("could not get submodule directory for '%s'"), clone_data->path);
1858+
1859+
/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
1860+
git_config_get_string("submodule.alternateLocation", &sm_alternate);
1861+
if (sm_alternate)
1862+
git_config_set_in_file(p, "submodule.alternateLocation",
1863+
sm_alternate);
1864+
git_config_get_string("submodule.alternateErrorStrategy", &error_strategy);
1865+
if (error_strategy)
1866+
git_config_set_in_file(p, "submodule.alternateErrorStrategy",
1867+
error_strategy);
1868+
1869+
free(sm_alternate);
1870+
free(error_strategy);
1871+
1872+
strbuf_release(&sb);
1873+
free(sm_gitdir);
1874+
free(p);
1875+
return 0;
1876+
}
1877+
1878+
static int module_clone(int argc, const char **argv, const char *prefix)
1879+
{
1880+
int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
1881+
struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
18161882

18171883
struct option module_clone_options[] = {
1818-
OPT_STRING(0, "prefix", &prefix,
1884+
OPT_STRING(0, "prefix", &clone_data.prefix,
18191885
N_("path"),
18201886
N_("alternative anchor for relative paths")),
1821-
OPT_STRING(0, "path", &path,
1887+
OPT_STRING(0, "path", &clone_data.path,
18221888
N_("path"),
18231889
N_("where the new submodule will be cloned to")),
1824-
OPT_STRING(0, "name", &name,
1890+
OPT_STRING(0, "name", &clone_data.name,
18251891
N_("string"),
18261892
N_("name of the new submodule")),
1827-
OPT_STRING(0, "url", &url,
1893+
OPT_STRING(0, "url", &clone_data.url,
18281894
N_("string"),
18291895
N_("url where to clone the submodule from")),
1830-
OPT_STRING_LIST(0, "reference", &reference,
1896+
OPT_STRING_LIST(0, "reference", &clone_data.reference,
18311897
N_("repo"),
18321898
N_("reference repository")),
18331899
OPT_BOOL(0, "dissociate", &dissociate,
18341900
N_("use --reference only while cloning")),
1835-
OPT_STRING(0, "depth", &depth,
1901+
OPT_STRING(0, "depth", &clone_data.depth,
18361902
N_("string"),
18371903
N_("depth for shallow clones")),
18381904
OPT__QUIET(&quiet, "Suppress output for cloning a submodule"),
18391905
OPT_BOOL(0, "progress", &progress,
18401906
N_("force cloning progress")),
18411907
OPT_BOOL(0, "require-init", &require_init,
18421908
N_("disallow cloning into non-empty directory")),
1843-
OPT_BOOL(0, "single-branch", &single_branch,
1909+
OPT_BOOL(0, "single-branch", &clone_data.single_branch,
18441910
N_("clone only one branch, HEAD or --branch")),
18451911
OPT_END()
18461912
};
@@ -1856,67 +1922,16 @@ static int module_clone(int argc, const char **argv, const char *prefix)
18561922
argc = parse_options(argc, argv, prefix, module_clone_options,
18571923
git_submodule_helper_usage, 0);
18581924

1859-
if (argc || !url || !path || !*path)
1925+
clone_data.dissociate = !!dissociate;
1926+
clone_data.quiet = !!quiet;
1927+
clone_data.progress = !!progress;
1928+
clone_data.require_init = !!require_init;
1929+
1930+
if (argc || !clone_data.url || !clone_data.path || !*(clone_data.path))
18601931
usage_with_options(git_submodule_helper_usage,
18611932
module_clone_options);
18621933

1863-
strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
1864-
sm_gitdir = absolute_pathdup(sb.buf);
1865-
strbuf_reset(&sb);
1866-
1867-
if (!is_absolute_path(path)) {
1868-
strbuf_addf(&sb, "%s/%s", get_git_work_tree(), path);
1869-
path = strbuf_detach(&sb, NULL);
1870-
} else
1871-
path = xstrdup(path);
1872-
1873-
if (validate_submodule_git_dir(sm_gitdir, name) < 0)
1874-
die(_("refusing to create/use '%s' in another submodule's "
1875-
"git dir"), sm_gitdir);
1876-
1877-
if (!file_exists(sm_gitdir)) {
1878-
if (safe_create_leading_directories_const(sm_gitdir) < 0)
1879-
die(_("could not create directory '%s'"), sm_gitdir);
1880-
1881-
prepare_possible_alternates(name, &reference);
1882-
1883-
if (clone_submodule(path, sm_gitdir, url, depth, &reference, dissociate,
1884-
quiet, progress, single_branch))
1885-
die(_("clone of '%s' into submodule path '%s' failed"),
1886-
url, path);
1887-
} else {
1888-
if (require_init && !access(path, X_OK) && !is_empty_dir(path))
1889-
die(_("directory not empty: '%s'"), path);
1890-
if (safe_create_leading_directories_const(path) < 0)
1891-
die(_("could not create directory '%s'"), path);
1892-
strbuf_addf(&sb, "%s/index", sm_gitdir);
1893-
unlink_or_warn(sb.buf);
1894-
strbuf_reset(&sb);
1895-
}
1896-
1897-
connect_work_tree_and_git_dir(path, sm_gitdir, 0);
1898-
1899-
p = git_pathdup_submodule(path, "config");
1900-
if (!p)
1901-
die(_("could not get submodule directory for '%s'"), path);
1902-
1903-
/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
1904-
git_config_get_string("submodule.alternateLocation", &sm_alternate);
1905-
if (sm_alternate)
1906-
git_config_set_in_file(p, "submodule.alternateLocation",
1907-
sm_alternate);
1908-
git_config_get_string("submodule.alternateErrorStrategy", &error_strategy);
1909-
if (error_strategy)
1910-
git_config_set_in_file(p, "submodule.alternateErrorStrategy",
1911-
error_strategy);
1912-
1913-
free(sm_alternate);
1914-
free(error_strategy);
1915-
1916-
strbuf_release(&sb);
1917-
free(sm_gitdir);
1918-
free(path);
1919-
free(p);
1934+
clone_submodule(&clone_data);
19201935
return 0;
19211936
}
19221937

0 commit comments

Comments
 (0)