fetch.con commit Merge branch 'js/fmt-patch' into next (c2b9e69)
   1#include "fetch.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;
  16int get_all = 0;
  17int get_verbosely = 0;
  18int get_recover = 0;
  19static unsigned char current_commit_sha1[20];
  20
  21void pull_say(const char *fmt, const char *hex) 
  22{
  23        if (get_verbosely)
  24                fprintf(stderr, fmt, hex);
  25}
  26
  27static void report_missing(const char *what, const unsigned char *missing)
  28{
  29        char missing_hex[41];
  30
  31        strcpy(missing_hex, sha1_to_hex(missing));;
  32        fprintf(stderr,
  33                "Cannot obtain needed %s %s\nwhile processing commit %s.\n",
  34                what, missing_hex, sha1_to_hex(current_commit_sha1));
  35}
  36
  37static int process(struct object *obj);
  38
  39static int process_tree(struct tree *tree)
  40{
  41        struct tree_entry_list *entry;
  42
  43        if (parse_tree(tree))
  44                return -1;
  45
  46        entry = tree->entries;
  47        tree->entries = NULL;
  48        while (entry) {
  49                struct tree_entry_list *next = entry->next;
  50                if (process(entry->item.any))
  51                        return -1;
  52                free(entry->name);
  53                free(entry);
  54                entry = next;
  55        }
  56        return 0;
  57}
  58
  59#define COMPLETE        (1U << 0)
  60#define SEEN            (1U << 1)
  61#define TO_SCAN         (1U << 2)
  62
  63static struct commit_list *complete = NULL;
  64
  65static int process_commit(struct commit *commit)
  66{
  67        if (parse_commit(commit))
  68                return -1;
  69
  70        while (complete && complete->item->date >= commit->date) {
  71                pop_most_recent_commit(&complete, COMPLETE);
  72        }
  73
  74        if (commit->object.flags & COMPLETE)
  75                return 0;
  76
  77        memcpy(current_commit_sha1, commit->object.sha1, 20);
  78
  79        pull_say("walk %s\n", sha1_to_hex(commit->object.sha1));
  80
  81        if (get_tree) {
  82                if (process(&commit->tree->object))
  83                        return -1;
  84                if (!get_all)
  85                        get_tree = 0;
  86        }
  87        if (get_history) {
  88                struct commit_list *parents = commit->parents;
  89                for (; parents; parents = parents->next) {
  90                        if (process(&parents->item->object))
  91                                return -1;
  92                }
  93        }
  94        return 0;
  95}
  96
  97static int process_tag(struct tag *tag)
  98{
  99        if (parse_tag(tag))
 100                return -1;
 101        return process(tag->tagged);
 102}
 103
 104static struct object_list *process_queue = NULL;
 105static struct object_list **process_queue_end = &process_queue;
 106
 107static int process_object(struct object *obj)
 108{
 109        if (obj->type == commit_type) {
 110                if (process_commit((struct commit *)obj))
 111                        return -1;
 112                return 0;
 113        }
 114        if (obj->type == tree_type) {
 115                if (process_tree((struct tree *)obj))
 116                        return -1;
 117                return 0;
 118        }
 119        if (obj->type == blob_type) {
 120                return 0;
 121        }
 122        if (obj->type == tag_type) {
 123                if (process_tag((struct tag *)obj))
 124                        return -1;
 125                return 0;
 126        }
 127        return error("Unable to determine requirements "
 128                     "of type %s for %s",
 129                     obj->type, sha1_to_hex(obj->sha1));
 130}
 131
 132static int process(struct object *obj)
 133{
 134        if (obj->flags & SEEN)
 135                return 0;
 136        obj->flags |= SEEN;
 137
 138        if (has_sha1_file(obj->sha1)) {
 139                /* We already have it, so we should scan it now. */
 140                obj->flags |= TO_SCAN;
 141        } else {
 142                if (obj->flags & COMPLETE)
 143                        return 0;
 144                prefetch(obj->sha1);
 145        }
 146                
 147        object_list_insert(obj, process_queue_end);
 148        process_queue_end = &(*process_queue_end)->next;
 149        return 0;
 150}
 151
 152static int loop(void)
 153{
 154        struct object_list *elem;
 155
 156        while (process_queue) {
 157                struct object *obj = process_queue->item;
 158                elem = process_queue;
 159                process_queue = elem->next;
 160                free(elem);
 161                if (!process_queue)
 162                        process_queue_end = &process_queue;
 163
 164                /* If we are not scanning this object, we placed it in
 165                 * the queue because we needed to fetch it first.
 166                 */
 167                if (! (obj->flags & TO_SCAN)) {
 168                        if (fetch(obj->sha1)) {
 169                                report_missing(obj->type
 170                                               ? obj->type
 171                                               : "object", obj->sha1);
 172                                return -1;
 173                        }
 174                }
 175                if (!obj->type)
 176                        parse_object(obj->sha1);
 177                if (process_object(obj))
 178                        return -1;
 179        }
 180        return 0;
 181}
 182
 183static int interpret_target(char *target, unsigned char *sha1)
 184{
 185        if (!get_sha1_hex(target, sha1))
 186                return 0;
 187        if (!check_ref_format(target)) {
 188                if (!fetch_ref(target, sha1)) {
 189                        return 0;
 190                }
 191        }
 192        return -1;
 193}
 194
 195static int mark_complete(const char *path, const unsigned char *sha1)
 196{
 197        struct commit *commit = lookup_commit_reference_gently(sha1, 1);
 198        if (commit) {
 199                commit->object.flags |= COMPLETE;
 200                insert_by_date(commit, &complete);
 201        }
 202        return 0;
 203}
 204
 205int pull(char *target)
 206{
 207        unsigned char sha1[20];
 208        int fd = -1;
 209
 210        save_commit_buffer = 0;
 211        track_object_refs = 0;
 212        if (write_ref && current_ref) {
 213                fd = lock_ref_sha1(write_ref, current_ref);
 214                if (fd < 0)
 215                        return -1;
 216        }
 217
 218        if (!get_recover) {
 219                for_each_ref(mark_complete);
 220        }
 221
 222        if (interpret_target(target, sha1))
 223                return error("Could not interpret %s as something to pull",
 224                             target);
 225        if (process(lookup_unknown_object(sha1)))
 226                return -1;
 227        if (loop())
 228                return -1;
 229        
 230        if (write_ref) {
 231                if (current_ref) {
 232                        write_ref_sha1(write_ref, fd, sha1);
 233                } else {
 234                        write_ref_sha1_unlocked(write_ref, sha1);
 235                }
 236        }
 237        return 0;
 238}