http-pull.con commit [PATCH] Make -s flag to show-diff a no-op. (d15aa43)
   1#include <fcntl.h>
   2#include <unistd.h>
   3#include <string.h>
   4#include <stdlib.h>
   5#include "cache.h"
   6#include "commit.h"
   7#include <errno.h>
   8#include <stdio.h>
   9
  10#include <curl/curl.h>
  11#include <curl/easy.h>
  12
  13static CURL *curl;
  14
  15static char *base;
  16
  17static int tree = 0;
  18static int commits = 0;
  19static int all = 0;
  20
  21static SHA_CTX c;
  22static z_stream stream;
  23
  24static int local;
  25static int zret;
  26
  27static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, 
  28                               void *data) {
  29        char expn[4096];
  30        size_t size = eltsize * nmemb;
  31        int posn = 0;
  32        do {
  33                ssize_t retval = write(local, ptr + posn, size - posn);
  34                if (retval < 0)
  35                        return posn;
  36                posn += retval;
  37        } while (posn < size);
  38
  39        stream.avail_in = size;
  40        stream.next_in = ptr;
  41        do {
  42                stream.next_out = expn;
  43                stream.avail_out = sizeof(expn);
  44                zret = inflate(&stream, Z_SYNC_FLUSH);
  45                SHA1_Update(&c, expn, sizeof(expn) - stream.avail_out);
  46        } while (stream.avail_in && zret == Z_OK);
  47        return size;
  48}
  49
  50static int fetch(unsigned char *sha1)
  51{
  52        char *hex = sha1_to_hex(sha1);
  53        char *filename = sha1_file_name(sha1);
  54        char real_sha1[20];
  55        char *url;
  56        char *posn;
  57
  58        if (has_sha1_file(sha1)) {
  59                return 0;
  60        }
  61
  62        local = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
  63
  64        if (local < 0)
  65                return error("Couldn't open %s\n", filename);
  66
  67        memset(&stream, 0, sizeof(stream));
  68
  69        inflateInit(&stream);
  70
  71        SHA1_Init(&c);
  72
  73        curl_easy_setopt(curl, CURLOPT_FILE, NULL);
  74        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
  75
  76        url = xmalloc(strlen(base) + 50);
  77        strcpy(url, base);
  78        posn = url + strlen(base);
  79        strcpy(posn, "objects/");
  80        posn += 8;
  81        memcpy(posn, hex, 2);
  82        posn += 2;
  83        *(posn++) = '/';
  84        strcpy(posn, hex + 2);
  85
  86        curl_easy_setopt(curl, CURLOPT_URL, url);
  87
  88        /*printf("Getting %s\n", hex);*/
  89
  90        if (curl_easy_perform(curl))
  91                return error("Couldn't get %s for %s\n", url, hex);
  92
  93        close(local);
  94        inflateEnd(&stream);
  95        SHA1_Final(real_sha1, &c);
  96        if (zret != Z_STREAM_END) {
  97                unlink(filename);
  98                return error("File %s (%s) corrupt\n", hex, url);
  99        }
 100        if (memcmp(sha1, real_sha1, 20)) {
 101                unlink(filename);
 102                return error("File %s has bad hash\n", hex);
 103        }
 104        
 105        return 0;
 106}
 107
 108static int process_tree(unsigned char *sha1)
 109{
 110        struct tree *tree = lookup_tree(sha1);
 111        struct tree_entry_list *entries;
 112
 113        if (parse_tree(tree))
 114                return -1;
 115
 116        for (entries = tree->entries; entries; entries = entries->next) {
 117                if (fetch(entries->item.tree->object.sha1))
 118                        return -1;
 119                if (entries->directory) {
 120                        if (process_tree(entries->item.tree->object.sha1))
 121                                return -1;
 122                }
 123        }
 124        return 0;
 125}
 126
 127static int process_commit(unsigned char *sha1)
 128{
 129        struct commit *obj = lookup_commit(sha1);
 130
 131        if (fetch(sha1))
 132                return -1;
 133
 134        if (parse_commit(obj))
 135                return -1;
 136
 137        if (tree) {
 138                if (fetch(obj->tree->object.sha1))
 139                        return -1;
 140                if (process_tree(obj->tree->object.sha1))
 141                        return -1;
 142                if (!all)
 143                        tree = 0;
 144        }
 145        if (commits) {
 146                struct commit_list *parents = obj->parents;
 147                for (; parents; parents = parents->next) {
 148                        if (has_sha1_file(parents->item->object.sha1))
 149                                continue;
 150                        if (fetch(parents->item->object.sha1)) {
 151                                /* The server might not have it, and
 152                                 * we don't mind. 
 153                                 */
 154                                continue;
 155                        }
 156                        if (process_commit(parents->item->object.sha1))
 157                                return -1;
 158                }
 159        }
 160        return 0;
 161}
 162
 163int main(int argc, char **argv)
 164{
 165        char *commit_id;
 166        char *url;
 167        int arg = 1;
 168        unsigned char sha1[20];
 169
 170        while (arg < argc && argv[arg][0] == '-') {
 171                if (argv[arg][1] == 't') {
 172                        tree = 1;
 173                } else if (argv[arg][1] == 'c') {
 174                        commits = 1;
 175                } else if (argv[arg][1] == 'a') {
 176                        all = 1;
 177                        tree = 1;
 178                        commits = 1;
 179                }
 180                arg++;
 181        }
 182        if (argc < arg + 2) {
 183                usage("http-pull [-c] [-t] [-a] commit-id url");
 184                return 1;
 185        }
 186        commit_id = argv[arg];
 187        url = argv[arg + 1];
 188
 189        get_sha1_hex(commit_id, sha1);
 190
 191        curl_global_init(CURL_GLOBAL_ALL);
 192
 193        curl = curl_easy_init();
 194
 195        base = url;
 196
 197        if (fetch(sha1))
 198                return 1;
 199        if (process_commit(sha1))
 200                return 1;
 201
 202        curl_global_cleanup();
 203        return 0;
 204}