#include "cache.h"
#include "tree-walk.h"
#include "dir.h"
#include "object-store.h"
#include "tree.h"
#include "pathspec.h"
#include "json-writer.h"
static const char *get_mode(const char *str, unsigned int *modep)
{
unsigned char c;
unsigned int mode = 0;
if (*str == ' ')
return NULL;
while ((c = *str++) != ' ') {
if (c < '0' || c > '7')
return NULL;
mode = (mode << 3) + (c - '0');
}
*modep = mode;
return str;
}
static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned long size, struct strbuf *err)
{
const char *path;
unsigned int mode, len;
const unsigned hashsz = the_hash_algo->rawsz;
if (size < hashsz + 3 || buf[size - (hashsz + 1)]) {
strbuf_addstr(err, _("too-short tree object"));
return -1;
}
path = get_mode(buf, &mode);
if (!path) {
strbuf_addstr(err, _("malformed mode in tree entry"));
return -1;
}
if (!*path) {
strbuf_addstr(err, _("empty filename in tree entry"));
return -1;
}
len = strlen(path) + 1;
/* Initialize the descriptor entry */
desc->entry.path = path;
desc->entry.mode = canon_mode(mode);
desc->entry.pathlen = len - 1;
oidread(&desc->entry.oid, (const unsigned char *)path + len);
return 0;
}
static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, unsigned long size, struct strbuf *err)
{
desc->buffer = buffer;
desc->size = size;
if (size)
return decode_tree_entry(desc, buffer, size, err);
return 0;
}
void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size)
{
struct strbuf err = STRBUF_INIT;
if (init_tree_desc_internal(desc, buffer, size, &err))
die("%s", err.buf);
strbuf_release(&err);
}
int init_tree_desc_gently(struct tree_desc *desc, const void *buffer, unsigned long size)
{
struct strbuf err = STRBUF_INIT;
int result = init_tree_desc_internal(desc, buffer, size, &err);
if (result)
error("%s", err.buf);
strbuf_release(&err);
return result;
}
void *fill_tree_descriptor(struct repository *r,
struct tree_desc *desc,
const struct object_id *oid)
{
unsigned long size = 0;
void *buf = NULL;
if (oid) {
buf = read_object_with_reference(r, oid, tree_type, &size, NULL);
if (!buf)
die("unable to read tree %s", oid_to_hex(oid));
}
init_tree_desc(desc, buf, size);
return buf;
}
static void entry_clear(struct name_entry *a)
{
memset(a, 0, sizeof(*a));
}
static void entry_extract(struct tree_desc *t, struct name_entry *a)
{
*a = t->entry;
}
static int update_tree_entry_internal(struct tree_desc *desc, struct strbuf *err)
{
const void *buf = desc->buffer;
const unsigned char *end = (const unsigned char *)desc->entry.path + desc->entry.pathlen + 1 + the_hash_algo->rawsz;
unsigned long size = desc->size;
unsigned long len = end - (const unsigned char *)buf;
if (size < len)
die(_("too-short tree file"));
|