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 <raykar.ath@gmail.com> Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Shourya Shukla <periperidip@gmail.com> Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Atharva Raykar committed
Jul 10, 2021 at 13:18 UTC
a98b02c11289879868dd0d5f80e894d8d01dc73b
1 file changed
+128
-113
builtin/submodule--helper.c
+128
-113
@@ -1658,45 +1658,20 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
1658
return 0;
1659
}
1660
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 }
1675
1676
struct submodule_alternate_setup {
1677
const char *submodule_name;
@@ -1802,37 +1777,128 @@ static void prepare_possible_alternates(const char *sm_name,
1777
free(error_strategy);
1778
}
1779
1805
-static int module_clone(int argc, const char **argv, const char *prefix)
1780
+static int clone_submodule(struct module_clone_data *clone_data)
1781
{
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;
1783
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;
1882
1883
struct option module_clone_options[] = {
1818
- OPT_STRING(0, "prefix", &prefix,
1884
+ OPT_STRING(0, "prefix", &clone_data.prefix,
1885
N_("path"),
1886
N_("alternative anchor for relative paths")),
1821
- OPT_STRING(0, "path", &path,
1887
+ OPT_STRING(0, "path", &clone_data.path,
1888
N_("path"),
1889
N_("where the new submodule will be cloned to")),
1824
- OPT_STRING(0, "name", &name,
1890
+ OPT_STRING(0, "name", &clone_data.name,
1891
N_("string"),
1892
N_("name of the new submodule")),
1827
- OPT_STRING(0, "url", &url,
1893
+ OPT_STRING(0, "url", &clone_data.url,
1894
N_("string"),
1895
N_("url where to clone the submodule from")),
1830
- OPT_STRING_LIST(0, "reference", &reference,
1896
+ OPT_STRING_LIST(0, "reference", &clone_data.reference,
1897
N_("repo"),
1898
N_("reference repository")),
1899
OPT_BOOL(0, "dissociate", &dissociate,
1900
N_("use --reference only while cloning")),
1835
- OPT_STRING(0, "depth", &depth,
1901
+ OPT_STRING(0, "depth", &clone_data.depth,
1902
N_("string"),
1903
N_("depth for shallow clones")),
1904
OPT__QUIET(&quiet, "Suppress output for cloning a submodule"),
@@ -1840,7 +1906,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
1906
N_("force cloning progress")),
1907
OPT_BOOL(0, "require-init", &require_init,
1908
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,
1910
N_("clone only one branch, HEAD or --branch")),
1911
OPT_END()
1912
};
@@ -1856,67 +1922,16 @@ static int module_clone(int argc, const char **argv, const char *prefix)
1922
argc = parse_options(argc, argv, prefix, module_clone_options,
1923
git_submodule_helper_usage, 0);
1924
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))
1931
usage_with_options(git_submodule_helper_usage,
1932
module_clone_options);
1933
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);
1935
return 0;
1936
}
1937