summaryrefslogtreecommitdiff
path: root/fetch-pack.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-07-04 23:35:13 (GMT)
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-04 23:35:13 (GMT)
commit75bfc6c232689ae06aba6a7d4aa15ac2791d9a11 (patch)
tree5cbe1763905b2fa0ec6281c8b1003149a1eb72c0 /fetch-pack.c
parentfb9040cc83540fff9d05c8056433a4aa05b8a7c2 (diff)
downloadgit-75bfc6c232689ae06aba6a7d4aa15ac2791d9a11.zip
git-75bfc6c232689ae06aba6a7d4aa15ac2791d9a11.tar.gz
git-75bfc6c232689ae06aba6a7d4aa15ac2791d9a11.tar.bz2
Make git-fetch-pack actually do all the unpacking etc.
It returns the result SHA1 on stdout, so you can do remote=$(git-fetch-pack host:dir branchname) and it will unpack the objects and "remote" will be the SHA1 name of the branch on the other side. You can then save that off, or merge it, or whatever.
Diffstat (limited to 'fetch-pack.c')
-rw-r--r--fetch-pack.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/fetch-pack.c b/fetch-pack.c
index 151c1ff..b8367a4 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "refs.h"
#include "pkt-line.h"
+#include <sys/wait.h>
static const char fetch_pack_usage[] = "git-fetch-pack [host:]directory [heads]* < mycommitlist";
static const char *exec = "git-upload-pack";
@@ -26,11 +27,17 @@ static int get_ack(int fd, unsigned char *result_sha1)
static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *remote)
{
static char line[1000];
- int count = 0, flushes = 0;
+ int count = 0, flushes = 0, retval;
+ FILE *revs;
+ revs = popen("git-rev-list $(git-rev-parse --all)", "r");
+ if (!revs)
+ die("unable to run 'git-rev-list'");
packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
packet_flush(fd[1]);
- while (fgets(line, sizeof(line), stdin) != NULL) {
+ flushes = 1;
+ retval = -1;
+ while (fgets(line, sizeof(line), revs) != NULL) {
unsigned char sha1[20];
if (get_sha1_hex(line, sha1))
die("git-fetch-pack: expected object name, got crud");
@@ -45,19 +52,22 @@ static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *rem
*/
if (count == 32)
continue;
- if (get_ack(fd[0], result_sha1))
- return 0;
+ if (get_ack(fd[0], result_sha1)) {
+ flushes = 0;
+ retval = 0;
+ break;
+ }
flushes--;
}
}
- flushes++;
- packet_flush(fd[1]);
+ pclose(revs);
+ packet_write(fd[1], "done\n");
while (flushes) {
flushes--;
if (get_ack(fd[0], result_sha1))
return 0;
}
- return -1;
+ return retval;
}
static int get_old_sha1(const char *refname, unsigned char *sha1)
@@ -88,12 +98,12 @@ static int check_ref(const char *refname, const unsigned char *sha1)
memset(mysha1, 0, 20);
if (!memcmp(sha1, mysha1, 20)) {
- printf("%s: unchanged\n", refname);
+ fprintf(stderr, "%s: unchanged\n", refname);
return 0;
}
memcpy(oldhex, sha1_to_hex(mysha1), 41);
- printf("%s: %s (%s)\n", refname, sha1_to_hex(sha1), oldhex);
+ fprintf(stderr, "%s: %s (%s)\n", refname, sha1_to_hex(sha1), oldhex);
return 1;
}
@@ -128,7 +138,8 @@ static int get_remote_heads(int fd, int nr_match, char **match, unsigned char *r
static int fetch_pack(int fd[2], int nr_match, char **match)
{
unsigned char sha1[20], remote[20];
- int heads;
+ int heads, status;
+ pid_t pid;
heads = get_remote_heads(fd[0], nr_match, match, remote);
if (heads != 1) {
@@ -137,11 +148,34 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
}
if (find_common(fd, sha1, remote) < 0)
die("git-fetch-pack: no common commits");
- close(fd[1]);
- dup2(fd[0], 0);
+ pid = fork();
+ if (pid < 0)
+ die("git-fetch-pack: unable to fork off git-unpack-objects");
+ if (!pid) {
+ close(fd[1]);
+ dup2(fd[0], 0);
+ close(fd[0]);
+ execlp("git-unpack-objects", "git-unpack-objects", NULL);
+ die("git-unpack-objects exec failed");
+ }
close(fd[0]);
- execlp("git-unpack-objects", "git-unpack-objects", NULL);
- die("git-unpack-objects exec failed");
+ 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);
+ puts(sha1_to_hex(remote));
+ 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);
}
int main(int argc, char **argv)