63002b18875d2c1d3c18e33c29d0ff6df5ded55a
   1#include "cache.h"
   2#include "walker.h"
   3#include "repository.h"
   4#include "object-store.h"
   5#include "commit.h"
   6#include "tree.h"
   7#include "tree-walk.h"
   8#include "tag.h"
   9#include "blob.h"
  10#include "refs.h"
  11
  12static struct object_id current_commit_oid;
  13
  14void walker_say(struct walker *walker, const char *fmt, ...)
  15{
  16        if (walker->get_verbosely) {
  17                va_list ap;
  18                va_start(ap, fmt);
  19                vfprintf(stderr, fmt, ap);
  20                va_end(ap);
  21        }
  22}
  23
  24static void report_missing(const struct object *obj)
  25{
  26        fprintf(stderr, "Cannot obtain needed %s %s\n",
  27                obj->type ? type_name(obj->type): "object",
  28                oid_to_hex(&obj->oid));
  29        if (!is_null_oid(&current_commit_oid))
  30                fprintf(stderr, "while processing commit %s.\n",
  31                        oid_to_hex(&current_commit_oid));
  32}
  33
  34static int process(struct walker *walker, struct object *obj);
  35
  36static int process_tree(struct walker *walker, struct tree *tree)
  37{
  38        struct tree_desc desc;
  39        struct name_entry entry;
  40
  41        if (parse_tree(tree))
  42                return -1;
  43
  44        init_tree_desc(&desc, tree->buffer, tree->size);
  45        while (tree_entry(&desc, &entry)) {
  46                struct object *obj = NULL;
  47
  48                /* submodule commits are not stored in the superproject */
  49                if (S_ISGITLINK(entry.mode))
  50                        continue;
  51                if (S_ISDIR(entry.mode)) {
  52                        struct tree *tree = lookup_tree(entry.oid);
  53                        if (tree)
  54                                obj = &tree->object;
  55                }
  56                else {
  57                        struct blob *blob = lookup_blob(entry.oid);
  58                        if (blob)
  59                                obj = &blob->object;
  60                }
  61                if (!obj || process(walker, obj))
  62                        return -1;
  63        }
  64        free_tree_buffer(tree);
  65        return 0;
  66}
  67
  68/* Remember to update object flag allocation in object.h */
  69#define COMPLETE        (1U << 0)
  70#define SEEN            (1U << 1)
  71#define TO_SCAN         (1U << 2)
  72
  73static struct commit_list *complete = NULL;
  74
  75static int process_commit(struct walker *walker, struct commit *commit)
  76{
  77        struct commit_list *parents;
  78
  79        if (parse_commit(commit))
  80                return -1;
  81
  82        while (complete && complete->item->date >= commit->date) {
  83                pop_most_recent_commit(&complete, COMPLETE);
  84        }
  85
  86        if (commit->object.flags & COMPLETE)
  87                return 0;
  88
  89        oidcpy(&current_commit_oid, &commit->object.oid);
  90
  91        walker_say(walker, "walk %s\n", oid_to_hex(&commit->object.oid));
  92
  93        if (process(walker, &get_commit_tree(commit)->object))
  94                return -1;
  95
  96        for (parents = commit->parents; parents; parents = parents->next) {
  97                if (process(walker, &parents->item->object))
  98                        return -1;
  99        }
 100
 101        return 0;
 102}
 103
 104static int process_tag(struct walker *walker, struct tag *tag)
 105{
 106        if (parse_tag(tag))
 107                return -1;
 108        return process(walker, tag->tagged);
 109}
 110
 111static struct object_list *process_queue = NULL;
 112static struct object_list **process_queue_end = &process_queue;
 113
 114static int process_object(struct walker *walker, struct object *obj)
 115{
 116        if (obj->type == OBJ_COMMIT) {
 117                if (process_commit(walker, (struct commit *)obj))
 118                        return -1;
 119                return 0;
 120        }
 121        if (obj->type == OBJ_TREE) {
 122                if (process_tree(walker, (struct tree *)obj))
 123                        return -1;
 124                return 0;
 125        }
 126        if (obj->type == OBJ_BLOB) {
 127                return 0;
 128        }
 129        if (obj->type == OBJ_TAG) {
 130                if (process_tag(walker, (struct tag *)obj))
 131                        return -1;
 132                return 0;
 133        }
 134        return error("Unable to determine requirements "
 135                     "of type %s for %s",
 136                     type_name(obj->type), oid_to_hex(&obj->oid));
 137}
 138
 139static int process(struct walker *walker, struct object *obj)
 140{
 141        if (obj->flags & SEEN)
 142                return 0;
 143        obj->flags |= SEEN;
 144
 145        if (has_object_file(&obj->oid)) {
 146                /* We already have it, so we should scan it now. */
 147                obj->flags |= TO_SCAN;
 148        }
 149        else {
 150                if (obj->flags & COMPLETE)
 151                        return 0;
 152                walker->prefetch(walker, obj->oid.hash);
 153        }
 154
 155        object_list_insert(obj, process_queue_end);
 156        process_queue_end = &(*process_queue_end)->next;
 157        return 0;
 158}
 159
 160static int loop(struct walker *walker)
 161{
 162        struct object_list *elem;
 163
 164        while (process_queue) {
 165                struct object *obj = process_queue->item;
 166                elem = process_queue;
 167                process_queue = elem->next;
 168                free(elem);
 169                if (!process_queue)
 170                        process_queue_end = &process_queue;
 171
 172                /* If we are not scanning this object, we placed it in
 173                 * the queue because we needed to fetch it first.
 174                 */
 175                if (! (obj->flags & TO_SCAN)) {
 176                        if (walker->fetch(walker, obj->oid.hash)) {
 177                                report_missing(obj);
 178                                return -1;
 179                        }
 180                }
 181                if (!obj->type)
 182                        parse_object(the_repository, &obj->oid);
 183                if (process_object(walker, obj))
 184                        return -1;
 185        }
 186        return 0;
 187}
 188
 189static int interpret_target(struct walker *walker, char *target, struct object_id *oid)
 190{
 191        if (!get_oid_hex(target, oid))
 192                return 0;
 193        if (!check_refname_format(target, 0)) {
 194                struct ref *ref = alloc_ref(target);
 195                if (!walker->fetch_ref(walker, ref)) {
 196                        oidcpy(oid, &ref->old_oid);
 197                        free(ref);
 198                        return 0;
 199                }
 200                free(ref);
 201        }
 202        return -1;
 203}
 204
 205static int mark_complete(const char *path, const struct object_id *oid,
 206                         int flag, void *cb_data)
 207{
 208        struct commit *commit = lookup_commit_reference_gently(oid, 1);
 209
 210        if (commit) {
 211                commit->object.flags |= COMPLETE;
 212                commit_list_insert(commit, &complete);
 213        }
 214        return 0;
 215}
 216
 217int walker_targets_stdin(char ***target, const char ***write_ref)
 218{
 219        int targets = 0, targets_alloc = 0;
 220        struct strbuf buf = STRBUF_INIT;
 221        *target = NULL; *write_ref = NULL;
 222        while (1) {
 223                char *rf_one = NULL;
 224                char *tg_one;
 225
 226                if (strbuf_getline_lf(&buf, stdin) == EOF)
 227                        break;
 228                tg_one = buf.buf;
 229                rf_one = strchr(tg_one, '\t');
 230                if (rf_one)
 231                        *rf_one++ = 0;
 232
 233                if (targets >= targets_alloc) {
 234                        targets_alloc = targets_alloc ? targets_alloc * 2 : 64;
 235                        REALLOC_ARRAY(*target, targets_alloc);
 236                        REALLOC_ARRAY(*write_ref, targets_alloc);
 237                }
 238                (*target)[targets] = xstrdup(tg_one);
 239                (*write_ref)[targets] = xstrdup_or_null(rf_one);
 240                targets++;
 241        }
 242        strbuf_release(&buf);
 243        return targets;
 244}
 245
 246void walker_targets_free(int targets, char **target, const char **write_ref)
 247{
 248        while (targets--) {
 249                free(target[targets]);
 250                if (write_ref)
 251                        free((char *) write_ref[targets]);
 252        }
 253}
 254
 255int walker_fetch(struct walker *walker, int targets, char **target,
 256                 const char **write_ref, const char *write_ref_log_details)
 257{
 258        struct strbuf refname = STRBUF_INIT;
 259        struct strbuf err = STRBUF_INIT;
 260        struct ref_transaction *transaction = NULL;
 261        struct object_id *oids = xmalloc(targets * sizeof(struct object_id));
 262        char *msg = NULL;
 263        int i, ret = -1;
 264
 265        save_commit_buffer = 0;
 266
 267        if (write_ref) {
 268                transaction = ref_transaction_begin(&err);
 269                if (!transaction) {
 270                        error("%s", err.buf);
 271                        goto done;
 272                }
 273        }
 274
 275        if (!walker->get_recover) {
 276                for_each_ref(mark_complete, NULL);
 277                commit_list_sort_by_date(&complete);
 278        }
 279
 280        for (i = 0; i < targets; i++) {
 281                if (interpret_target(walker, target[i], oids + i)) {
 282                        error("Could not interpret response from server '%s' as something to pull", target[i]);
 283                        goto done;
 284                }
 285                if (process(walker, lookup_unknown_object(oids[i].hash)))
 286                        goto done;
 287        }
 288
 289        if (loop(walker))
 290                goto done;
 291        if (!write_ref) {
 292                ret = 0;
 293                goto done;
 294        }
 295        if (write_ref_log_details) {
 296                msg = xstrfmt("fetch from %s", write_ref_log_details);
 297        } else {
 298                msg = NULL;
 299        }
 300        for (i = 0; i < targets; i++) {
 301                if (!write_ref[i])
 302                        continue;
 303                strbuf_reset(&refname);
 304                strbuf_addf(&refname, "refs/%s", write_ref[i]);
 305                if (ref_transaction_update(transaction, refname.buf,
 306                                           oids + i, NULL, 0,
 307                                           msg ? msg : "fetch (unknown)",
 308                                           &err)) {
 309                        error("%s", err.buf);
 310                        goto done;
 311                }
 312        }
 313        if (ref_transaction_commit(transaction, &err)) {
 314                error("%s", err.buf);
 315                goto done;
 316        }
 317
 318        ret = 0;
 319
 320done:
 321        ref_transaction_free(transaction);
 322        free(msg);
 323        free(oids);
 324        strbuf_release(&err);
 325        strbuf_release(&refname);
 326        return ret;
 327}
 328
 329void walker_free(struct walker *walker)
 330{
 331        walker->cleanup(walker);
 332        free(walker);
 333}