summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pitre <nico@fluxnic.net>2009-09-26 03:54:42 (GMT)
committerShawn O. Pearce <spearce@spearce.org>2009-09-26 19:51:04 (GMT)
commit5bdc32d3e50d8335c65e136e6b5234c5dd92a7a9 (patch)
tree52f428f14b58a13fc56a6093c5d0fd6b63131ec4
parentfb3650ed100a549f80d822f28ccf0f82e9f75f3e (diff)
downloadgit-5bdc32d3e50d8335c65e136e6b5234c5dd92a7a9.zip
git-5bdc32d3e50d8335c65e136e6b5234c5dd92a7a9.tar.gz
git-5bdc32d3e50d8335c65e136e6b5234c5dd92a7a9.tar.bz2
make 'git clone' ask the remote only for objects it cares about
Current behavior of 'git clone' when not using --mirror is to fetch everything from the peer, and then filter out unwanted refs just before writing them out to the cloned repository. This may become highly inefficient if the peer has an unusual ref namespace, or if it simply has "remotes" refs of its own, and those locally unwanted refs are connecting to a large set of objects which becomes unreferenced as soon as they are fetched. Let's filter out those unwanted refs from the peer _before_ asking it what refs we want to fetch instead, which is the most logical thing to do anyway. Signed-off-by: Nicolas Pitre <nico@fluxnic.net> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
-rw-r--r--builtin-clone.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/builtin-clone.c b/builtin-clone.c
index bab2d84..4992c25 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -329,24 +329,28 @@ static void remove_junk_on_signal(int signo)
raise(signo);
}
-static struct ref *write_remote_refs(const struct ref *refs,
- struct refspec *refspec, const char *reflog)
+static struct ref *wanted_peer_refs(const struct ref *refs,
+ struct refspec *refspec)
{
struct ref *local_refs = NULL;
struct ref **tail = &local_refs;
- struct ref *r;
get_fetch_map(refs, refspec, &tail, 0);
if (!option_mirror)
get_fetch_map(refs, tag_refspec, &tail, 0);
+ return local_refs;
+}
+
+static void write_remote_refs(const struct ref *local_refs)
+{
+ const struct ref *r;
+
for (r = local_refs; r; r = r->next)
add_extra_ref(r->peer_ref->name, r->old_sha1, 0);
pack_refs(PACK_REFS_ALL);
clear_extra_refs();
-
- return local_refs;
}
int cmd_clone(int argc, const char **argv, const char *prefix)
@@ -495,9 +499,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
strbuf_reset(&value);
- if (path && !is_bundle)
+ if (path && !is_bundle) {
refs = clone_local(path, git_dir);
- else {
+ mapped_refs = wanted_peer_refs(refs, refspec);
+ } else {
struct remote *remote = remote_get(argv[0]);
transport = transport_get(remote, remote->url[0]);
@@ -520,14 +525,16 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
option_upload_pack);
refs = transport_get_remote_refs(transport);
- if (refs)
- transport_fetch_refs(transport, refs);
+ if (refs) {
+ mapped_refs = wanted_peer_refs(refs, refspec);
+ transport_fetch_refs(transport, mapped_refs);
+ }
}
if (refs) {
clear_extra_refs();
- mapped_refs = write_remote_refs(refs, refspec, reflog_msg.buf);
+ write_remote_refs(mapped_refs);
remote_head = find_ref_by_name(refs, "HEAD");
remote_head_points_at =