builtin / remote-fd.con commit commit: add short-circuit to paint_down_to_common() (d7c1ec3)
   1#include "builtin.h"
   2#include "transport.h"
   3
   4static const char usage_msg[] =
   5        "git remote-fd <remote> <url>";
   6
   7/*
   8 * URL syntax:
   9 *      'fd::<inoutfd>[/<anything>]'            Read/write socket pair
  10 *                                              <inoutfd>.
  11 *      'fd::<infd>,<outfd>[/<anything>]'       Read pipe <infd> and write
  12 *                                              pipe <outfd>.
  13 *      [foo] indicates 'foo' is optional. <anything> is any string.
  14 *
  15 * The data output to <outfd>/<inoutfd> should be passed unmolested to
  16 * git-receive-pack/git-upload-pack/git-upload-archive and output of
  17 * git-receive-pack/git-upload-pack/git-upload-archive should be passed
  18 * unmolested to <infd>/<inoutfd>.
  19 *
  20 */
  21
  22#define MAXCOMMAND 4096
  23
  24static void command_loop(int input_fd, int output_fd)
  25{
  26        char buffer[MAXCOMMAND];
  27
  28        while (1) {
  29                size_t i;
  30                if (!fgets(buffer, MAXCOMMAND - 1, stdin)) {
  31                        if (ferror(stdin))
  32                                die("Input error");
  33                        return;
  34                }
  35                /* Strip end of line characters. */
  36                i = strlen(buffer);
  37                while (i > 0 && isspace(buffer[i - 1]))
  38                        buffer[--i] = 0;
  39
  40                if (!strcmp(buffer, "capabilities")) {
  41                        printf("*connect\n\n");
  42                        fflush(stdout);
  43                } else if (!strncmp(buffer, "connect ", 8)) {
  44                        printf("\n");
  45                        fflush(stdout);
  46                        if (bidirectional_transfer_loop(input_fd,
  47                                output_fd))
  48                                die("Copying data between file descriptors failed");
  49                        return;
  50                } else {
  51                        die("Bad command: %s", buffer);
  52                }
  53        }
  54}
  55
  56int cmd_remote_fd(int argc, const char **argv, const char *prefix)
  57{
  58        int input_fd = -1;
  59        int output_fd = -1;
  60        char *end;
  61
  62        if (argc != 3)
  63                usage(usage_msg);
  64
  65        input_fd = (int)strtoul(argv[2], &end, 10);
  66
  67        if ((end == argv[2]) || (*end != ',' && *end != '/' && *end))
  68                die("Bad URL syntax");
  69
  70        if (*end == '/' || !*end) {
  71                output_fd = input_fd;
  72        } else {
  73                char *end2;
  74                output_fd = (int)strtoul(end + 1, &end2, 10);
  75
  76                if ((end2 == end + 1) || (*end2 != '/' && *end2))
  77                        die("Bad URL syntax");
  78        }
  79
  80        command_loop(input_fd, output_fd);
  81        return 0;
  82}