fetch-pack: start multi-head pulling.
This is a beginning of resurrecting the multi-head pulling support for git-fetch-pack command. The git-fetch-script wrapper still only knows about fetching a single head, without renaming, so it is not very useful unless you directly call git-fetch-pack itself yet. It also fixes a longstanding obsolete description of how the command discovers the list of local commits.
This commit is contained in:
@ -9,19 +9,19 @@ git-fetch-pack - Receive missing objects from another repository.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
git-fetch-pack [-q] [--exec=<git-upload-pack>] [<host>:]<directory> [<head>...] < <commit-list>
|
git-fetch-pack [-q] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Invokes 'git-upload-pack' on a potentially remote repository,
|
Invokes 'git-upload-pack' on a potentially remote repository,
|
||||||
and asks it to send objects missing from this repository, to
|
and asks it to send objects missing from this repository, to
|
||||||
update the named heads. The list of commits available locally
|
update the named heads. The list of commits available locally
|
||||||
is fed from the standard input, to be sent to 'git-upload-pack'
|
is found out by scanning local $GIT_DIR/refs/ and sent to
|
||||||
running on the other end.
|
'git-upload-pack' running on the other end.
|
||||||
|
|
||||||
This command can be used only when the local side has a common
|
This command degenerates to download everything to complete the
|
||||||
(ancestor) commit with the remote head that is being pulled
|
asked refs from the remote side when the local side does not
|
||||||
from. Use 'git-clone-pack' for that.
|
have a common ancestor commit.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
@ -50,15 +50,11 @@ OPTIONS
|
|||||||
<directory>::
|
<directory>::
|
||||||
The repository to sync from.
|
The repository to sync from.
|
||||||
|
|
||||||
<head>...::
|
<refs>...::
|
||||||
The remote heads to update from. This is relative to
|
The remote heads to update from. This is relative to
|
||||||
$GIT_DIR (e.g. "HEAD", "refs/heads/master"). When
|
$GIT_DIR (e.g. "HEAD", "refs/heads/master"). When
|
||||||
unspecified, update from all heads the remote side has.
|
unspecified, update from all heads the remote side has.
|
||||||
|
|
||||||
However the program refuses to work if more than one
|
|
||||||
remote head matches the specified heads. I am not sure
|
|
||||||
what this means... Help!!!!!
|
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
56
fetch-pack.c
56
fetch-pack.c
@ -4,10 +4,13 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
static int quiet;
|
static int quiet;
|
||||||
static const char fetch_pack_usage[] = "git-fetch-pack [-q] [--exec=upload-pack] [host:]directory [heads]* < mycommitlist";
|
static int verbose;
|
||||||
|
static const char fetch_pack_usage[] =
|
||||||
|
"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
|
||||||
static const char *exec = "git-upload-pack";
|
static const char *exec = "git-upload-pack";
|
||||||
|
|
||||||
static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *remote)
|
static int find_common(int fd[2], unsigned char *result_sha1,
|
||||||
|
struct ref *refs)
|
||||||
{
|
{
|
||||||
static char line[1000];
|
static char line[1000];
|
||||||
int count = 0, flushes = 0, retval;
|
int count = 0, flushes = 0, retval;
|
||||||
@ -16,7 +19,16 @@ static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *rem
|
|||||||
revs = popen("git-rev-list $(git-rev-parse --all)", "r");
|
revs = popen("git-rev-list $(git-rev-parse --all)", "r");
|
||||||
if (!revs)
|
if (!revs)
|
||||||
die("unable to run 'git-rev-list'");
|
die("unable to run 'git-rev-list'");
|
||||||
packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
|
|
||||||
|
while (refs) {
|
||||||
|
unsigned char *remote = refs->old_sha1;
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr,
|
||||||
|
"want %s (%s)\n", sha1_to_hex(remote),
|
||||||
|
refs->name);
|
||||||
|
packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
|
||||||
|
refs = refs->next;
|
||||||
|
}
|
||||||
packet_flush(fd[1]);
|
packet_flush(fd[1]);
|
||||||
flushes = 1;
|
flushes = 1;
|
||||||
retval = -1;
|
retval = -1;
|
||||||
@ -25,6 +37,8 @@ static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *rem
|
|||||||
if (get_sha1_hex(line, sha1))
|
if (get_sha1_hex(line, sha1))
|
||||||
die("git-fetch-pack: expected object name, got crud");
|
die("git-fetch-pack: expected object name, got crud");
|
||||||
packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
|
packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
|
||||||
if (!(31 & ++count)) {
|
if (!(31 & ++count)) {
|
||||||
packet_flush(fd[1]);
|
packet_flush(fd[1]);
|
||||||
flushes++;
|
flushes++;
|
||||||
@ -38,6 +52,8 @@ static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *rem
|
|||||||
if (get_ack(fd[0], result_sha1)) {
|
if (get_ack(fd[0], result_sha1)) {
|
||||||
flushes = 0;
|
flushes = 0;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "got ack\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
flushes--;
|
flushes--;
|
||||||
@ -45,19 +61,19 @@ static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *rem
|
|||||||
}
|
}
|
||||||
pclose(revs);
|
pclose(revs);
|
||||||
packet_write(fd[1], "done\n");
|
packet_write(fd[1], "done\n");
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "done\n");
|
||||||
while (flushes) {
|
while (flushes) {
|
||||||
flushes--;
|
flushes--;
|
||||||
if (get_ack(fd[0], result_sha1))
|
if (get_ack(fd[0], result_sha1)) {
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "got ack\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Eventually we'll want to be able to fetch multiple heads.
|
|
||||||
*
|
|
||||||
* Right now we'll just require a single match.
|
|
||||||
*/
|
|
||||||
static int fetch_pack(int fd[2], int nr_match, char **match)
|
static int fetch_pack(int fd[2], int nr_match, char **match)
|
||||||
{
|
{
|
||||||
struct ref *ref;
|
struct ref *ref;
|
||||||
@ -70,12 +86,8 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
|
|||||||
packet_flush(fd[1]);
|
packet_flush(fd[1]);
|
||||||
die("no matching remote head");
|
die("no matching remote head");
|
||||||
}
|
}
|
||||||
if (ref->next) {
|
if (find_common(fd, sha1, ref) < 0)
|
||||||
packet_flush(fd[1]);
|
fprintf(stderr, "warning: no common commits\n");
|
||||||
die("multiple remote heads");
|
|
||||||
}
|
|
||||||
if (find_common(fd, sha1, ref->old_sha1) < 0)
|
|
||||||
die("git-fetch-pack: no common commits");
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
die("git-fetch-pack: unable to fork off git-unpack-objects");
|
die("git-fetch-pack: unable to fork off git-unpack-objects");
|
||||||
@ -97,7 +109,11 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
|
|||||||
int code = WEXITSTATUS(status);
|
int code = WEXITSTATUS(status);
|
||||||
if (code)
|
if (code)
|
||||||
die("git-unpack-objects died with error code %d", code);
|
die("git-unpack-objects died with error code %d", code);
|
||||||
puts(sha1_to_hex(ref->old_sha1));
|
while (ref) {
|
||||||
|
printf("%s %s\n",
|
||||||
|
sha1_to_hex(ref->old_sha1), ref->name);
|
||||||
|
ref = ref->next;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (WIFSIGNALED(status)) {
|
if (WIFSIGNALED(status)) {
|
||||||
@ -124,6 +140,14 @@ int main(int argc, char **argv)
|
|||||||
exec = arg + 7;
|
exec = arg + 7;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp("-q", arg)) {
|
||||||
|
quiet = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp("-v", arg)) {
|
||||||
|
verbose = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
usage(fetch_pack_usage);
|
usage(fetch_pack_usage);
|
||||||
}
|
}
|
||||||
dest = arg;
|
dest = arg;
|
||||||
|
@ -31,6 +31,10 @@ rsync://*)
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
head=$(git-fetch-pack "$merge_repo" "$merge_head")
|
head=$(git-fetch-pack "$merge_repo" "$merge_head")
|
||||||
|
if h=`expr "$head" : '\([^ ][^ ]*\) '`
|
||||||
|
then
|
||||||
|
head=$h
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
esac || exit 1
|
esac || exit 1
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user