tag.con commit Fourth batch (bc12974)
   1#include "cache.h"
   2#include "tag.h"
   3#include "object-store.h"
   4#include "commit.h"
   5#include "tree.h"
   6#include "blob.h"
   7#include "alloc.h"
   8#include "gpg-interface.h"
   9#include "packfile.h"
  10
  11const char *tag_type = "tag";
  12
  13static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags)
  14{
  15        struct signature_check sigc;
  16        size_t payload_size;
  17        int ret;
  18
  19        memset(&sigc, 0, sizeof(sigc));
  20
  21        payload_size = parse_signature(buf, size);
  22
  23        if (size == payload_size) {
  24                if (flags & GPG_VERIFY_VERBOSE)
  25                        write_in_full(1, buf, payload_size);
  26                return error("no signature found");
  27        }
  28
  29        ret = check_signature(buf, payload_size, buf + payload_size,
  30                                size - payload_size, &sigc);
  31
  32        if (!(flags & GPG_VERIFY_OMIT_STATUS))
  33                print_signature_buffer(&sigc, flags);
  34
  35        signature_check_clear(&sigc);
  36        return ret;
  37}
  38
  39int gpg_verify_tag(const struct object_id *oid, const char *name_to_report,
  40                unsigned flags)
  41{
  42        enum object_type type;
  43        char *buf;
  44        unsigned long size;
  45        int ret;
  46
  47        type = oid_object_info(the_repository, oid, NULL);
  48        if (type != OBJ_TAG)
  49                return error("%s: cannot verify a non-tag object of type %s.",
  50                                name_to_report ?
  51                                name_to_report :
  52                                find_unique_abbrev(oid, DEFAULT_ABBREV),
  53                                type_name(type));
  54
  55        buf = read_object_file(oid, &type, &size);
  56        if (!buf)
  57                return error("%s: unable to read file.",
  58                                name_to_report ?
  59                                name_to_report :
  60                                find_unique_abbrev(oid, DEFAULT_ABBREV));
  61
  62        ret = run_gpg_verify(buf, size, flags);
  63
  64        free(buf);
  65        return ret;
  66}
  67
  68struct object *deref_tag(struct repository *r, struct object *o, const char *warn, int warnlen)
  69{
  70        struct object_id *last_oid = NULL;
  71        while (o && o->type == OBJ_TAG)
  72                if (((struct tag *)o)->tagged) {
  73                        last_oid = &((struct tag *)o)->tagged->oid;
  74                        o = parse_object(r, last_oid);
  75                } else {
  76                        last_oid = NULL;
  77                        o = NULL;
  78                }
  79        if (!o && warn) {
  80                if (last_oid && is_promisor_object(last_oid))
  81                        return NULL;
  82                if (!warnlen)
  83                        warnlen = strlen(warn);
  84                error("missing object referenced by '%.*s'", warnlen, warn);
  85        }
  86        return o;
  87}
  88
  89struct object *deref_tag_noverify(struct object *o)
  90{
  91        while (o && o->type == OBJ_TAG) {
  92                o = parse_object(the_repository, &o->oid);
  93                if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged)
  94                        o = ((struct tag *)o)->tagged;
  95                else
  96                        o = NULL;
  97        }
  98        return o;
  99}
 100
 101struct tag *lookup_tag(struct repository *r, const struct object_id *oid)
 102{
 103        struct object *obj = lookup_object(r, oid);
 104        if (!obj)
 105                return create_object(r, oid, alloc_tag_node(r));
 106        return object_as_type(r, obj, OBJ_TAG, 0);
 107}
 108
 109static timestamp_t parse_tag_date(const char *buf, const char *tail)
 110{
 111        const char *dateptr;
 112
 113        while (buf < tail && *buf++ != '>')
 114                /* nada */;
 115        if (buf >= tail)
 116                return 0;
 117        dateptr = buf;
 118        while (buf < tail && *buf++ != '\n')
 119                /* nada */;
 120        if (buf >= tail)
 121                return 0;
 122        /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */
 123        return parse_timestamp(dateptr, NULL, 10);
 124}
 125
 126void release_tag_memory(struct tag *t)
 127{
 128        free(t->tag);
 129        t->tagged = NULL;
 130        t->object.parsed = 0;
 131        t->date = 0;
 132}
 133
 134int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, unsigned long size)
 135{
 136        struct object_id oid;
 137        char type[20];
 138        const char *bufptr = data;
 139        const char *tail = bufptr + size;
 140        const char *nl;
 141
 142        if (item->object.parsed)
 143                return 0;
 144        item->object.parsed = 1;
 145
 146        if (size < the_hash_algo->hexsz + 24)
 147                return -1;
 148        if (memcmp("object ", bufptr, 7) || parse_oid_hex(bufptr + 7, &oid, &bufptr) || *bufptr++ != '\n')
 149                return -1;
 150
 151        if (!starts_with(bufptr, "type "))
 152                return -1;
 153        bufptr += 5;
 154        nl = memchr(bufptr, '\n', tail - bufptr);
 155        if (!nl || sizeof(type) <= (nl - bufptr))
 156                return -1;
 157        memcpy(type, bufptr, nl - bufptr);
 158        type[nl - bufptr] = '\0';
 159        bufptr = nl + 1;
 160
 161        if (!strcmp(type, blob_type)) {
 162                item->tagged = (struct object *)lookup_blob(r, &oid);
 163        } else if (!strcmp(type, tree_type)) {
 164                item->tagged = (struct object *)lookup_tree(r, &oid);
 165        } else if (!strcmp(type, commit_type)) {
 166                item->tagged = (struct object *)lookup_commit(r, &oid);
 167        } else if (!strcmp(type, tag_type)) {
 168                item->tagged = (struct object *)lookup_tag(r, &oid);
 169        } else {
 170                error("Unknown type %s", type);
 171                item->tagged = NULL;
 172        }
 173
 174        if (bufptr + 4 < tail && starts_with(bufptr, "tag "))
 175                ;               /* good */
 176        else
 177                return -1;
 178        bufptr += 4;
 179        nl = memchr(bufptr, '\n', tail - bufptr);
 180        if (!nl)
 181                return -1;
 182        item->tag = xmemdupz(bufptr, nl - bufptr);
 183        bufptr = nl + 1;
 184
 185        if (bufptr + 7 < tail && starts_with(bufptr, "tagger "))
 186                item->date = parse_tag_date(bufptr, tail);
 187        else
 188                item->date = 0;
 189
 190        return 0;
 191}
 192
 193int parse_tag(struct tag *item)
 194{
 195        enum object_type type;
 196        void *data;
 197        unsigned long size;
 198        int ret;
 199
 200        if (item->object.parsed)
 201                return 0;
 202        data = read_object_file(&item->object.oid, &type, &size);
 203        if (!data)
 204                return error("Could not read %s",
 205                             oid_to_hex(&item->object.oid));
 206        if (type != OBJ_TAG) {
 207                free(data);
 208                return error("Object %s not a tag",
 209                             oid_to_hex(&item->object.oid));
 210        }
 211        ret = parse_tag_buffer(the_repository, item, data, size);
 212        free(data);
 213        return ret;
 214}
 215
 216struct object_id *get_tagged_oid(struct tag *tag)
 217{
 218        if (!tag->tagged)
 219                die("bad tag");
 220        return &tag->tagged->oid;
 221}