git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
	"Shawn O. Pearce" <spearce@spearce.org>,
	"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH v2] Limit refs to fetch to minimum in shallow clones
Date: Thu,  5 Jan 2012 13:05:16 +0700	[thread overview]
Message-ID: <1325743516-14940-1-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1325676922-6995-1-git-send-email-pclouds@gmail.com>

The main purpose of shallow clones is to reduce download by only
fetching objects up to a certain depth from the given refs. The number
of objects depends on how many refs to follow. So:

 - Only fetch HEAD or the ref specified by --branch
 - Only fetch tags that point to downloaded objects

More tags/branches can be fetched later using git-fetch as usual.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Only lightly tested, but seems to work. I'll check later if --branch
 works with a tag like Junio's example --single=v3.2

 Documentation/git-clone.txt |   14 ++++++----
 builtin/clone.c             |   54 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 4b8b26b..d69f440 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -172,12 +172,14 @@ objects from the source repository into a pack in the cloned repository.
 
 --depth <depth>::
 	Create a 'shallow' clone with a history truncated to the
-	specified number of revisions.  A shallow repository has a
-	number of limitations (you cannot clone or fetch from
-	it, nor push from nor into it), but is adequate if you
-	are only interested in the recent history of a large project
-	with a long history, and would want to send in fixes
-	as patches.
+	specified number of revisions. Only one branch (either HEAD
+	or specified by --branch) is fetched. Tags that point
+	outside truncated history are not fetched.
++
+A shallow repository has a number of limitations (you cannot clone or
+fetch from it, nor push from nor into it), but is adequate if you are
+only interested in the recent history of a large project with a long
+history, and would want to send in fixes as patches.
 
 --recursive::
 --recurse-submodules::
diff --git a/builtin/clone.c b/builtin/clone.c
index efe8b6c..8de9248 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -48,6 +48,7 @@ static int option_verbosity;
 static int option_progress;
 static struct string_list option_config;
 static struct string_list option_reference;
+static char *src_ref_prefix = "refs/heads/";
 
 static int opt_parse_reference(const struct option *opt, const char *arg, int unset)
 {
@@ -427,9 +428,27 @@ static struct ref *wanted_peer_refs(const struct ref *refs,
 	struct ref *local_refs = head;
 	struct ref **tail = head ? &head->next : &local_refs;
 
-	get_fetch_map(refs, refspec, &tail, 0);
-	if (!option_mirror)
-		get_fetch_map(refs, tag_refspec, &tail, 0);
+	if (option_depth) {
+		struct ref *remote_head = NULL;
+
+		if (!option_branch)
+			remote_head = guess_remote_head(head, refs, 0);
+		else {
+			struct strbuf sb = STRBUF_INIT;
+			strbuf_addstr(&sb, src_ref_prefix);
+			strbuf_addstr(&sb, option_branch);
+			remote_head = find_ref_by_name(refs, sb.buf);
+			strbuf_release(&sb);
+		}
+
+		if (remote_head)
+			get_fetch_map(remote_head, refspec, &tail, 0);
+	}
+	else {
+		get_fetch_map(refs, refspec, &tail, 0);
+		if (!option_mirror)
+			get_fetch_map(refs, tag_refspec, &tail, 0);
+	}
 
 	return local_refs;
 }
@@ -448,6 +467,27 @@ static void write_remote_refs(const struct ref *local_refs)
 	clear_extra_refs();
 }
 
+static void write_followtags(const struct ref *refs)
+{
+	struct ref_lock *lock;
+	const struct ref *ref;
+
+	for (ref = refs; ref; ref = ref->next) {
+		if (prefixcmp(ref->name, "refs/tags"))
+			continue;
+		if (!suffixcmp(ref->name, "^{}"))
+			continue;
+		if (!has_sha1_file(ref->old_sha1))
+			continue;
+
+		lock = lock_any_ref_for_update(ref->name, NULL, 0);
+		if (!lock)
+			die_errno(_("unable to lock %s for writing"), ref->name);
+		if (write_ref_sha1(lock, ref->old_sha1, "storing tag") < 0)
+			die_errno(_("unable to write %s"), ref->name);
+	}
+}
+
 static int write_one_config(const char *key, const char *value, void *data)
 {
 	return git_config_set_multivar(key, value ? value : "true", "^$", 0);
@@ -478,7 +518,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
 	struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
 	struct transport *transport = NULL;
-	char *src_ref_prefix = "refs/heads/";
 	int err = 0;
 
 	struct refspec *refspec;
@@ -642,9 +681,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
 		transport_set_option(transport, TRANS_OPT_KEEP, "yes");
 
-		if (option_depth)
+		if (option_depth) {
 			transport_set_option(transport, TRANS_OPT_DEPTH,
 					     option_depth);
+			transport_set_option(transport, TRANS_OPT_FOLLOWTAGS,
+					     "1");
+		}
 
 		transport_set_verbosity(transport, option_verbosity, option_progress);
 
@@ -663,6 +705,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		clear_extra_refs();
 
 		write_remote_refs(mapped_refs);
+		if (option_depth)
+			write_followtags(refs);
 
 		remote_head = find_ref_by_name(refs, "HEAD");
 		remote_head_points_at =
-- 
1.7.3.1.256.g2539c.dirty

  parent reply	other threads:[~2012-01-05  6:05 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-04 11:35 [PATCH] Do not fetch tags on new shallow clones Nguyễn Thái Ngọc Duy
2012-01-04 15:16 ` Shawn Pearce
2012-01-04 23:59 ` Junio C Hamano
2012-01-05  3:05   ` Shawn Pearce
2012-01-05  5:57     ` Junio C Hamano
2012-01-05 15:16       ` Shawn Pearce
2012-01-05  6:05 ` Nguyễn Thái Ngọc Duy [this message]
2012-01-05 21:25   ` [PATCH v2] Limit refs to fetch to minimum in " Junio C Hamano
2012-01-06  7:11   ` [PATCH v3] " Nguyễn Thái Ngọc Duy
2012-01-06 18:40     ` Junio C Hamano
2012-01-07 14:16       ` Nguyen Thai Ngoc Duy
2012-01-07 14:45     ` [PATCH v4] clone: add --single-branch to fetch only one branch Nguyễn Thái Ngọc Duy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1325743516-14940-1-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=spearce@spearce.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).