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
next prev 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).