tag.con commit git-svn: several graft-branches improvements (c1927a8)
   1#include "cache.h"
   2#include "tag.h"
   3
   4const char *tag_type = "tag";
   5
   6struct object *deref_tag(struct object *o, const char *warn, int warnlen)
   7{
   8        while (o && o->type == TYPE_TAG)
   9                o = parse_object(((struct tag *)o)->tagged->sha1);
  10        if (!o && warn) {
  11                if (!warnlen)
  12                        warnlen = strlen(warn);
  13                error("missing object referenced by '%.*s'", warnlen, warn);
  14        }
  15        return o;
  16}
  17
  18struct tag *lookup_tag(const unsigned char *sha1)
  19{
  20        struct object *obj = lookup_object(sha1);
  21        if (!obj) {
  22                struct tag *ret = alloc_tag_node();
  23                created_object(sha1, &ret->object);
  24                ret->object.type = TYPE_TAG;
  25                return ret;
  26        }
  27        if (!obj->type)
  28                obj->type = TYPE_TAG;
  29        if (obj->type != TYPE_TAG) {
  30                error("Object %s is a %s, not a tree",
  31                      sha1_to_hex(sha1), typename(obj->type));
  32                return NULL;
  33        }
  34        return (struct tag *) obj;
  35}
  36
  37int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
  38{
  39        int typelen, taglen;
  40        unsigned char object[20];
  41        const char *type_line, *tag_line, *sig_line;
  42        char type[20];
  43
  44        if (item->object.parsed)
  45                return 0;
  46        item->object.parsed = 1;
  47
  48        if (size < 64)
  49                return -1;
  50        if (memcmp("object ", data, 7) || get_sha1_hex((char *) data + 7, object))
  51                return -1;
  52
  53        type_line = (char *) data + 48;
  54        if (memcmp("\ntype ", type_line-1, 6))
  55                return -1;
  56
  57        tag_line = strchr(type_line, '\n');
  58        if (!tag_line || memcmp("tag ", ++tag_line, 4))
  59                return -1;
  60
  61        sig_line = strchr(tag_line, '\n');
  62        if (!sig_line)
  63                return -1;
  64        sig_line++;
  65
  66        typelen = tag_line - type_line - strlen("type \n");
  67        if (typelen >= 20)
  68                return -1;
  69        memcpy(type, type_line + 5, typelen);
  70        type[typelen] = '\0';
  71        taglen = sig_line - tag_line - strlen("tag \n");
  72        item->tag = xmalloc(taglen + 1);
  73        memcpy(item->tag, tag_line + 4, taglen);
  74        item->tag[taglen] = '\0';
  75
  76        item->tagged = lookup_object_type(object, type);
  77        if (item->tagged && track_object_refs) {
  78                struct object_refs *refs = alloc_object_refs(1);
  79                refs->ref[0] = item->tagged;
  80                set_object_refs(&item->object, refs);
  81        }
  82
  83        return 0;
  84}
  85
  86int parse_tag(struct tag *item)
  87{
  88        char type[20];
  89        void *data;
  90        unsigned long size;
  91        int ret;
  92
  93        if (item->object.parsed)
  94                return 0;
  95        data = read_sha1_file(item->object.sha1, type, &size);
  96        if (!data)
  97                return error("Could not read %s",
  98                             sha1_to_hex(item->object.sha1));
  99        if (strcmp(type, tag_type)) {
 100                free(data);
 101                return error("Object %s not a tag",
 102                             sha1_to_hex(item->object.sha1));
 103        }
 104        ret = parse_tag_buffer(item, data, size);
 105        free(data);
 106        return ret;
 107}