summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2013-07-15 10:28:31 -0700
committerJunio C Hamano <gitster@pobox.com>2013-07-15 10:28:31 -0700
commitdd28abca6ab1b8c4b55fdcadeaae092fc897c063 (patch)
tree3efdc0ebaf8dc3f8b4c8ff744c5396499600c4b3
parent0da7a53a76b48ea1b2ee6ebe7bd7fbcd7d5c3f9d (diff)
parent099327b55275ddad678c27c7501e1babed078aef (diff)
downloadgit-dd28abca6ab1b8c4b55fdcadeaae092fc897c063.tar.gz
Merge branch 'jk/fetch-pack-many-refs'
Fetching between repositories with many refs employed O(n^2) algorithm to match up the common objects, which has been corrected. * jk/fetch-pack-many-refs: fetch-pack: avoid quadratic behavior in rev_list_push commit.c: make compare_commits_by_commit_date global fetch-pack: avoid quadratic list insertion in mark_complete
-rw-r--r--commit.c2
-rw-r--r--commit.h2
-rw-r--r--fetch-pack.c16
3 files changed, 11 insertions, 9 deletions
diff --git a/commit.c b/commit.c
index 521e49c309..ebc0eeab8f 100644
--- a/commit.c
+++ b/commit.c
@@ -581,7 +581,7 @@ static int compare_commits_by_author_date(const void *a_, const void *b_,
return 0;
}
-static int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused)
+int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused)
{
const struct commit *a = a_, *b = b_;
/* newer commits with larger date first */
diff --git a/commit.h b/commit.h
index 4d452dc96d..18a523495e 100644
--- a/commit.h
+++ b/commit.h
@@ -254,4 +254,6 @@ extern void print_commit_list(struct commit_list *list,
*/
extern void check_commit_signature(const struct commit* commit, struct signature_check *sigc);
+int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
+
#endif /* COMMIT_H */
diff --git a/fetch-pack.c b/fetch-pack.c
index abe5ffbba5..6684348c0e 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -11,6 +11,7 @@
#include "run-command.h"
#include "transport.h"
#include "version.h"
+#include "prio-queue.h"
static int transfer_unpack_limit = -1;
static int fetch_unpack_limit = -1;
@@ -37,7 +38,7 @@ static int marked;
*/
#define MAX_IN_VAIN 256
-static struct commit_list *rev_list;
+static struct prio_queue rev_list = { compare_commits_by_commit_date };
static int non_common_revs, multi_ack, use_sideband, allow_tip_sha1_in_want;
static void rev_list_push(struct commit *commit, int mark)
@@ -49,7 +50,7 @@ static void rev_list_push(struct commit *commit, int mark)
if (parse_commit(commit))
return;
- commit_list_insert_by_date(commit, &rev_list);
+ prio_queue_put(&rev_list, commit);
if (!(commit->object.flags & COMMON))
non_common_revs++;
@@ -122,10 +123,10 @@ static const unsigned char *get_rev(void)
unsigned int mark;
struct commit_list *parents;
- if (rev_list == NULL || non_common_revs == 0)
+ if (rev_list.nr == 0 || non_common_revs == 0)
return NULL;
- commit = rev_list->item;
+ commit = prio_queue_get(&rev_list);
if (!commit->object.parsed)
parse_commit(commit);
parents = commit->parents;
@@ -152,8 +153,6 @@ static const unsigned char *get_rev(void)
mark_common(parents->item, 1, 0);
parents = parents->next;
}
-
- rev_list = rev_list->next;
}
return commit->object.sha1;
@@ -442,7 +441,7 @@ static int find_common(struct fetch_pack_args *args,
in_vain = 0;
got_continue = 1;
if (ack == ACK_ready) {
- rev_list = NULL;
+ clear_prio_queue(&rev_list);
got_ready = 1;
}
break;
@@ -505,7 +504,7 @@ static int mark_complete(const char *refname, const unsigned char *sha1, int fla
struct commit *commit = (struct commit *)o;
if (!(commit->object.flags & COMPLETE)) {
commit->object.flags |= COMPLETE;
- commit_list_insert_by_date(commit, &complete);
+ commit_list_insert(commit, &complete);
}
}
return 0;
@@ -622,6 +621,7 @@ static int everything_local(struct fetch_pack_args *args,
if (!args->depth) {
for_each_ref(mark_complete, NULL);
for_each_alternate_ref(mark_alternate_complete, NULL);
+ commit_list_sort_by_date(&complete);
if (cutoff)
mark_recent_complete_commits(args, cutoff);
}