]>
Commit | Line | Data |
---|---|---|
1 | #ifndef COUNTERPART_ENV_NAME | |
2 | #define COUNTERPART_ENV_NAME "GIT_SSH_FETCH" | |
3 | #endif | |
4 | #ifndef COUNTERPART_PROGRAM_NAME | |
5 | #define COUNTERPART_PROGRAM_NAME "git-ssh-fetch" | |
6 | #endif | |
7 | #ifndef MY_PROGRAM_NAME | |
8 | #define MY_PROGRAM_NAME "git-ssh-upload" | |
9 | #endif | |
10 | ||
11 | #include "cache.h" | |
12 | #include "rsh.h" | |
13 | #include "refs.h" | |
14 | ||
15 | #include <string.h> | |
16 | ||
17 | static unsigned char local_version = 1; | |
18 | static unsigned char remote_version = 0; | |
19 | ||
20 | static int verbose = 0; | |
21 | ||
22 | static int serve_object(int fd_in, int fd_out) { | |
23 | ssize_t size; | |
24 | unsigned char sha1[20]; | |
25 | signed char remote; | |
26 | int posn = 0; | |
27 | do { | |
28 | size = read(fd_in, sha1 + posn, 20 - posn); | |
29 | if (size < 0) { | |
30 | perror("git-ssh-upload: read "); | |
31 | return -1; | |
32 | } | |
33 | if (!size) | |
34 | return -1; | |
35 | posn += size; | |
36 | } while (posn < 20); | |
37 | ||
38 | if (verbose) | |
39 | fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1)); | |
40 | ||
41 | remote = 0; | |
42 | ||
43 | if (!has_sha1_file(sha1)) { | |
44 | fprintf(stderr, "git-ssh-upload: could not find %s\n", | |
45 | sha1_to_hex(sha1)); | |
46 | remote = -1; | |
47 | } | |
48 | ||
49 | write(fd_out, &remote, 1); | |
50 | ||
51 | if (remote < 0) | |
52 | return 0; | |
53 | ||
54 | return write_sha1_to_fd(fd_out, sha1); | |
55 | } | |
56 | ||
57 | static int serve_version(int fd_in, int fd_out) | |
58 | { | |
59 | if (read(fd_in, &remote_version, 1) < 1) | |
60 | return -1; | |
61 | write(fd_out, &local_version, 1); | |
62 | return 0; | |
63 | } | |
64 | ||
65 | static int serve_ref(int fd_in, int fd_out) | |
66 | { | |
67 | char ref[PATH_MAX]; | |
68 | unsigned char sha1[20]; | |
69 | int posn = 0; | |
70 | signed char remote = 0; | |
71 | do { | |
72 | if (read(fd_in, ref + posn, 1) < 1) | |
73 | return -1; | |
74 | posn++; | |
75 | } while (ref[posn - 1]); | |
76 | ||
77 | if (verbose) | |
78 | fprintf(stderr, "Serving %s\n", ref); | |
79 | ||
80 | if (get_ref_sha1(ref, sha1)) | |
81 | remote = -1; | |
82 | write(fd_out, &remote, 1); | |
83 | if (remote) | |
84 | return 0; | |
85 | write(fd_out, sha1, 20); | |
86 | return 0; | |
87 | } | |
88 | ||
89 | ||
90 | static void service(int fd_in, int fd_out) { | |
91 | char type; | |
92 | int retval; | |
93 | do { | |
94 | retval = read(fd_in, &type, 1); | |
95 | if (retval < 1) { | |
96 | if (retval < 0) | |
97 | perror("git-ssh-upload: read "); | |
98 | return; | |
99 | } | |
100 | if (type == 'v' && serve_version(fd_in, fd_out)) | |
101 | return; | |
102 | if (type == 'o' && serve_object(fd_in, fd_out)) | |
103 | return; | |
104 | if (type == 'r' && serve_ref(fd_in, fd_out)) | |
105 | return; | |
106 | } while (1); | |
107 | } | |
108 | ||
109 | static const char ssh_push_usage[] = | |
110 | MY_PROGRAM_NAME " [-c] [-t] [-a] [-w ref] commit-id url"; | |
111 | ||
112 | int main(int argc, char **argv) | |
113 | { | |
114 | int arg = 1; | |
115 | char *commit_id; | |
116 | char *url; | |
117 | int fd_in, fd_out; | |
118 | const char *prog; | |
119 | unsigned char sha1[20]; | |
120 | char hex[41]; | |
121 | ||
122 | prog = getenv(COUNTERPART_ENV_NAME); | |
123 | if (!prog) prog = COUNTERPART_PROGRAM_NAME; | |
124 | while (arg < argc && argv[arg][0] == '-') { | |
125 | if (argv[arg][1] == 'w') | |
126 | arg++; | |
127 | arg++; | |
128 | } | |
129 | if (argc < arg + 2) | |
130 | usage(ssh_push_usage); | |
131 | commit_id = argv[arg]; | |
132 | url = argv[arg + 1]; | |
133 | if (get_sha1(commit_id, sha1)) | |
134 | usage(ssh_push_usage); | |
135 | memcpy(hex, sha1_to_hex(sha1), sizeof(hex)); | |
136 | argv[arg] = hex; | |
137 | ||
138 | if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1)) | |
139 | return 1; | |
140 | ||
141 | service(fd_in, fd_out); | |
142 | return 0; | |
143 | } |