зеркало из https://github.com/microsoft/git.git
Merge branch 'jk/clone-cmdline-config'
* jk/clone-cmdline-config: clone: accept config options on the command line config: make git_config_parse_parameter a public function remote: use new OPT_STRING_LIST parse-options: add OPT_STRING_LIST helper
This commit is contained in:
Коммит
ff94409da9
|
@ -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;
|
Specify the directory from which templates will be used;
|
||||||
(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
|
(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>::
|
--depth <depth>::
|
||||||
Create a 'shallow' clone with a history truncated to the
|
Create a 'shallow' clone with a history truncated to the
|
||||||
specified number of revisions. A shallow repository has a
|
specified number of revisions. A shallow repository has a
|
||||||
|
|
|
@ -46,6 +46,7 @@ static const char *real_git_dir;
|
||||||
static char *option_upload_pack = "git-upload-pack";
|
static char *option_upload_pack = "git-upload-pack";
|
||||||
static int option_verbosity;
|
static int option_verbosity;
|
||||||
static int option_progress;
|
static int option_progress;
|
||||||
|
static struct string_list option_config;
|
||||||
|
|
||||||
static struct option builtin_clone_options[] = {
|
static struct option builtin_clone_options[] = {
|
||||||
OPT__VERBOSITY(&option_verbosity),
|
OPT__VERBOSITY(&option_verbosity),
|
||||||
|
@ -83,7 +84,8 @@ static struct option builtin_clone_options[] = {
|
||||||
"create a shallow clone of that depth"),
|
"create a shallow clone of that depth"),
|
||||||
OPT_STRING(0, "separate-git-dir", &real_git_dir, "gitdir",
|
OPT_STRING(0, "separate-git-dir", &real_git_dir, "gitdir",
|
||||||
"separate git dir from working tree"),
|
"separate git dir from working tree"),
|
||||||
|
OPT_STRING_LIST('c', "config", &option_config, "key=value",
|
||||||
|
"set config inside the new repository"),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -364,6 +366,22 @@ static void write_remote_refs(const struct ref *local_refs)
|
||||||
clear_extra_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 cmd_clone(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int is_bundle = 0, is_local;
|
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);
|
printf(_("Cloning into %s...\n"), dir);
|
||||||
}
|
}
|
||||||
init_db(option_template, INIT_DB_QUIET);
|
init_db(option_template, INIT_DB_QUIET);
|
||||||
|
write_config(&option_config);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point, the config exists, so we do not need the
|
* At this point, the config exists, so we do not need the
|
||||||
|
|
|
@ -88,16 +88,6 @@ static inline int postfixcmp(const char *string, const char *postfix)
|
||||||
return strcmp(string + len1 - len2, 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)
|
static int fetch_remote(const char *name)
|
||||||
{
|
{
|
||||||
const char *argv[] = { "fetch", name, NULL, NULL };
|
const char *argv[] = { "fetch", name, NULL, NULL };
|
||||||
|
@ -176,8 +166,8 @@ static int add(int argc, const char **argv)
|
||||||
TAGS_SET),
|
TAGS_SET),
|
||||||
OPT_SET_INT(0, NULL, &fetch_tags,
|
OPT_SET_INT(0, NULL, &fetch_tags,
|
||||||
"or do not fetch any tag at all (--no-tags)", TAGS_UNSET),
|
"or do not fetch any tag at all (--no-tags)", TAGS_UNSET),
|
||||||
OPT_CALLBACK('t', "track", &track, "branch",
|
OPT_STRING_LIST('t', "track", &track, "branch",
|
||||||
"branch(es) to track", opt_parse_track),
|
"branch(es) to track"),
|
||||||
OPT_STRING('m', "master", &master, "branch", "master branch"),
|
OPT_STRING('m', "master", &master, "branch", "master branch"),
|
||||||
{ OPTION_CALLBACK, 0, "mirror", &mirror, "push|fetch",
|
{ OPTION_CALLBACK, 0, "mirror", &mirror, "push|fetch",
|
||||||
"set up remote as a mirror to push to or fetch from",
|
"set up remote as a mirror to push to or fetch from",
|
||||||
|
|
2
cache.h
2
cache.h
|
@ -1082,6 +1082,8 @@ extern int config_error_nonbool(const char *);
|
||||||
extern const char *get_log_output_encoding(void);
|
extern const char *get_log_output_encoding(void);
|
||||||
extern const char *get_commit_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;
|
extern const char *config_exclusive_filename;
|
||||||
|
|
||||||
#define MAX_GITNAME (1000)
|
#define MAX_GITNAME (1000)
|
||||||
|
|
4
config.c
4
config.c
|
@ -47,8 +47,8 @@ void git_config_push_parameter(const char *text)
|
||||||
strbuf_release(&env);
|
strbuf_release(&env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int git_config_parse_parameter(const char *text,
|
int git_config_parse_parameter(const char *text,
|
||||||
config_fn_t fn, void *data)
|
config_fn_t fn, void *data)
|
||||||
{
|
{
|
||||||
struct strbuf **pair;
|
struct strbuf **pair;
|
||||||
pair = strbuf_split_str(text, '=', 2);
|
pair = strbuf_split_str(text, '=', 2);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
#include "string-list.h"
|
||||||
|
|
||||||
static int parse_options_usage(struct parse_opt_ctx_t *ctx,
|
static int parse_options_usage(struct parse_opt_ctx_t *ctx,
|
||||||
const char * const *usagestr,
|
const char * const *usagestr,
|
||||||
|
@ -687,3 +688,19 @@ int parse_options_concat(struct option *dst, size_t dst_size, struct option *src
|
||||||
}
|
}
|
||||||
return -1;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -130,6 +130,9 @@ struct option {
|
||||||
(h), PARSE_OPT_NOARG, NULL, (p) }
|
(h), PARSE_OPT_NOARG, NULL, (p) }
|
||||||
#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), "n", (h) }
|
#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(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, \
|
#define OPT_UYN(s, l, v, h) { OPTION_CALLBACK, (s), (l), (v), NULL, \
|
||||||
(h), PARSE_OPT_NOARG, &parse_opt_tertiary }
|
(h), PARSE_OPT_NOARG, &parse_opt_tertiary }
|
||||||
#define OPT_DATE(s, l, v, h) \
|
#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_verbosity_cb(const struct option *, const char *, int);
|
||||||
extern int parse_opt_with_commit(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_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__VERBOSE(var, h) OPT_BOOLEAN('v', "verbose", (var), (h))
|
||||||
#define OPT__QUIET(var, h) OPT_BOOLEAN('q', "quiet", (var), (h))
|
#define OPT__QUIET(var, h) OPT_BOOLEAN('q', "quiet", (var), (h))
|
||||||
|
|
|
@ -28,6 +28,7 @@ String options
|
||||||
--st <st> get another string (pervert ordering)
|
--st <st> get another string (pervert ordering)
|
||||||
-o <str> get another string
|
-o <str> get another string
|
||||||
--default-string set string to default
|
--default-string set string to default
|
||||||
|
--list <str> add str to list
|
||||||
|
|
||||||
Magic arguments
|
Magic arguments
|
||||||
--quux means --quux
|
--quux means --quux
|
||||||
|
@ -337,4 +338,20 @@ test_expect_success 'negation of OPT_NONEG flags is not ambiguous' '
|
||||||
test_cmp expect output
|
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
|
test_done
|
||||||
|
|
|
@ -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
|
|
@ -1,5 +1,6 @@
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "parse-options.h"
|
#include "parse-options.h"
|
||||||
|
#include "string-list.h"
|
||||||
|
|
||||||
static int boolean = 0;
|
static int boolean = 0;
|
||||||
static int integer = 0;
|
static int integer = 0;
|
||||||
|
@ -9,6 +10,7 @@ static int verbose = 0, dry_run = 0, quiet = 0;
|
||||||
static char *string = NULL;
|
static char *string = NULL;
|
||||||
static char *file = NULL;
|
static char *file = NULL;
|
||||||
static int ambiguous;
|
static int ambiguous;
|
||||||
|
static struct string_list list;
|
||||||
|
|
||||||
static int length_callback(const struct option *opt, const char *arg, int unset)
|
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_STRING('o', NULL, &string, "str", "get another string"),
|
||||||
OPT_SET_PTR(0, "default-string", &string,
|
OPT_SET_PTR(0, "default-string", &string,
|
||||||
"set string to default", (unsigned long)"default"),
|
"set string to default", (unsigned long)"default"),
|
||||||
|
OPT_STRING_LIST(0, "list", &list, "str", "add str to list"),
|
||||||
OPT_GROUP("Magic arguments"),
|
OPT_GROUP("Magic arguments"),
|
||||||
OPT_ARGUMENT("quux", "means --quux"),
|
OPT_ARGUMENT("quux", "means --quux"),
|
||||||
OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
|
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("dry run: %s\n", dry_run ? "yes" : "no");
|
||||||
printf("file: %s\n", file ? file : "(not set)");
|
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++)
|
for (i = 0; i < argc; i++)
|
||||||
printf("arg %02d: %s\n", i, argv[i]);
|
printf("arg %02d: %s\n", i, argv[i]);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче