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