tag.con commit completion: offer ctags symbol names for 'git log -S', '-G' and '-L:' (41d2716)
   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 unsigned char *sha1, 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 = sha1_object_info(sha1, 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(sha1, DEFAULT_ABBREV),
  50                                typename(type));
  51
  52        buf = read_sha1_file(sha1, &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(sha1, 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.hash);
  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.hash);
  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 unsigned char *sha1)
  93{
  94        struct object *obj = lookup_object(sha1);
  95        if (!obj)
  96                return create_object(sha1, alloc_tag_node());
  97        return object_as_type(obj, OBJ_TAG, 0);
  98}
  99
 100static unsigned long 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 strtoul will stop at buf-1 */
 114        return strtoul(dateptr, NULL, 10);
 115}
 116
 117int parse_tag_buffer(struct tag *item, const void *data, unsigned long size)
 118{
 119        unsigned char sha1[20];
 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 < 64)
 130                return -1;
 131        if (memcmp("object ", bufptr, 7) || get_sha1_hex(bufptr + 7, sha1) || bufptr[47] != '\n')
 132                return -1;
 133        bufptr += 48; /* "object " + sha1 + "\n" */
 134
 135        if (!starts_with(bufptr, "type "))
 136                return -1;
 137        bufptr += 5;
 138        nl = memchr(bufptr, '\n', tail - bufptr);
 139        if (!nl || sizeof(type) <= (nl - bufptr))
 140                return -1;
 141        memcpy(type, bufptr, nl - bufptr);
 142        type[nl - bufptr] = '\0';
 143        bufptr = nl + 1;
 144
 145        if (!strcmp(type, blob_type)) {
 146                item->tagged = &lookup_blob(sha1)->object;
 147        } else if (!strcmp(type, tree_type)) {
 148                item->tagged = &lookup_tree(sha1)->object;
 149        } else if (!strcmp(type, commit_type)) {
 150                item->tagged = &lookup_commit(sha1)->object;
 151        } else if (!strcmp(type, tag_type)) {
 152                item->tagged = &lookup_tag(sha1)->object;
 153        } else {
 154                error("Unknown type %s", type);
 155                item->tagged = NULL;
 156        }
 157
 158        if (bufptr + 4 < tail && starts_with(bufptr, "tag "))
 159                ;               /* good */
 160        else
 161                return -1;
 162        bufptr += 4;
 163        nl = memchr(bufptr, '\n', tail - bufptr);
 164        if (!nl)
 165                return -1;
 166        item->tag = xmemdupz(bufptr, nl - bufptr);
 167        bufptr = nl + 1;
 168
 169        if (bufptr + 7 < tail && starts_with(bufptr, "tagger "))
 170                item->date = parse_tag_date(bufptr, tail);
 171        else
 172                item->date = 0;
 173
 174        return 0;
 175}
 176
 177int parse_tag(struct tag *item)
 178{
 179        enum object_type type;
 180        void *data;
 181        unsigned long size;
 182        int ret;
 183
 184        if (item->object.parsed)
 185                return 0;
 186        data = read_sha1_file(item->object.oid.hash, &type, &size);
 187        if (!data)
 188                return error("Could not read %s",
 189                             oid_to_hex(&item->object.oid));
 190        if (type != OBJ_TAG) {
 191                free(data);
 192                return error("Object %s not a tag",
 193                             oid_to_hex(&item->object.oid));
 194        }
 195        ret = parse_tag_buffer(item, data, size);
 196        free(data);
 197        return ret;
 198}