pull.con commit [PATCH] Finish initial cut of git-pack-object/git-unpack-object pair. (8ee378a)
   1#include "pull.h"
   2
   3#include "cache.h"
   4#include "commit.h"
   5#include "tree.h"
   6#include "tag.h"
   7#include "blob.h"
   8#include "refs.h"
   9
  10const char *write_ref = NULL;
  11
  12const unsigned char *current_ref = NULL;
  13
  14int get_tree = 0;
  15int get_history = 0;
  16/* 1 means "get delta", 2 means "really check delta harder */
  17int get_delta = 1;
  18int get_all = 0;
  19int get_verbosely = 0;
  20static unsigned char current_commit_sha1[20];
  21
  22static const char commitS[] = "commit";
  23static const char treeS[] = "tree";
  24static const char blobS[] = "blob";
  25
  26void pull_say(const char *fmt, const char *hex) {
  27        if (get_verbosely)
  28                fprintf(stderr, fmt, hex);
  29}
  30
  31static void report_missing(const char *what, const unsigned char *missing)
  32{
  33        char missing_hex[41];
  34
  35        strcpy(missing_hex, sha1_to_hex(missing));;
  36        fprintf(stderr,
  37                "Cannot obtain needed %s %s\nwhile processing commit %s.\n",
  38                what, missing_hex, sha1_to_hex(current_commit_sha1));
  39}
  40
  41static int make_sure_we_have_it(const char *what, unsigned char *sha1)
  42{
  43        int status = 0;
  44
  45        if (!has_sha1_file(sha1)) {
  46                status = fetch(sha1);
  47                if (status && what)
  48                        report_missing(what, sha1);
  49        }
  50        else if (get_delta < 2)
  51                return 0;
  52
  53        if (get_delta) {
  54                unsigned char delta_sha1[20];
  55                status = sha1_delta_base(sha1, delta_sha1);
  56                if (0 < status)
  57                        status = make_sure_we_have_it(what, delta_sha1);
  58        }
  59        return status;
  60}
  61
  62static int process_unknown(unsigned char *sha1);
  63
  64static int process_tree(unsigned char *sha1)
  65{
  66        struct tree *tree = lookup_tree(sha1);
  67        struct tree_entry_list *entries;
  68
  69        if (parse_tree(tree))
  70                return -1;
  71
  72        for (entries = tree->entries; entries; entries = entries->next) {
  73                const char *what = entries->directory ? treeS : blobS;
  74                if (make_sure_we_have_it(what, entries->item.tree->object.sha1))
  75                        return -1;
  76                if (entries->directory) {
  77                        if (process_tree(entries->item.tree->object.sha1))
  78                                return -1;
  79                }
  80        }
  81        return 0;
  82}
  83
  84static int process_commit(unsigned char *sha1)
  85{
  86        struct commit *obj = lookup_commit(sha1);
  87
  88        if (make_sure_we_have_it(commitS, sha1))
  89                return -1;
  90
  91        if (parse_commit(obj))
  92                return -1;
  93
  94        if (get_tree) {
  95                if (make_sure_we_have_it(treeS, obj->tree->object.sha1))
  96                        return -1;
  97                if (process_tree(obj->tree->object.sha1))
  98                        return -1;
  99                if (!get_all)
 100                        get_tree = 0;
 101        }
 102        if (get_history) {
 103                struct commit_list *parents = obj->parents;
 104                for (; parents; parents = parents->next) {
 105                        if (has_sha1_file(parents->item->object.sha1))
 106                                continue;
 107                        if (make_sure_we_have_it(NULL,
 108                                                 parents->item->object.sha1)) {
 109                                /* The server might not have it, and
 110                                 * we don't mind. 
 111                                 */
 112                                continue;
 113                        }
 114                        if (process_commit(parents->item->object.sha1))
 115                                return -1;
 116                        memcpy(current_commit_sha1, sha1, 20);
 117                }
 118        }
 119        return 0;
 120}
 121
 122static int process_tag(unsigned char *sha1)
 123{
 124        struct tag *obj = lookup_tag(sha1);
 125
 126        if (parse_tag(obj))
 127                return -1;
 128        return process_unknown(obj->tagged->sha1);
 129}
 130
 131static int process_unknown(unsigned char *sha1)
 132{
 133        struct object *obj;
 134        if (make_sure_we_have_it("object", sha1))
 135                return -1;
 136        obj = parse_object(sha1);
 137        if (!obj)
 138                return error("Unable to parse object %s", sha1_to_hex(sha1));
 139        if (obj->type == commit_type)
 140                return process_commit(sha1);
 141        if (obj->type == tree_type)
 142                return process_tree(sha1);
 143        if (obj->type == blob_type)
 144                return 0;
 145        if (obj->type == tag_type)
 146                return process_tag(sha1);
 147        return error("Unable to determine requirement of type %s for %s",
 148                     obj->type, sha1_to_hex(sha1));
 149}
 150
 151static int interpret_target(char *target, unsigned char *sha1)
 152{
 153        if (!get_sha1_hex(target, sha1))
 154                return 0;
 155        if (!check_ref_format(target)) {
 156                if (!fetch_ref(target, sha1)) {
 157                        return 0;
 158                }
 159        }
 160        return -1;
 161}
 162
 163
 164int pull(char *target)
 165{
 166        unsigned char sha1[20];
 167        int fd = -1;
 168
 169        if (write_ref && current_ref) {
 170                fd = lock_ref_sha1(write_ref, current_ref);
 171                if (fd < 0)
 172                        return -1;
 173        }
 174
 175        if (interpret_target(target, sha1))
 176                return error("Could not interpret %s as something to pull",
 177                             target);
 178        if (process_unknown(sha1))
 179                return -1;
 180        
 181        if (write_ref) {
 182                if (current_ref) {
 183                        write_ref_sha1(write_ref, fd, sha1);
 184                } else {
 185                        write_ref_sha1_unlocked(write_ref, sha1);
 186                }
 187        }
 188        return 0;
 189}