blob: bdf51a7a1437efd49fb5c642ab9294c7f43698de [file] [log] [blame]
Junio C Hamanof71a69a2005-09-15 14:56:37 -07001#ifndef COUNTERPART_ENV_NAME
2#define COUNTERPART_ENV_NAME "GIT_SSH_UPLOAD"
3#endif
4#ifndef COUNTERPART_PROGRAM_NAME
5#define COUNTERPART_PROGRAM_NAME "git-ssh-upload"
6#endif
7#ifndef MY_PROGRAM_NAME
8#define MY_PROGRAM_NAME "git-ssh-fetch"
9#endif
10
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -070011#include "cache.h"
12#include "commit.h"
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -070013#include "rsh.h"
Junio C Hamano215a7ad2005-09-07 17:26:23 -070014#include "fetch.h"
Daniel Barkalowc7c4bbe2005-06-06 16:43:27 -040015#include "refs.h"
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -070016
17static int fd_in;
18static int fd_out;
19
David Rientjes96f1e582006-08-15 10:23:48 -070020static unsigned char remote_version;
Daniel Barkalowdba385b2005-06-03 17:43:52 -040021static unsigned char local_version = 1;
22
David Rientjes96f1e582006-08-15 10:23:48 -070023static int prefetches;
Daniel Barkalow70a0c6f2005-10-04 00:24:55 -040024
David Rientjes96f1e582006-08-15 10:23:48 -070025static struct object_list *in_transit;
Daniel Barkalow70a0c6f2005-10-04 00:24:55 -040026static struct object_list **end_of_transit = &in_transit;
27
barkalow@iabervon.org1e8be592005-08-02 19:46:10 -040028void prefetch(unsigned char *sha1)
29{
barkalow@iabervon.org70b98292005-08-02 19:46:29 -040030 char type = 'o';
Daniel Barkalow70a0c6f2005-10-04 00:24:55 -040031 struct object_list *node;
32 if (prefetches > 100) {
33 fetch(in_transit->item->sha1);
34 }
35 node = xmalloc(sizeof(struct object_list));
36 node->next = NULL;
37 node->item = lookup_unknown_object(sha1);
38 *end_of_transit = node;
39 end_of_transit = &node->next;
Andy Whitcroft93822c22007-01-08 15:58:23 +000040 /* XXX: what if these writes fail? */
41 write_in_full(fd_out, &type, 1);
42 write_in_full(fd_out, sha1, 20);
Daniel Barkalow70a0c6f2005-10-04 00:24:55 -040043 prefetches++;
barkalow@iabervon.org1e8be592005-08-02 19:46:10 -040044}
45
barkalow@iabervon.org70b98292005-08-02 19:46:29 -040046static char conn_buf[4096];
David Rientjes96f1e582006-08-15 10:23:48 -070047static size_t conn_buf_posn;
barkalow@iabervon.org70b98292005-08-02 19:46:29 -040048
Daniel Barkalow4250a5e2005-04-30 16:53:56 -070049int fetch(unsigned char *sha1)
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -070050{
Junio C Hamanoe78d9772005-05-06 01:37:21 -070051 int ret;
Daniel Barkalowdba385b2005-06-03 17:43:52 -040052 signed char remote;
Daniel Barkalow70a0c6f2005-10-04 00:24:55 -040053 struct object_list *temp;
54
David Rientjesa89fccd2006-08-17 11:54:57 -070055 if (hashcmp(sha1, in_transit->item->sha1)) {
Pavel Roskina9486b02006-07-10 02:57:51 -040056 /* we must have already fetched it to clean the queue */
Daniel Barkalow70a0c6f2005-10-04 00:24:55 -040057 return has_sha1_file(sha1) ? 0 : -1;
58 }
59 prefetches--;
60 temp = in_transit;
61 in_transit = in_transit->next;
62 if (!in_transit)
63 end_of_transit = &in_transit;
64 free(temp);
barkalow@iabervon.org70b98292005-08-02 19:46:29 -040065
66 if (conn_buf_posn) {
67 remote = conn_buf[0];
68 memmove(conn_buf, conn_buf + 1, --conn_buf_posn);
69 } else {
Andy Whitcroft93d26e42007-01-08 15:58:08 +000070 if (xread(fd_in, &remote, 1) < 1)
barkalow@iabervon.org70b98292005-08-02 19:46:29 -040071 return -1;
72 }
Pavel Roskina9486b02006-07-10 02:57:51 -040073 /* fprintf(stderr, "Got %d\n", remote); */
Daniel Barkalowdba385b2005-06-03 17:43:52 -040074 if (remote < 0)
75 return remote;
barkalow@iabervon.org70b98292005-08-02 19:46:29 -040076 ret = write_sha1_from_fd(sha1, fd_in, conn_buf, 4096, &conn_buf_posn);
Junio C Hamanoe78d9772005-05-06 01:37:21 -070077 if (!ret)
78 pull_say("got %s\n", sha1_to_hex(sha1));
79 return ret;
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -070080}
81
Linus Torvalds6da40162005-07-03 10:10:45 -070082static int get_version(void)
Daniel Barkalowdba385b2005-06-03 17:43:52 -040083{
84 char type = 'v';
Andy Whitcroft93822c22007-01-08 15:58:23 +000085 if (write_in_full(fd_out, &type, 1) != 1 ||
86 write_in_full(fd_out, &local_version, 1)) {
87 return error("Couldn't request version from remote end");
88 }
Andy Whitcroft93d26e42007-01-08 15:58:08 +000089 if (xread(fd_in, &remote_version, 1) < 1) {
Daniel Barkalowdba385b2005-06-03 17:43:52 -040090 return error("Couldn't read version from remote end");
91 }
92 return 0;
93}
94
Daniel Barkalowcd541a62005-06-06 16:38:26 -040095int fetch_ref(char *ref, unsigned char *sha1)
96{
Daniel Barkalowc7c4bbe2005-06-06 16:43:27 -040097 signed char remote;
98 char type = 'r';
Andy Whitcroft93822c22007-01-08 15:58:23 +000099 int length = strlen(ref) + 1;
100 if (write_in_full(fd_out, &type, 1) != 1 ||
101 write_in_full(fd_out, ref, length) != length)
102 return -1;
Andy Whitcroft93d26e42007-01-08 15:58:08 +0000103
104 if (read_in_full(fd_in, &remote, 1) != 1)
105 return -1;
Daniel Barkalowc7c4bbe2005-06-06 16:43:27 -0400106 if (remote < 0)
107 return remote;
Andy Whitcroft93d26e42007-01-08 15:58:08 +0000108 if (read_in_full(fd_in, sha1, 20) != 20)
109 return -1;
Daniel Barkalowc7c4bbe2005-06-06 16:43:27 -0400110 return 0;
Daniel Barkalowcd541a62005-06-06 16:38:26 -0400111}
112
Junio C Hamanof71a69a2005-09-15 14:56:37 -0700113static const char ssh_fetch_usage[] =
114 MY_PROGRAM_NAME
Petr Baudiscc41cd22006-07-27 20:58:53 +0200115 " [-c] [-t] [-a] [-v] [--recover] [-w ref] commit-id url";
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700116int main(int argc, char **argv)
117{
Petr Baudisc6b69bd2006-07-27 23:56:14 +0200118 const char *write_ref = NULL;
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700119 char *commit_id;
120 char *url;
121 int arg = 1;
Jason Riedyc7c81b32005-08-23 13:34:07 -0700122 const char *prog;
123
124 prog = getenv("GIT_SSH_PUSH");
Junio C Hamano215a7ad2005-09-07 17:26:23 -0700125 if (!prog) prog = "git-ssh-upload";
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700126
Junio C Hamano5a327712005-11-26 00:47:59 -0800127 setup_git_directory();
Shawn Pearced0740d92006-05-19 03:29:26 -0400128 git_config(git_default_config);
Junio C Hamano5a327712005-11-26 00:47:59 -0800129
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700130 while (arg < argc && argv[arg][0] == '-') {
131 if (argv[arg][1] == 't') {
Daniel Barkalow4250a5e2005-04-30 16:53:56 -0700132 get_tree = 1;
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700133 } else if (argv[arg][1] == 'c') {
Daniel Barkalow4250a5e2005-04-30 16:53:56 -0700134 get_history = 1;
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700135 } else if (argv[arg][1] == 'a') {
Daniel Barkalow4250a5e2005-04-30 16:53:56 -0700136 get_all = 1;
137 get_tree = 1;
138 get_history = 1;
Junio C Hamanoe78d9772005-05-06 01:37:21 -0700139 } else if (argv[arg][1] == 'v') {
140 get_verbosely = 1;
Daniel Barkalowc7c4bbe2005-06-06 16:43:27 -0400141 } else if (argv[arg][1] == 'w') {
142 write_ref = argv[arg + 1];
143 arg++;
Daniel Barkalow820eca62005-09-26 21:38:08 -0400144 } else if (!strcmp(argv[arg], "--recover")) {
145 get_recover = 1;
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700146 }
147 arg++;
148 }
149 if (argc < arg + 2) {
Junio C Hamanof71a69a2005-09-15 14:56:37 -0700150 usage(ssh_fetch_usage);
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700151 return 1;
152 }
153 commit_id = argv[arg];
154 url = argv[arg + 1];
155
Linus Torvalds001d4a22005-06-07 14:23:46 -0700156 if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1))
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700157 return 1;
158
Daniel Barkalowdba385b2005-06-03 17:43:52 -0400159 if (get_version())
160 return 1;
161
Petr Baudis4211e4d2006-07-27 23:56:17 +0200162 if (pull(1, &commit_id, &write_ref, url))
Daniel Barkalow6eb7ed52005-04-23 18:47:23 -0700163 return 1;
164
165 return 0;
166}