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