summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <junkio@cox.net>2005-10-18 18:42:19 -0700
committerLibravatar Junio C Hamano <junkio@cox.net>2005-10-18 18:42:19 -0700
commitea5a65a59916503d2a14369c46b1023384d51645 (patch)
tree6cd6c03b2aed8908fe56a10d1366bd040dc7ead5
parentEven when overwriting tags, report if they are changed or not. (diff)
downloadtgif-ea5a65a59916503d2a14369c46b1023384d51645.tar.xz
Do not ask for objects known to be complete.
On top of optimization by Linus not to ask refs that already match, we can walk our refs and not issue "want" for things that are known to be reachable from them. Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r--fetch-pack.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/fetch-pack.c b/fetch-pack.c
index 459736909c..969e72a781 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1,6 +1,9 @@
#include "cache.h"
#include "refs.h"
#include "pkt-line.h"
+#include "commit.h"
+#include "tag.h"
+#include <time.h>
#include <sys/wait.h>
static int quiet;
@@ -78,16 +81,73 @@ static int find_common(int fd[2], unsigned char *result_sha1,
return retval;
}
+#define COMPLETE (1U << 0)
+static struct commit_list *complete = NULL;
+
+static int mark_complete(const char *path, const unsigned char *sha1)
+{
+ struct object *o = parse_object(sha1);
+
+ while (o && o->type == tag_type) {
+ o->flags |= COMPLETE;
+ o = parse_object(((struct tag *)o)->tagged->sha1);
+ }
+ if (o->type == commit_type) {
+ struct commit *commit = (struct commit *)o;
+ commit->object.flags |= COMPLETE;
+ insert_by_date(commit, &complete);
+ }
+ return 0;
+}
+
+static void mark_recent_complete_commits(unsigned long cutoff)
+{
+ while (complete && cutoff <= complete->item->date) {
+ if (verbose)
+ fprintf(stderr, "Marking %s as complete\n",
+ sha1_to_hex(complete->item->object.sha1));
+ pop_most_recent_commit(&complete, COMPLETE);
+ }
+}
+
static int everything_local(struct ref *refs)
{
+ struct ref *ref;
int retval;
+ unsigned long cutoff = 0;
+
+ track_object_refs = 0;
+ save_commit_buffer = 0;
+
+ for (ref = refs; ref; ref = ref->next) {
+ struct object *o;
+
+ o = parse_object(ref->old_sha1);
+ if (!o)
+ continue;
+
+ /* We already have it -- which may mean that we were
+ * in sync with the other side at some time after
+ * that (it is OK if we guess wrong here).
+ */
+ if (o->type == commit_type) {
+ struct commit *commit = (struct commit *)o;
+ if (!cutoff || cutoff < commit->date)
+ cutoff = commit->date;
+ }
+ }
+
+ for_each_ref(mark_complete);
+ if (cutoff)
+ mark_recent_complete_commits(cutoff);
for (retval = 1; refs ; refs = refs->next) {
const unsigned char *remote = refs->old_sha1;
unsigned char local[20];
+ struct object *o;
- if (read_ref(git_path("%s", refs->name), local) < 0 ||
- memcmp(remote, local, 20)) {
+ o = parse_object(remote);
+ if (!o || !(o->flags & COMPLETE)) {
retval = 0;
if (!verbose)
continue;