tag.con commit get-tar-commit-id: parse comment record (3548726)
   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->hash);
 104        if (!obj)
 105                return create_object(r, oid->hash,
 106                                     alloc_tag_node(r));
 107        return object_as_type(r, obj, OBJ_TAG, 0);
 108}
 109
 110static timestamp_t parse_tag_date(const char *buf, const char *tail)
 111{
 112        const char *dateptr;
 113
 114        while (buf < tail && *buf++ != '>')
 115                /* nada */;
 116        if (buf >= tail)
 117                return 0;
 118        dateptr = buf;
 119        while (buf < tail && *buf++ != '\n')
 120                /* nada */;
 121        if (buf >= tail)
 122                return 0;
 123        /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */
 124        return parse_timestamp(dateptr, NULL, 10);
 125}
 126
 127void release_tag_memory(struct tag *t)
 128{
 129        free(t->tag);
 130        t->tagged = NULL;
 131        t->object.parsed = 0;
 132        t->date = 0;
 133}
 134
 135int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, unsigned long size)
 136{
 137        struct object_id oid;
 138        char type[20];
 139        const char *bufptr = data;
 140        const char *tail = bufptr + size;
 141        const char *nl;
 142
 143        if (item->object.parsed)
 144                return 0;
 145        item->object.parsed = 1;
 146
 147        if (size < the_hash_algo->hexsz + 24)
 148                return -1;
 149        if (memcmp("object ", bufptr, 7) || parse_oid_hex(bufptr + 7, &oid, &bufptr) || *bufptr++ != '\n')
 150                return -1;
 151
 152        if (!starts_with(bufptr, "type "))
 153                return -1;
 154        bufptr += 5;
 155        nl = memchr(bufptr, '\n', tail - bufptr);
 156        if (!nl || sizeof(type) <= (nl - bufptr))
 157                return -1;
 158        memcpy(type, bufptr, nl - bufptr);
 159        type[nl - bufptr] = '\0';
 160        bufptr = nl + 1;
 161
 162        if (!strcmp(type, blob_type)) {
 163                item->tagged = (struct object *)lookup_blob(r, &oid);
 164        } else if (!strcmp(type, tree_type)) {
 165                item->tagged = (struct object *)lookup_tree(r, &oid);
 166        } else if (!strcmp(type, commit_type)) {
 167                item->tagged = (struct object *)lookup_commit(r, &oid);
 168        } else if (!strcmp(type, tag_type)) {
 169                item->tagged = (struct object *)lookup_tag(r, &oid);
 170        } else {
 171                error("Unknown type %s", type);
 172                item->tagged = NULL;
 173        }
 174
 175        if (bufptr + 4 < tail && starts_with(bufptr, "tag "))
 176                ;               /* good */
 177        else
 178                return -1;
 179        bufptr += 4;
 180        nl = memchr(bufptr, '\n', tail - bufptr);
 181        if (!nl)
 182                return -1;
 183        item->tag = xmemdupz(bufptr, nl - bufptr);
 184        bufptr = nl + 1;
 185
 186        if (bufptr + 7 < tail && starts_with(bufptr, "tagger "))
 187                item->date = parse_tag_date(bufptr, tail);
 188        else
 189                item->date = 0;
 190
 191        return 0;
 192}
 193
 194int parse_tag(struct tag *item)
 195{
 196        enum object_type type;
 197        void *data;
 198        unsigned long size;
 199        int ret;
 200
 201        if (item->object.parsed)
 202                return 0;
 203        data = read_object_file(&item->object.oid, &type, &size);
 204        if (!data)
 205                return error("Could not read %s",
 206                             oid_to_hex(&item->object.oid));
 207        if (type != OBJ_TAG) {
 208                free(data);
 209                return error("Object %s not a tag",
 210                             oid_to_hex(&item->object.oid));
 211        }
 212        ret = parse_tag_buffer(the_repository, item, data, size);
 213        free(data);
 214        return ret;
 215}