Skip to content

Commit

Permalink
clone: accept config options on the command line
Browse files Browse the repository at this point in the history
Clone does all of init, "remote add", fetch, and checkout
without giving the user a chance to intervene and set any
configuration. This patch allows you to set config options
in the newly created repository after the clone, but before
we do any other operations.

In many cases, this is a minor convenience over something
like:

  git clone git://...
  git config core.whatever true

But in some cases, it can bring extra efficiency by changing
how the fetch or checkout work. For example, setting
line-ending config before the checkout avoids having to
re-checkout all of the contents with the correct line
endings.

It also provides a mechanism for passing information to remote
helpers during a clone; the helpers may read the git config
to influence how they operate.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Jun 22, 2011
1 parent 2496844 commit 84054f7
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
11 changes: 11 additions & 0 deletions Documentation/git-clone.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 20 additions & 1 deletion builtin/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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()
};

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
40 changes: 40 additions & 0 deletions t/t5708-clone-config.sh
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 84054f7

Please sign in to comment.