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