diff options
-rw-r--r-- | Documentation/git-clone.txt | 11 | ||||
-rw-r--r-- | builtin/clone.c | 21 | ||||
-rw-r--r-- | builtin/remote.c | 14 | ||||
-rw-r--r-- | cache.h | 2 | ||||
-rw-r--r-- | config.c | 4 | ||||
-rw-r--r-- | parse-options.c | 17 | ||||
-rw-r--r-- | parse-options.h | 4 | ||||
-rwxr-xr-x | t/t0040-parse-options.sh | 17 | ||||
-rwxr-xr-x | t/t5708-clone-config.sh | 40 | ||||
-rw-r--r-- | test-parse-options.c | 6 |
10 files changed, 121 insertions, 15 deletions
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index b093e45497..4b8b26b75e 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -159,6 +159,17 @@ objects from the source repository into a pack in the cloned repository. Specify the directory from which templates will be used; (See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].) +--config <key>=<value>:: +-c <key>=<value>:: + Set a configuration variable in the newly-created repository; + this takes effect immediately after the repository is + initialized, but before the remote history is fetched or any + files checked out. The key is in the same format as expected by + linkgit:git-config[1] (e.g., `core.eol=true`). If multiple + values are given for the same key, each value will be written to + the config file. This makes it safe, for example, to add + additional fetch refspecs to the origin remote. + --depth <depth>:: Create a 'shallow' clone with a history truncated to the specified number of revisions. A shallow repository has a diff --git a/builtin/clone.c b/builtin/clone.c index f579794d9a..a15784a7b8 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -46,6 +46,7 @@ static const char *real_git_dir; static char *option_upload_pack = "git-upload-pack"; static int option_verbosity; static int option_progress; +static struct string_list option_config; static struct option builtin_clone_options[] = { OPT__VERBOSITY(&option_verbosity), @@ -83,7 +84,8 @@ static struct option builtin_clone_options[] = { "create a shallow clone of that depth"), OPT_STRING(0, "separate-git-dir", &real_git_dir, "gitdir", "separate git dir from working tree"), - + OPT_STRING_LIST('c', "config", &option_config, "key=value", + "set config inside the new repository"), OPT_END() }; @@ -364,6 +366,22 @@ static void write_remote_refs(const struct ref *local_refs) clear_extra_refs(); } +static int write_one_config(const char *key, const char *value, void *data) +{ + return git_config_set_multivar(key, value ? value : "true", "^$", 0); +} + +static void write_config(struct string_list *config) +{ + int i; + + for (i = 0; i < config->nr; i++) { + if (git_config_parse_parameter(config->items[i].string, + write_one_config, NULL) < 0) + die("unable to write parameters to config file"); + } +} + int cmd_clone(int argc, const char **argv, const char *prefix) { int is_bundle = 0, is_local; @@ -482,6 +500,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) printf(_("Cloning into %s...\n"), dir); } init_db(option_template, INIT_DB_QUIET); + write_config(&option_config); /* * At this point, the config exists, so we do not need the diff --git a/builtin/remote.c b/builtin/remote.c index 9ff1cac69b..05b1f5b76d 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -88,16 +88,6 @@ static inline int postfixcmp(const char *string, const char *postfix) return strcmp(string + len1 - len2, postfix); } -static int opt_parse_track(const struct option *opt, const char *arg, int not) -{ - struct string_list *list = opt->value; - if (not) - string_list_clear(list, 0); - else - string_list_append(list, arg); - return 0; -} - static int fetch_remote(const char *name) { const char *argv[] = { "fetch", name, NULL, NULL }; @@ -176,8 +166,8 @@ static int add(int argc, const char **argv) TAGS_SET), OPT_SET_INT(0, NULL, &fetch_tags, "or do not fetch any tag at all (--no-tags)", TAGS_UNSET), - OPT_CALLBACK('t', "track", &track, "branch", - "branch(es) to track", opt_parse_track), + OPT_STRING_LIST('t', "track", &track, "branch", + "branch(es) to track"), OPT_STRING('m', "master", &master, "branch", "master branch"), { OPTION_CALLBACK, 0, "mirror", &mirror, "push|fetch", "set up remote as a mirror to push to or fetch from", @@ -1082,6 +1082,8 @@ extern int config_error_nonbool(const char *); extern const char *get_log_output_encoding(void); extern const char *get_commit_output_encoding(void); +extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data); + extern const char *config_exclusive_filename; #define MAX_GITNAME (1000) @@ -47,8 +47,8 @@ void git_config_push_parameter(const char *text) strbuf_release(&env); } -static int git_config_parse_parameter(const char *text, - config_fn_t fn, void *data) +int git_config_parse_parameter(const char *text, + config_fn_t fn, void *data) { struct strbuf **pair; pair = strbuf_split_str(text, '=', 2); diff --git a/parse-options.c b/parse-options.c index 73bd28ad90..879ea82a31 100644 --- a/parse-options.c +++ b/parse-options.c @@ -3,6 +3,7 @@ #include "cache.h" #include "commit.h" #include "color.h" +#include "string-list.h" static int parse_options_usage(struct parse_opt_ctx_t *ctx, const char * const *usagestr, @@ -687,3 +688,19 @@ int parse_options_concat(struct option *dst, size_t dst_size, struct option *src } return -1; } + +int parse_opt_string_list(const struct option *opt, const char *arg, int unset) +{ + struct string_list *v = opt->value; + + if (unset) { + string_list_clear(v, 0); + return 0; + } + + if (!arg) + return -1; + + string_list_append(v, xstrdup(arg)); + return 0; +} diff --git a/parse-options.h b/parse-options.h index d1b12fe979..05eb09b878 100644 --- a/parse-options.h +++ b/parse-options.h @@ -130,6 +130,9 @@ struct option { (h), PARSE_OPT_NOARG, NULL, (p) } #define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), "n", (h) } #define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } +#define OPT_STRING_LIST(s, l, v, a, h) \ + { OPTION_CALLBACK, (s), (l), (v), (a), \ + (h), 0, &parse_opt_string_list } #define OPT_UYN(s, l, v, h) { OPTION_CALLBACK, (s), (l), (v), NULL, \ (h), PARSE_OPT_NOARG, &parse_opt_tertiary } #define OPT_DATE(s, l, v, h) \ @@ -204,6 +207,7 @@ extern int parse_opt_color_flag_cb(const struct option *, const char *, int); extern int parse_opt_verbosity_cb(const struct option *, const char *, int); extern int parse_opt_with_commit(const struct option *, const char *, int); extern int parse_opt_tertiary(const struct option *, const char *, int); +extern int parse_opt_string_list(const struct option *, const char *, int); #define OPT__VERBOSE(var, h) OPT_BOOLEAN('v', "verbose", (var), (h)) #define OPT__QUIET(var, h) OPT_BOOLEAN('q', "quiet", (var), (h)) diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index ae266147b6..007f39d5e1 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -28,6 +28,7 @@ String options --st <st> get another string (pervert ordering) -o <str> get another string --default-string set string to default + --list <str> add str to list Magic arguments --quux means --quux @@ -337,4 +338,20 @@ test_expect_success 'negation of OPT_NONEG flags is not ambiguous' ' test_cmp expect output ' +cat >>expect <<'EOF' +list: foo +list: bar +list: baz +EOF +test_expect_success '--list keeps list of strings' ' + test-parse-options --list foo --list=bar --list=baz >output && + test_cmp expect output +' + +test_expect_success '--no-list resets list' ' + test-parse-options --list=other --list=irrelevant --list=options \ + --no-list --list=foo --list=bar --list=baz >output && + test_cmp expect output +' + test_done diff --git a/t/t5708-clone-config.sh b/t/t5708-clone-config.sh new file mode 100755 index 0000000000..27d730c0a7 --- /dev/null +++ b/t/t5708-clone-config.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +test_description='tests for git clone -c key=value' +. ./test-lib.sh + +test_expect_success 'clone -c sets config in cloned repo' ' + rm -rf child && + git clone -c core.foo=bar . child && + echo bar >expect && + git --git-dir=child/.git config core.foo >actual && + test_cmp expect actual +' + +test_expect_success 'clone -c can set multi-keys' ' + rm -rf child && + git clone -c core.foo=bar -c core.foo=baz . child && + { echo bar; echo baz; } >expect && + git --git-dir=child/.git config --get-all core.foo >actual && + test_cmp expect actual +' + +test_expect_success 'clone -c without a value is boolean true' ' + rm -rf child && + git clone -c core.foo . child && + echo true >expect && + git --git-dir=child/.git config --bool core.foo >actual && + test_cmp expect actual +' + +test_expect_success 'clone -c config is available during clone' ' + echo content >file && + git add file && + git commit -m one && + rm -rf child && + git clone -c core.autocrlf . child && + printf "content\\r\\n" >expect && + test_cmp expect child/file +' + +test_done diff --git a/test-parse-options.c b/test-parse-options.c index 4e3710b9a8..91a5701657 100644 --- a/test-parse-options.c +++ b/test-parse-options.c @@ -1,5 +1,6 @@ #include "cache.h" #include "parse-options.h" +#include "string-list.h" static int boolean = 0; static int integer = 0; @@ -9,6 +10,7 @@ static int verbose = 0, dry_run = 0, quiet = 0; static char *string = NULL; static char *file = NULL; static int ambiguous; +static struct string_list list; static int length_callback(const struct option *opt, const char *arg, int unset) { @@ -54,6 +56,7 @@ int main(int argc, const char **argv) OPT_STRING('o', NULL, &string, "str", "get another string"), OPT_SET_PTR(0, "default-string", &string, "set string to default", (unsigned long)"default"), + OPT_STRING_LIST(0, "list", &list, "str", "add str to list"), OPT_GROUP("Magic arguments"), OPT_ARGUMENT("quux", "means --quux"), OPT_NUMBER_CALLBACK(&integer, "set integer to NUM", @@ -85,6 +88,9 @@ int main(int argc, const char **argv) printf("dry run: %s\n", dry_run ? "yes" : "no"); printf("file: %s\n", file ? file : "(not set)"); + for (i = 0; i < list.nr; i++) + printf("list: %s\n", list.items[i].string); + for (i = 0; i < argc; i++) printf("arg %02d: %s\n", i, argv[i]); |