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