Re: [PATCHv8] clone --single: limit the fetch refspec to fetched branch

2012-09-20 Thread Junio C Hamano
Thanks.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv8] clone --single: limit the fetch refspec to fetched branch

2012-09-20 Thread Ralf Thielow
After running "git clone --single", the resulting repository has the
usual default "+refs/heads/*:refs/remotes/origin/*" wildcard fetch
refspec installed, which means that a subsequent "git fetch" will
end up grabbing all the other branches.

Update the fetch refspec to cover only the singly cloned ref instead
to correct this.

That means:
If "--single" is used without "--branch" or "--mirror", the
fetch refspec covers the branch on which remote's HEAD points to.
If "--single" is used with "--branch", it'll cover only the branch
specified in the "--branch" option.
If "--single" is combined with "--mirror", then it'll cover all
refs of the cloned repository.
If "--single" is used with "--branch" that specifies a tag, then
it'll cover only the ref for this tag.

Signed-off-by: Ralf Thielow 
---

changes in v8:
- remove unnecessary strbuf_reset
- remove test from v7 which has shown that tags get fetched when cloning
- add test to show that tags will not being updated when using simple "git 
clone"
- change position of the tag in the setup, not directly in the test

 Documentation/git-clone.txt |  15 +++--
 builtin/clone.c |  65 ++
 t/t5709-clone-refspec.sh| 156 
 3 Dateien geändert, 218 Zeilen hinzugefügt(+), 18 Zeilen entfernt(-)
 create mode 100755 t/t5709-clone-refspec.sh

diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index c1ddd4c..6d98ef3 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -29,7 +29,8 @@ currently active branch.
 After the clone, a plain `git fetch` without arguments will update
 all the remote-tracking branches, and a `git pull` without
 arguments will in addition merge the remote master branch into the
-current master branch, if any.
+current master branch, if any (this is untrue when "--single-branch"
+is given; see below).
 
 This default configuration is achieved by creating references to
 the remote branch heads under `refs/remotes/origin` and
@@ -152,9 +153,10 @@ objects from the source repository into a pack in the 
cloned repository.
 -b ::
Instead of pointing the newly created HEAD to the branch pointed
to by the cloned repository's HEAD, point to `` branch
-   instead. `--branch` can also take tags and treat them like
-   detached HEAD. In a non-bare repository, this is the branch
-   that will be checked out.
+   instead. In a non-bare repository, this is the branch that will
+   be checked out.
+   `--branch` can also take tags and detaches the HEAD at that commit
+   in the resulting repository.
 
 --upload-pack ::
 -u ::
@@ -193,6 +195,11 @@ objects from the source repository into a pack in the 
cloned repository.
clone with the `--depth` option, this is the default, unless
`--no-single-branch` is given to fetch the histories near the
tips of all branches.
+   Further fetches into the resulting repository will only update the
+   remote tracking branch for the branch this option was used for the
+   initial cloning.  If the HEAD at the remote did not point at any
+   branch when `--single-branch` clone was made, no remote tracking
+   branch is created.
 
 --recursive::
 --recurse-submodules::
diff --git a/builtin/clone.c b/builtin/clone.c
index 5e8f3ba..047239c 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -610,6 +610,54 @@ static void write_config(struct string_list *config)
}
 }
 
+static void write_refspec_config(const char* src_ref_prefix,
+   const struct ref* our_head_points_at,
+   const struct ref* remote_head_points_at, struct strbuf* 
branch_top)
+{
+   struct strbuf key = STRBUF_INIT;
+   struct strbuf value = STRBUF_INIT;
+
+   if (option_mirror || !option_bare) {
+   if (option_single_branch && !option_mirror) {
+   if (option_branch) {
+   if (strstr(our_head_points_at->name, 
"refs/tags/"))
+   strbuf_addf(&value, "+%s:%s", 
our_head_points_at->name,
+   our_head_points_at->name);
+   else
+   strbuf_addf(&value, "+%s:%s%s", 
our_head_points_at->name,
+   branch_top->buf, option_branch);
+   } else if (remote_head_points_at) {
+   strbuf_addf(&value, "+%s:%s%s", 
remote_head_points_at->name,
+   branch_top->buf,
+   
skip_prefix(remote_head_points_at->name, "refs/heads/"));
+   }
+   /*
+* otherwise, the next "git fetch" will
+* simply fetch from HEAD without updating
+* any remote tracking branch, which is w