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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.