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