2005-07-04 20:26:53 +00:00
|
|
|
#include "cache.h"
|
2005-07-04 22:29:17 +00:00
|
|
|
#include "refs.h"
|
2005-07-04 20:26:53 +00:00
|
|
|
#include "pkt-line.h"
|
2005-10-19 21:27:02 +00:00
|
|
|
#include "commit.h"
|
|
|
|
#include "tag.h"
|
|
|
|
#include <time.h>
|
2005-07-04 23:35:13 +00:00
|
|
|
#include <sys/wait.h>
|
2005-07-04 20:26:53 +00:00
|
|
|
|
2005-07-14 07:08:37 +00:00
|
|
|
static int quiet;
|
2005-08-12 09:08:29 +00:00
|
|
|
static int verbose;
|
|
|
|
static const char fetch_pack_usage[] =
|
|
|
|
"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
|
2005-07-04 20:26:53 +00:00
|
|
|
static const char *exec = "git-upload-pack";
|
|
|
|
|
2005-10-19 23:14:34 +00:00
|
|
|
#define COMPLETE (1U << 0)
|
|
|
|
|
2005-08-12 09:08:29 +00:00
|
|
|
static int find_common(int fd[2], unsigned char *result_sha1,
|
|
|
|
struct ref *refs)
|
2005-07-04 20:26:53 +00:00
|
|
|
{
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
int fetching;
|
2005-07-04 20:26:53 +00:00
|
|
|
static char line[1000];
|
2005-10-19 23:14:34 +00:00
|
|
|
static char rev_command[1024];
|
|
|
|
int count = 0, flushes = 0, retval, rev_command_len;
|
2005-07-04 23:35:13 +00:00
|
|
|
FILE *revs;
|
2005-07-04 20:26:53 +00:00
|
|
|
|
2005-10-19 23:14:34 +00:00
|
|
|
strcpy(rev_command, "git-rev-list $(git-rev-parse --all)");
|
|
|
|
rev_command_len = strlen(rev_command);
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
fetching = 0;
|
|
|
|
for ( ; refs ; refs = refs->next) {
|
2005-08-12 09:08:29 +00:00
|
|
|
unsigned char *remote = refs->old_sha1;
|
2005-10-20 01:28:17 +00:00
|
|
|
struct object *o;
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
|
2005-10-19 23:14:34 +00:00
|
|
|
/*
|
2005-10-20 01:28:17 +00:00
|
|
|
* If that object is complete (i.e. it is an ancestor of a
|
|
|
|
* local ref), we tell them we have it but do not have to
|
|
|
|
* tell them about its ancestors, which they already know
|
|
|
|
* about.
|
|
|
|
*/
|
|
|
|
if (has_sha1_file(remote) &&
|
|
|
|
((o = parse_object(remote)) != NULL) &&
|
|
|
|
(o->flags & COMPLETE)) {
|
|
|
|
struct commit_list *p;
|
|
|
|
struct commit *commit =
|
|
|
|
(struct commit *) (o = deref_tag(o));
|
|
|
|
if (!o)
|
|
|
|
goto repair;
|
|
|
|
if (o->type != commit_type)
|
|
|
|
continue;
|
|
|
|
p = commit->parents;
|
|
|
|
while (p &&
|
|
|
|
rev_command_len + 44 < sizeof(rev_command)) {
|
2005-10-19 23:14:34 +00:00
|
|
|
snprintf(rev_command + rev_command_len, 44,
|
2005-10-20 01:28:17 +00:00
|
|
|
" ^%s",
|
|
|
|
sha1_to_hex(p->item->object.sha1));
|
2005-10-19 23:14:34 +00:00
|
|
|
rev_command_len += 43;
|
2005-10-20 01:28:17 +00:00
|
|
|
p = p->next;
|
2005-10-19 23:14:34 +00:00
|
|
|
}
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
continue;
|
2005-10-19 23:14:34 +00:00
|
|
|
}
|
2005-10-20 01:28:17 +00:00
|
|
|
repair:
|
2005-08-12 09:08:29 +00:00
|
|
|
packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
fetching++;
|
2005-08-12 09:08:29 +00:00
|
|
|
}
|
2005-07-04 22:29:17 +00:00
|
|
|
packet_flush(fd[1]);
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
if (!fetching)
|
|
|
|
return 1;
|
2005-10-19 23:14:34 +00:00
|
|
|
|
|
|
|
revs = popen(rev_command, "r");
|
|
|
|
if (!revs)
|
|
|
|
die("unable to run 'git-rev-list'");
|
|
|
|
|
2005-07-04 23:35:13 +00:00
|
|
|
flushes = 1;
|
|
|
|
retval = -1;
|
|
|
|
while (fgets(line, sizeof(line), revs) != NULL) {
|
2005-07-04 20:26:53 +00:00
|
|
|
unsigned char sha1[20];
|
|
|
|
if (get_sha1_hex(line, sha1))
|
|
|
|
die("git-fetch-pack: expected object name, got crud");
|
|
|
|
packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
|
2005-08-12 09:08:29 +00:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
|
2005-07-04 20:26:53 +00:00
|
|
|
if (!(31 & ++count)) {
|
|
|
|
packet_flush(fd[1]);
|
|
|
|
flushes++;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We keep one window "ahead" of the other side, and
|
|
|
|
* will wait for an ACK only on the next one
|
|
|
|
*/
|
|
|
|
if (count == 32)
|
|
|
|
continue;
|
2005-07-04 23:35:13 +00:00
|
|
|
if (get_ack(fd[0], result_sha1)) {
|
|
|
|
flushes = 0;
|
|
|
|
retval = 0;
|
2005-08-12 09:08:29 +00:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "got ack\n");
|
2005-07-04 23:35:13 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-07-04 20:26:53 +00:00
|
|
|
flushes--;
|
|
|
|
}
|
|
|
|
}
|
2005-07-04 23:35:13 +00:00
|
|
|
pclose(revs);
|
|
|
|
packet_write(fd[1], "done\n");
|
2005-08-12 09:08:29 +00:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "done\n");
|
2005-07-04 20:26:53 +00:00
|
|
|
while (flushes) {
|
|
|
|
flushes--;
|
2005-08-12 09:08:29 +00:00
|
|
|
if (get_ack(fd[0], result_sha1)) {
|
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "got ack\n");
|
2005-07-04 20:26:53 +00:00
|
|
|
return 0;
|
2005-08-12 09:08:29 +00:00
|
|
|
}
|
2005-07-04 20:26:53 +00:00
|
|
|
}
|
2005-07-04 23:35:13 +00:00
|
|
|
return retval;
|
2005-07-04 20:26:53 +00:00
|
|
|
}
|
|
|
|
|
2005-10-19 21:27:02 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
static int everything_local(struct ref *refs)
|
|
|
|
{
|
2005-10-19 21:27:02 +00:00
|
|
|
struct ref *ref;
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
int retval;
|
2005-10-19 21:27:02 +00:00
|
|
|
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);
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
|
|
|
|
for (retval = 1; refs ; refs = refs->next) {
|
|
|
|
const unsigned char *remote = refs->old_sha1;
|
|
|
|
unsigned char local[20];
|
2005-10-19 21:27:02 +00:00
|
|
|
struct object *o;
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
|
2005-10-19 21:27:02 +00:00
|
|
|
o = parse_object(remote);
|
|
|
|
if (!o || !(o->flags & COMPLETE)) {
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
retval = 0;
|
|
|
|
if (!verbose)
|
|
|
|
continue;
|
|
|
|
fprintf(stderr,
|
|
|
|
"want %s (%s)\n", sha1_to_hex(remote),
|
|
|
|
refs->name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(refs->new_sha1, local, 20);
|
|
|
|
if (!verbose)
|
|
|
|
continue;
|
|
|
|
fprintf(stderr,
|
|
|
|
"already have %s (%s)\n", sha1_to_hex(remote),
|
|
|
|
refs->name);
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2005-07-04 20:26:53 +00:00
|
|
|
static int fetch_pack(int fd[2], int nr_match, char **match)
|
|
|
|
{
|
2005-07-16 20:55:50 +00:00
|
|
|
struct ref *ref;
|
|
|
|
unsigned char sha1[20];
|
|
|
|
int status;
|
2005-07-04 23:35:13 +00:00
|
|
|
pid_t pid;
|
2005-07-04 20:26:53 +00:00
|
|
|
|
2005-10-14 01:57:40 +00:00
|
|
|
get_remote_heads(fd[0], &ref, nr_match, match, 1);
|
2005-07-16 20:55:50 +00:00
|
|
|
if (!ref) {
|
|
|
|
packet_flush(fd[1]);
|
|
|
|
die("no matching remote head");
|
|
|
|
}
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
if (everything_local(ref)) {
|
|
|
|
packet_flush(fd[1]);
|
|
|
|
goto all_done;
|
|
|
|
}
|
2005-08-12 09:08:29 +00:00
|
|
|
if (find_common(fd, sha1, ref) < 0)
|
|
|
|
fprintf(stderr, "warning: no common commits\n");
|
2005-07-04 23:35:13 +00:00
|
|
|
pid = fork();
|
|
|
|
if (pid < 0)
|
|
|
|
die("git-fetch-pack: unable to fork off git-unpack-objects");
|
|
|
|
if (!pid) {
|
|
|
|
dup2(fd[0], 0);
|
|
|
|
close(fd[0]);
|
2005-07-14 02:40:06 +00:00
|
|
|
close(fd[1]);
|
2005-07-14 07:08:37 +00:00
|
|
|
execlp("git-unpack-objects", "git-unpack-objects",
|
|
|
|
quiet ? "-q" : NULL, NULL);
|
2005-07-04 23:35:13 +00:00
|
|
|
die("git-unpack-objects exec failed");
|
|
|
|
}
|
2005-07-04 22:29:17 +00:00
|
|
|
close(fd[0]);
|
2005-07-04 23:35:13 +00:00
|
|
|
close(fd[1]);
|
|
|
|
while (waitpid(pid, &status, 0) < 0) {
|
|
|
|
if (errno != EINTR)
|
|
|
|
die("waiting for git-unpack-objects: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
if (WIFEXITED(status)) {
|
|
|
|
int code = WEXITSTATUS(status);
|
|
|
|
if (code)
|
|
|
|
die("git-unpack-objects died with error code %d", code);
|
git-fetch-pack: avoid unnecessary zero packing
If everything is up-to-date locally, we don't need to even ask for a
pack-file from the remote, or try to unpack it.
This is especially important for tags - since the pack-file common commit
logic is based purely on the commit history, it will never be able to find
a common tag, and will thus always end up re-fetching them.
Especially notably, if the tag points to a non-commit (eg a tagged tree),
the pack-file would be unnecessarily big, just because it cannot any most
recent common point between commits for pruning.
Short-circuiting the case where we already have that reference means that
we avoid a lot of these in the common case.
NOTE! This only matches remote ref names against the same local name,
which works well for tags, but is not as generic as it could be. If we
ever need to, we could match against _any_ local ref (if we have it, we
have it), but this "match against same name" is simpler and more
efficient, and covers the common case.
Renaming of refs is common for branch heads, but since those are always
commits, the pack-file generation can optimize that case.
In some cases we might still end up fetching pack-files unnecessarily, but
this at least avoids the re-fetching of tags over and over if you use a
regular
git fetch --tags ...
which was the main reason behind the change.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-18 18:35:17 +00:00
|
|
|
all_done:
|
2005-08-12 09:08:29 +00:00
|
|
|
while (ref) {
|
|
|
|
printf("%s %s\n",
|
|
|
|
sha1_to_hex(ref->old_sha1), ref->name);
|
|
|
|
ref = ref->next;
|
|
|
|
}
|
2005-07-04 23:35:13 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (WIFSIGNALED(status)) {
|
|
|
|
int sig = WTERMSIG(status);
|
|
|
|
die("git-unpack-objects died of signal %d", sig);
|
|
|
|
}
|
|
|
|
die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
|
2005-07-04 20:26:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int i, ret, nr_heads;
|
|
|
|
char *dest = NULL, **heads;
|
|
|
|
int fd[2];
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
nr_heads = 0;
|
|
|
|
heads = NULL;
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
char *arg = argv[i];
|
|
|
|
|
|
|
|
if (*arg == '-') {
|
2005-07-14 07:08:37 +00:00
|
|
|
if (!strncmp("--exec=", arg, 7)) {
|
|
|
|
exec = arg + 7;
|
|
|
|
continue;
|
|
|
|
}
|
2005-08-12 09:08:29 +00:00
|
|
|
if (!strcmp("-q", arg)) {
|
|
|
|
quiet = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!strcmp("-v", arg)) {
|
|
|
|
verbose = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2005-07-04 20:26:53 +00:00
|
|
|
usage(fetch_pack_usage);
|
|
|
|
}
|
|
|
|
dest = arg;
|
|
|
|
heads = argv + i + 1;
|
|
|
|
nr_heads = argc - i - 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!dest)
|
|
|
|
usage(fetch_pack_usage);
|
|
|
|
pid = git_connect(fd, dest, exec);
|
|
|
|
if (pid < 0)
|
|
|
|
return 1;
|
|
|
|
ret = fetch_pack(fd, nr_heads, heads);
|
|
|
|
close(fd[0]);
|
|
|
|
close(fd[1]);
|
|
|
|
finish_connect(pid);
|
|
|
|
return ret;
|
|
|
|
}
|