@ -22,33 +22,60 @@ static const char *get_mode(const char *str, unsigned int *modep)
return str;
return str;
}
}
static void decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned long size)
static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned long size, struct strbuf *err)
{
{
const char *path;
const char *path;
unsigned int mode, len;
unsigned int mode, len;
if (size < 23 || buf[size - 21])
if (size < 23 || buf[size - 21]) {
die(_("too-short tree object"));
strbuf_addstr(err, _("too-short tree object"));
return -1;
}
path = get_mode(buf, &mode);
path = get_mode(buf, &mode);
if (!path)
if (!path) {
die(_("malformed mode in tree entry for tree"));
strbuf_addstr(err, _("malformed mode in tree entry"));
if (!*path)
return -1;
die(_("empty filename in tree entry for tree"));
}
if (!*path) {
strbuf_addstr(err, _("empty filename in tree entry"));
return -1;
}
len = strlen(path) + 1;
len = strlen(path) + 1;
/* Initialize the descriptor entry */
/* Initialize the descriptor entry */
desc->entry.path = path;
desc->entry.path = path;
desc->entry.mode = canon_mode(mode);
desc->entry.mode = canon_mode(mode);
desc->entry.oid = (const struct object_id *)(path + len);
desc->entry.oid = (const struct object_id *)(path + len);
return 0;
}
}
void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size)
static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, unsigned long size, struct strbuf *err)
{
{
desc->buffer = buffer;
desc->buffer = buffer;
desc->size = size;
desc->size = size;
if (size)
if (size)
decode_tree_entry(desc, buffer, 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 tree_desc *desc, const unsigned char *sha1)
void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1)
@ -75,7 +102,7 @@ static void entry_extract(struct tree_desc *t, struct name_entry *a)
*a = t->entry;
*a = t->entry;
}
}
void update_tree_entry(struct tree_desc *desc)
static int update_tree_entry_internal(struct tree_desc *desc, struct strbuf *err)
{
{
const void *buf = desc->buffer;
const void *buf = desc->buffer;
const unsigned char *end = desc->entry.oid->hash + 20;
const unsigned char *end = desc->entry.oid->hash + 20;
@ -89,7 +116,30 @@ void update_tree_entry(struct tree_desc *desc)
desc->buffer = buf;
desc->buffer = buf;
desc->size = size;
desc->size = size;
if (size)
if (size)
decode_tree_entry(desc, buf, size);
return decode_tree_entry(desc, buf, size, err);
return 0;
}
void update_tree_entry(struct tree_desc *desc)
{
struct strbuf err = STRBUF_INIT;
if (update_tree_entry_internal(desc, &err))
die("%s", err.buf);
strbuf_release(&err);
}
int update_tree_entry_gently(struct tree_desc *desc)
{
struct strbuf err = STRBUF_INIT;
if (update_tree_entry_internal(desc, &err)) {
error("%s", err.buf);
strbuf_release(&err);
/* Stop processing this tree after error */
desc->size = 0;
return -1;
}
strbuf_release(&err);
return 0;
}
}
int tree_entry(struct tree_desc *desc, struct name_entry *entry)
int tree_entry(struct tree_desc *desc, struct name_entry *entry)
@ -102,6 +152,17 @@ int tree_entry(struct tree_desc *desc, struct name_entry *entry)
return 1;
return 1;
}
}
int tree_entry_gently(struct tree_desc *desc, struct name_entry *entry)
{
if (!desc->size)
return 0;
*entry = desc->entry;
if (update_tree_entry_gently(desc))
return 0;
return 1;
}
void setup_traverse_info(struct traverse_info *info, const char *base)
void setup_traverse_info(struct traverse_info *info, const char *base)
{
{
int pathlen = strlen(base);
int pathlen = strlen(base);