mirror of
https://github.com/git/git.git
synced 2024-11-17 14:34:49 +01:00
Merge branch 'jc/lt-tree-n-cache-tree' into next
* jc/lt-tree-n-cache-tree: Remove "tree->entries" tree-entry list from tree parser Switch "read_tree_recursive()" over to tree-walk functionality Make "tree_entry" have a SHA1 instead of a union of object pointers Add raw tree buffer info to "struct tree" Don't use "sscanf()" for tree mode scanning git-fetch: avoid using "case ... in (arm)"
This commit is contained in:
commit
52bc0e294c
13 changed files with 220 additions and 123 deletions
4
blame.c
4
blame.c
|
@ -149,7 +149,7 @@ static void free_patch(struct patch *p)
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_blob_sha1_internal(unsigned char *sha1, const char *base,
|
static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
|
||||||
int baselen, const char *pathname,
|
int baselen, const char *pathname,
|
||||||
unsigned mode, int stage);
|
unsigned mode, int stage);
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ static int get_blob_sha1(struct tree *t, const char *pathname,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_blob_sha1_internal(unsigned char *sha1, const char *base,
|
static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
|
||||||
int baselen, const char *pathname,
|
int baselen, const char *pathname,
|
||||||
unsigned mode, int stage)
|
unsigned mode, int stage)
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,7 +53,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int show_tree(unsigned char *sha1, const char *base, int baselen,
|
static int show_tree(const unsigned char *sha1, const char *base, int baselen,
|
||||||
const char *pathname, unsigned mode, int stage)
|
const char *pathname, unsigned mode, int stage)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "cache-tree.h"
|
#include "cache-tree.h"
|
||||||
|
#include "tree-walk.h"
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
|
@ -40,7 +41,7 @@ static struct tree_entry_list df_conflict_list = {
|
||||||
|
|
||||||
typedef int (*merge_fn_t)(struct cache_entry **src);
|
typedef int (*merge_fn_t)(struct cache_entry **src);
|
||||||
|
|
||||||
static int entcmp(char *name1, int dir1, char *name2, int dir2)
|
static int entcmp(const char *name1, int dir1, const char *name2, int dir2)
|
||||||
{
|
{
|
||||||
int len1 = strlen(name1);
|
int len1 = strlen(name1);
|
||||||
int len2 = strlen(name2);
|
int len2 = strlen(name2);
|
||||||
|
@ -68,7 +69,7 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
|
||||||
int src_size = len + 1;
|
int src_size = len + 1;
|
||||||
do {
|
do {
|
||||||
int i;
|
int i;
|
||||||
char *first;
|
const char *first;
|
||||||
int firstdir = 0;
|
int firstdir = 0;
|
||||||
int pathlen;
|
int pathlen;
|
||||||
unsigned ce_size;
|
unsigned ce_size;
|
||||||
|
@ -162,9 +163,10 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (posns[i]->directory) {
|
if (posns[i]->directory) {
|
||||||
|
struct tree *tree = lookup_tree(posns[i]->sha1);
|
||||||
any_dirs = 1;
|
any_dirs = 1;
|
||||||
parse_tree(posns[i]->item.tree);
|
parse_tree(tree);
|
||||||
subposns[i] = posns[i]->item.tree->entries;
|
subposns[i] = create_tree_entry_list(tree);
|
||||||
posns[i] = posns[i]->next;
|
posns[i] = posns[i]->next;
|
||||||
src[i + merge] = &df_conflict_entry;
|
src[i + merge] = &df_conflict_entry;
|
||||||
continue;
|
continue;
|
||||||
|
@ -188,7 +190,7 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
|
||||||
|
|
||||||
any_files = 1;
|
any_files = 1;
|
||||||
|
|
||||||
memcpy(ce->sha1, posns[i]->item.any->sha1, 20);
|
memcpy(ce->sha1, posns[i]->sha1, 20);
|
||||||
src[i + merge] = ce;
|
src[i + merge] = ce;
|
||||||
subposns[i] = &df_conflict_list;
|
subposns[i] = &df_conflict_list;
|
||||||
posns[i] = posns[i]->next;
|
posns[i] = posns[i]->next;
|
||||||
|
@ -369,7 +371,7 @@ static int unpack_trees(merge_fn_t fn)
|
||||||
if (len) {
|
if (len) {
|
||||||
posns = xmalloc(len * sizeof(struct tree_entry_list *));
|
posns = xmalloc(len * sizeof(struct tree_entry_list *));
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
posns[i] = ((struct tree *) posn->item)->entries;
|
posns[i] = create_tree_entry_list((struct tree *) posn->item);
|
||||||
posn = posn->next;
|
posn = posn->next;
|
||||||
}
|
}
|
||||||
if (unpack_trees_rec(posns, len, prefix ? prefix : "",
|
if (unpack_trees_rec(posns, len, prefix ? prefix : "",
|
||||||
|
@ -800,19 +802,31 @@ static int read_cache_unmerged(void)
|
||||||
|
|
||||||
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
|
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
|
||||||
{
|
{
|
||||||
struct tree_entry_list *ent;
|
struct tree_desc desc;
|
||||||
int cnt;
|
int cnt = 0;
|
||||||
|
|
||||||
memcpy(it->sha1, tree->object.sha1, 20);
|
memcpy(it->sha1, tree->object.sha1, 20);
|
||||||
for (cnt = 0, ent = tree->entries; ent; ent = ent->next) {
|
desc.buf = tree->buffer;
|
||||||
if (!ent->directory)
|
desc.size = tree->size;
|
||||||
|
|
||||||
|
while (desc.size) {
|
||||||
|
unsigned mode;
|
||||||
|
const char *name;
|
||||||
|
const unsigned char *sha1;
|
||||||
|
|
||||||
|
sha1 = tree_entry_extract(&desc, &name, &mode);
|
||||||
|
update_tree_entry(&desc);
|
||||||
|
|
||||||
|
if (!S_ISDIR(mode))
|
||||||
cnt++;
|
cnt++;
|
||||||
else {
|
else {
|
||||||
struct cache_tree_sub *sub;
|
struct cache_tree_sub *sub;
|
||||||
struct tree *subtree = (struct tree *)ent->item.tree;
|
struct tree *subtree;
|
||||||
|
|
||||||
|
subtree = lookup_tree(sha1);
|
||||||
if (!subtree->object.parsed)
|
if (!subtree->object.parsed)
|
||||||
parse_tree(subtree);
|
parse_tree(subtree);
|
||||||
sub = cache_tree_sub(it, ent->name);
|
sub = cache_tree_sub(it, name);
|
||||||
sub->cache_tree = cache_tree();
|
sub->cache_tree = cache_tree();
|
||||||
prime_cache_tree_rec(sub->cache_tree, subtree);
|
prime_cache_tree_rec(sub->cache_tree, subtree);
|
||||||
cnt += sub->cache_tree->entry_count;
|
cnt += sub->cache_tree->entry_count;
|
||||||
|
|
|
@ -113,7 +113,7 @@ static struct object_list **process_tree(struct tree *tree,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
struct object *obj = &tree->object;
|
struct object *obj = &tree->object;
|
||||||
struct tree_entry_list *entry;
|
struct tree_desc desc;
|
||||||
struct name_path me;
|
struct name_path me;
|
||||||
|
|
||||||
if (!revs.tree_objects)
|
if (!revs.tree_objects)
|
||||||
|
@ -128,18 +128,25 @@ static struct object_list **process_tree(struct tree *tree,
|
||||||
me.up = path;
|
me.up = path;
|
||||||
me.elem = name;
|
me.elem = name;
|
||||||
me.elem_len = strlen(name);
|
me.elem_len = strlen(name);
|
||||||
entry = tree->entries;
|
|
||||||
tree->entries = NULL;
|
desc.buf = tree->buffer;
|
||||||
while (entry) {
|
desc.size = tree->size;
|
||||||
struct tree_entry_list *next = entry->next;
|
|
||||||
if (entry->directory)
|
while (desc.size) {
|
||||||
p = process_tree(entry->item.tree, p, &me, entry->name);
|
unsigned mode;
|
||||||
|
const char *name;
|
||||||
|
const unsigned char *sha1;
|
||||||
|
|
||||||
|
sha1 = tree_entry_extract(&desc, &name, &mode);
|
||||||
|
update_tree_entry(&desc);
|
||||||
|
|
||||||
|
if (S_ISDIR(mode))
|
||||||
|
p = process_tree(lookup_tree(sha1), p, &me, name);
|
||||||
else
|
else
|
||||||
p = process_blob(entry->item.blob, p, &me, entry->name);
|
p = process_blob(lookup_blob(sha1), p, &me, name);
|
||||||
free(entry->name);
|
|
||||||
free(entry);
|
|
||||||
entry = next;
|
|
||||||
}
|
}
|
||||||
|
free(tree->buffer);
|
||||||
|
tree->buffer = NULL;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
fetch.c
16
fetch.c
|
@ -42,16 +42,22 @@ static int process_tree(struct tree *tree)
|
||||||
if (parse_tree(tree))
|
if (parse_tree(tree))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
entry = tree->entries;
|
entry = create_tree_entry_list(tree);
|
||||||
tree->entries = NULL;
|
|
||||||
while (entry) {
|
while (entry) {
|
||||||
struct tree_entry_list *next = entry->next;
|
struct tree_entry_list *next = entry->next;
|
||||||
if (process(entry->item.any))
|
|
||||||
return -1;
|
if (entry->directory) {
|
||||||
free(entry->name);
|
struct tree *tree = lookup_tree(entry->sha1);
|
||||||
|
process_tree(tree);
|
||||||
|
} else {
|
||||||
|
struct blob *blob = lookup_blob(entry->sha1);
|
||||||
|
process(&blob->object);
|
||||||
|
}
|
||||||
free(entry);
|
free(entry);
|
||||||
entry = next;
|
entry = next;
|
||||||
}
|
}
|
||||||
|
free(tree->buffer);
|
||||||
|
tree->buffer = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "cache-tree.h"
|
#include "cache-tree.h"
|
||||||
|
|
||||||
#define REACHABLE 0x0001
|
#define REACHABLE 0x0001
|
||||||
|
#define SEEN 0x0002
|
||||||
|
|
||||||
static int show_root = 0;
|
static int show_root = 0;
|
||||||
static int show_tags = 0;
|
static int show_tags = 0;
|
||||||
|
@ -161,7 +162,7 @@ static int fsck_tree(struct tree *item)
|
||||||
struct tree_entry_list *entry, *last;
|
struct tree_entry_list *entry, *last;
|
||||||
|
|
||||||
last = NULL;
|
last = NULL;
|
||||||
for (entry = item->entries; entry; entry = entry->next) {
|
for (entry = create_tree_entry_list(item); entry; entry = entry->next) {
|
||||||
if (strchr(entry->name, '/'))
|
if (strchr(entry->name, '/'))
|
||||||
has_full_path = 1;
|
has_full_path = 1;
|
||||||
has_zero_pad |= entry->zeropad;
|
has_zero_pad |= entry->zeropad;
|
||||||
|
@ -198,17 +199,15 @@ static int fsck_tree(struct tree *item)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(last->name);
|
|
||||||
free(last);
|
free(last);
|
||||||
}
|
}
|
||||||
|
|
||||||
last = entry;
|
last = entry;
|
||||||
}
|
}
|
||||||
if (last) {
|
if (last)
|
||||||
free(last->name);
|
|
||||||
free(last);
|
free(last);
|
||||||
}
|
free(item->buffer);
|
||||||
item->entries = NULL;
|
item->buffer = NULL;
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
if (has_full_path) {
|
if (has_full_path) {
|
||||||
|
@ -278,6 +277,9 @@ static int fsck_sha1(unsigned char *sha1)
|
||||||
struct object *obj = parse_object(sha1);
|
struct object *obj = parse_object(sha1);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return error("%s: object not found", sha1_to_hex(sha1));
|
return error("%s: object not found", sha1_to_hex(sha1));
|
||||||
|
if (obj->flags & SEEN)
|
||||||
|
return 0;
|
||||||
|
obj->flags |= SEEN;
|
||||||
if (obj->type == blob_type)
|
if (obj->type == blob_type)
|
||||||
return 0;
|
return 0;
|
||||||
if (obj->type == tree_type)
|
if (obj->type == tree_type)
|
||||||
|
@ -465,6 +467,7 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i, heads;
|
int i, heads;
|
||||||
|
|
||||||
|
track_object_refs = 1;
|
||||||
setup_git_directory();
|
setup_git_directory();
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
|
|
|
@ -211,12 +211,12 @@ esac
|
||||||
reflist=$(get_remote_refs_for_fetch "$@")
|
reflist=$(get_remote_refs_for_fetch "$@")
|
||||||
if test "$tags"
|
if test "$tags"
|
||||||
then
|
then
|
||||||
taglist=$(IFS=" " &&
|
taglist=`IFS=" " &&
|
||||||
git-ls-remote $upload_pack --tags "$remote" |
|
git-ls-remote $upload_pack --tags "$remote" |
|
||||||
while read sha1 name
|
while read sha1 name
|
||||||
do
|
do
|
||||||
case "$name" in
|
case "$name" in
|
||||||
(*^*) continue ;;
|
*^*) continue ;;
|
||||||
esac
|
esac
|
||||||
if git-check-ref-format "$name"
|
if git-check-ref-format "$name"
|
||||||
then
|
then
|
||||||
|
@ -224,7 +224,7 @@ then
|
||||||
else
|
else
|
||||||
echo >&2 "warning: tag ${name} ignored"
|
echo >&2 "warning: tag ${name} ignored"
|
||||||
fi
|
fi
|
||||||
done)
|
done`
|
||||||
if test "$#" -gt 1
|
if test "$#" -gt 1
|
||||||
then
|
then
|
||||||
# remote URL plus explicit refspecs; we need to merge them.
|
# remote URL plus explicit refspecs; we need to merge them.
|
||||||
|
|
30
http-push.c
30
http-push.c
|
@ -1704,6 +1704,7 @@ static struct object_list **process_blob(struct blob *blob,
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
obj->flags |= SEEN;
|
obj->flags |= SEEN;
|
||||||
|
name = strdup(name);
|
||||||
return add_object(obj, p, path, name);
|
return add_object(obj, p, path, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1713,7 +1714,7 @@ static struct object_list **process_tree(struct tree *tree,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
struct object *obj = &tree->object;
|
struct object *obj = &tree->object;
|
||||||
struct tree_entry_list *entry;
|
struct tree_desc desc;
|
||||||
struct name_path me;
|
struct name_path me;
|
||||||
|
|
||||||
obj->flags |= LOCAL;
|
obj->flags |= LOCAL;
|
||||||
|
@ -1724,21 +1725,30 @@ static struct object_list **process_tree(struct tree *tree,
|
||||||
die("bad tree object %s", sha1_to_hex(obj->sha1));
|
die("bad tree object %s", sha1_to_hex(obj->sha1));
|
||||||
|
|
||||||
obj->flags |= SEEN;
|
obj->flags |= SEEN;
|
||||||
|
name = strdup(name);
|
||||||
p = add_object(obj, p, NULL, name);
|
p = add_object(obj, p, NULL, name);
|
||||||
me.up = path;
|
me.up = path;
|
||||||
me.elem = name;
|
me.elem = name;
|
||||||
me.elem_len = strlen(name);
|
me.elem_len = strlen(name);
|
||||||
entry = tree->entries;
|
|
||||||
tree->entries = NULL;
|
desc.buf = tree->buffer;
|
||||||
while (entry) {
|
desc.size = tree->size;
|
||||||
struct tree_entry_list *next = entry->next;
|
|
||||||
if (entry->directory)
|
while (desc.size) {
|
||||||
p = process_tree(entry->item.tree, p, &me, entry->name);
|
unsigned mode;
|
||||||
|
const char *name;
|
||||||
|
const unsigned char *sha1;
|
||||||
|
|
||||||
|
sha1 = tree_entry_extract(&desc, &name, &mode);
|
||||||
|
update_tree_entry(&desc);
|
||||||
|
|
||||||
|
if (S_ISDIR(mode))
|
||||||
|
p = process_tree(lookup_tree(sha1), p, &me, name);
|
||||||
else
|
else
|
||||||
p = process_blob(entry->item.blob, p, &me, entry->name);
|
p = process_blob(lookup_blob(sha1), p, &me, name);
|
||||||
free(entry);
|
|
||||||
entry = next;
|
|
||||||
}
|
}
|
||||||
|
free(tree->buffer);
|
||||||
|
tree->buffer = NULL;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
object.c
7
object.c
|
@ -9,7 +9,7 @@ struct object **objs;
|
||||||
static int nr_objs;
|
static int nr_objs;
|
||||||
int obj_allocs;
|
int obj_allocs;
|
||||||
|
|
||||||
int track_object_refs = 1;
|
int track_object_refs = 0;
|
||||||
|
|
||||||
static int hashtable_index(const unsigned char *sha1)
|
static int hashtable_index(const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
|
@ -200,8 +200,11 @@ struct object *parse_object(const unsigned char *sha1)
|
||||||
obj = &blob->object;
|
obj = &blob->object;
|
||||||
} else if (!strcmp(type, tree_type)) {
|
} else if (!strcmp(type, tree_type)) {
|
||||||
struct tree *tree = lookup_tree(sha1);
|
struct tree *tree = lookup_tree(sha1);
|
||||||
parse_tree_buffer(tree, buffer, size);
|
|
||||||
obj = &tree->object;
|
obj = &tree->object;
|
||||||
|
if (!tree->object.parsed) {
|
||||||
|
parse_tree_buffer(tree, buffer, size);
|
||||||
|
buffer = NULL;
|
||||||
|
}
|
||||||
} else if (!strcmp(type, commit_type)) {
|
} else if (!strcmp(type, commit_type)) {
|
||||||
struct commit *commit = lookup_commit(sha1);
|
struct commit *commit = lookup_commit(sha1);
|
||||||
parse_commit_buffer(commit, buffer, size);
|
parse_commit_buffer(commit, buffer, size);
|
||||||
|
|
|
@ -63,14 +63,13 @@ void mark_tree_uninteresting(struct tree *tree)
|
||||||
return;
|
return;
|
||||||
if (parse_tree(tree) < 0)
|
if (parse_tree(tree) < 0)
|
||||||
die("bad tree %s", sha1_to_hex(obj->sha1));
|
die("bad tree %s", sha1_to_hex(obj->sha1));
|
||||||
entry = tree->entries;
|
entry = create_tree_entry_list(tree);
|
||||||
tree->entries = NULL;
|
|
||||||
while (entry) {
|
while (entry) {
|
||||||
struct tree_entry_list *next = entry->next;
|
struct tree_entry_list *next = entry->next;
|
||||||
if (entry->directory)
|
if (entry->directory)
|
||||||
mark_tree_uninteresting(entry->item.tree);
|
mark_tree_uninteresting(lookup_tree(entry->sha1));
|
||||||
else
|
else
|
||||||
mark_blob_uninteresting(entry->item.blob);
|
mark_blob_uninteresting(lookup_blob(entry->sha1));
|
||||||
free(entry);
|
free(entry);
|
||||||
entry = next;
|
entry = next;
|
||||||
}
|
}
|
||||||
|
|
21
tree-walk.c
21
tree-walk.c
|
@ -47,18 +47,33 @@ void update_tree_entry(struct tree_desc *desc)
|
||||||
desc->size = size - len;
|
desc->size = size - len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *get_mode(const char *str, unsigned int *modep)
|
||||||
|
{
|
||||||
|
unsigned char c;
|
||||||
|
unsigned int mode = 0;
|
||||||
|
|
||||||
|
while ((c = *str++) != ' ') {
|
||||||
|
if (c < '0' || c > '7')
|
||||||
|
return NULL;
|
||||||
|
mode = (mode << 3) + (c - '0');
|
||||||
|
}
|
||||||
|
*modep = mode;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep)
|
const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep)
|
||||||
{
|
{
|
||||||
void *tree = desc->buf;
|
void *tree = desc->buf;
|
||||||
unsigned long size = desc->size;
|
unsigned long size = desc->size;
|
||||||
int len = strlen(tree)+1;
|
int len = strlen(tree)+1;
|
||||||
const unsigned char *sha1 = tree + len;
|
const unsigned char *sha1 = tree + len;
|
||||||
const char *path = strchr(tree, ' ');
|
const char *path;
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
|
|
||||||
if (!path || size < len + 20 || sscanf(tree, "%o", &mode) != 1)
|
path = get_mode(tree, &mode);
|
||||||
|
if (!path || size < len + 20)
|
||||||
die("corrupt tree file");
|
die("corrupt tree file");
|
||||||
*pathp = path+1;
|
*pathp = path;
|
||||||
*modep = canon_mode(mode);
|
*modep = canon_mode(mode);
|
||||||
return sha1;
|
return sha1;
|
||||||
}
|
}
|
||||||
|
|
152
tree.c
152
tree.c
|
@ -3,11 +3,12 @@
|
||||||
#include "blob.h"
|
#include "blob.h"
|
||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
#include "tree-walk.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
const char *tree_type = "tree";
|
const char *tree_type = "tree";
|
||||||
|
|
||||||
static int read_one_entry(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
|
static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
@ -77,19 +78,26 @@ int read_tree_recursive(struct tree *tree,
|
||||||
int stage, const char **match,
|
int stage, const char **match,
|
||||||
read_tree_fn_t fn)
|
read_tree_fn_t fn)
|
||||||
{
|
{
|
||||||
struct tree_entry_list *list;
|
struct tree_desc desc;
|
||||||
|
|
||||||
if (parse_tree(tree))
|
if (parse_tree(tree))
|
||||||
return -1;
|
return -1;
|
||||||
list = tree->entries;
|
|
||||||
while (list) {
|
desc.buf = tree->buffer;
|
||||||
struct tree_entry_list *current = list;
|
desc.size = tree->size;
|
||||||
list = list->next;
|
|
||||||
if (!match_tree_entry(base, baselen, current->name,
|
while (desc.size) {
|
||||||
current->mode, match))
|
unsigned mode;
|
||||||
|
const char *name;
|
||||||
|
const unsigned char *sha1;
|
||||||
|
|
||||||
|
sha1 = tree_entry_extract(&desc, &name, &mode);
|
||||||
|
update_tree_entry(&desc);
|
||||||
|
|
||||||
|
if (!match_tree_entry(base, baselen, name, mode, match))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (fn(current->item.any->sha1, base, baselen,
|
switch (fn(sha1, base, baselen, name, mode, stage)) {
|
||||||
current->name, current->mode, stage)) {
|
|
||||||
case 0:
|
case 0:
|
||||||
continue;
|
continue;
|
||||||
case READ_TREE_RECURSIVE:
|
case READ_TREE_RECURSIVE:
|
||||||
|
@ -97,16 +105,16 @@ int read_tree_recursive(struct tree *tree,
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (current->directory) {
|
if (S_ISDIR(mode)) {
|
||||||
int retval;
|
int retval;
|
||||||
int pathlen = strlen(current->name);
|
int pathlen = strlen(name);
|
||||||
char *newbase;
|
char *newbase;
|
||||||
|
|
||||||
newbase = xmalloc(baselen + 1 + pathlen);
|
newbase = xmalloc(baselen + 1 + pathlen);
|
||||||
memcpy(newbase, base, baselen);
|
memcpy(newbase, base, baselen);
|
||||||
memcpy(newbase + baselen, current->name, pathlen);
|
memcpy(newbase + baselen, name, pathlen);
|
||||||
newbase[baselen + pathlen] = '/';
|
newbase[baselen + pathlen] = '/';
|
||||||
retval = read_tree_recursive(current->item.tree,
|
retval = read_tree_recursive(lookup_tree(sha1),
|
||||||
newbase,
|
newbase,
|
||||||
baselen + pathlen + 1,
|
baselen + pathlen + 1,
|
||||||
stage, match, fn);
|
stage, match, fn);
|
||||||
|
@ -143,62 +151,97 @@ struct tree *lookup_tree(const unsigned char *sha1)
|
||||||
return (struct tree *) obj;
|
return (struct tree *) obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int track_tree_refs(struct tree *item)
|
||||||
|
{
|
||||||
|
int n_refs = 0, i;
|
||||||
|
struct object_refs *refs;
|
||||||
|
struct tree_desc desc;
|
||||||
|
|
||||||
|
/* Count how many entries there are.. */
|
||||||
|
desc.buf = item->buffer;
|
||||||
|
desc.size = item->size;
|
||||||
|
while (desc.size) {
|
||||||
|
n_refs++;
|
||||||
|
update_tree_entry(&desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate object refs and walk it again.. */
|
||||||
|
i = 0;
|
||||||
|
refs = alloc_object_refs(n_refs);
|
||||||
|
desc.buf = item->buffer;
|
||||||
|
desc.size = item->size;
|
||||||
|
while (desc.size) {
|
||||||
|
unsigned mode;
|
||||||
|
const char *name;
|
||||||
|
const unsigned char *sha1;
|
||||||
|
struct object *obj;
|
||||||
|
|
||||||
|
sha1 = tree_entry_extract(&desc, &name, &mode);
|
||||||
|
update_tree_entry(&desc);
|
||||||
|
if (S_ISDIR(mode))
|
||||||
|
obj = &lookup_tree(sha1)->object;
|
||||||
|
else
|
||||||
|
obj = &lookup_blob(sha1)->object;
|
||||||
|
refs->ref[i++] = obj;
|
||||||
|
}
|
||||||
|
set_object_refs(&item->object, refs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
|
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
|
||||||
{
|
{
|
||||||
void *bufptr = buffer;
|
|
||||||
struct tree_entry_list **list_p;
|
|
||||||
int n_refs = 0;
|
|
||||||
|
|
||||||
if (item->object.parsed)
|
if (item->object.parsed)
|
||||||
return 0;
|
return 0;
|
||||||
item->object.parsed = 1;
|
item->object.parsed = 1;
|
||||||
list_p = &item->entries;
|
item->buffer = buffer;
|
||||||
while (size) {
|
item->size = size;
|
||||||
struct object *obj;
|
|
||||||
|
if (track_object_refs)
|
||||||
|
track_tree_refs(item);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tree_entry_list *create_tree_entry_list(struct tree *tree)
|
||||||
|
{
|
||||||
|
struct tree_desc desc;
|
||||||
|
struct tree_entry_list *ret = NULL;
|
||||||
|
struct tree_entry_list **list_p = &ret;
|
||||||
|
|
||||||
|
desc.buf = tree->buffer;
|
||||||
|
desc.size = tree->size;
|
||||||
|
|
||||||
|
while (desc.size) {
|
||||||
|
unsigned mode;
|
||||||
|
const char *path;
|
||||||
|
const unsigned char *sha1;
|
||||||
struct tree_entry_list *entry;
|
struct tree_entry_list *entry;
|
||||||
int len = 1+strlen(bufptr);
|
|
||||||
unsigned char *file_sha1 = bufptr + len;
|
sha1 = tree_entry_extract(&desc, &path, &mode);
|
||||||
char *path = strchr(bufptr, ' ');
|
|
||||||
unsigned int mode;
|
|
||||||
if (size < len + 20 || !path ||
|
|
||||||
sscanf(bufptr, "%o", &mode) != 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
entry = xmalloc(sizeof(struct tree_entry_list));
|
entry = xmalloc(sizeof(struct tree_entry_list));
|
||||||
entry->name = strdup(path + 1);
|
entry->name = path;
|
||||||
|
entry->sha1 = sha1;
|
||||||
|
entry->mode = mode;
|
||||||
entry->directory = S_ISDIR(mode) != 0;
|
entry->directory = S_ISDIR(mode) != 0;
|
||||||
entry->executable = (mode & S_IXUSR) != 0;
|
entry->executable = (mode & S_IXUSR) != 0;
|
||||||
entry->symlink = S_ISLNK(mode) != 0;
|
entry->symlink = S_ISLNK(mode) != 0;
|
||||||
entry->zeropad = *(char *)bufptr == '0';
|
entry->zeropad = *(const char *)(desc.buf) == '0';
|
||||||
entry->mode = mode;
|
|
||||||
entry->next = NULL;
|
entry->next = NULL;
|
||||||
|
|
||||||
bufptr += len + 20;
|
update_tree_entry(&desc);
|
||||||
size -= len + 20;
|
|
||||||
|
|
||||||
if (entry->directory) {
|
|
||||||
entry->item.tree = lookup_tree(file_sha1);
|
|
||||||
obj = &entry->item.tree->object;
|
|
||||||
} else {
|
|
||||||
entry->item.blob = lookup_blob(file_sha1);
|
|
||||||
obj = &entry->item.blob->object;
|
|
||||||
}
|
|
||||||
if (obj)
|
|
||||||
n_refs++;
|
|
||||||
*list_p = entry;
|
*list_p = entry;
|
||||||
list_p = &entry->next;
|
list_p = &entry->next;
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (track_object_refs) {
|
void free_tree_entry_list(struct tree_entry_list *list)
|
||||||
struct tree_entry_list *entry;
|
{
|
||||||
unsigned i = 0;
|
while (list) {
|
||||||
struct object_refs *refs = alloc_object_refs(n_refs);
|
struct tree_entry_list *next = list->next;
|
||||||
for (entry = item->entries; entry; entry = entry->next)
|
free(list);
|
||||||
refs->ref[i++] = entry->item.any;
|
list = next;
|
||||||
set_object_refs(&item->object, refs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_tree(struct tree *item)
|
int parse_tree(struct tree *item)
|
||||||
|
@ -206,7 +249,6 @@ int parse_tree(struct tree *item)
|
||||||
char type[20];
|
char type[20];
|
||||||
void *buffer;
|
void *buffer;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (item->object.parsed)
|
if (item->object.parsed)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -219,9 +261,7 @@ int parse_tree(struct tree *item)
|
||||||
return error("Object %s not a tree",
|
return error("Object %s not a tree",
|
||||||
sha1_to_hex(item->object.sha1));
|
sha1_to_hex(item->object.sha1));
|
||||||
}
|
}
|
||||||
ret = parse_tree_buffer(item, buffer, size);
|
return parse_tree_buffer(item, buffer, size);
|
||||||
free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tree *parse_tree_indirect(const unsigned char *sha1)
|
struct tree *parse_tree_indirect(const unsigned char *sha1)
|
||||||
|
|
16
tree.h
16
tree.h
|
@ -12,19 +12,19 @@ struct tree_entry_list {
|
||||||
unsigned symlink : 1;
|
unsigned symlink : 1;
|
||||||
unsigned zeropad : 1;
|
unsigned zeropad : 1;
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
char *name;
|
const char *name;
|
||||||
union {
|
const unsigned char *sha1;
|
||||||
struct object *any;
|
|
||||||
struct tree *tree;
|
|
||||||
struct blob *blob;
|
|
||||||
} item;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tree {
|
struct tree {
|
||||||
struct object object;
|
struct object object;
|
||||||
struct tree_entry_list *entries;
|
void *buffer;
|
||||||
|
unsigned long size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tree_entry_list *create_tree_entry_list(struct tree *);
|
||||||
|
void free_tree_entry_list(struct tree_entry_list *);
|
||||||
|
|
||||||
struct tree *lookup_tree(const unsigned char *sha1);
|
struct tree *lookup_tree(const unsigned char *sha1);
|
||||||
|
|
||||||
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size);
|
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size);
|
||||||
|
@ -35,7 +35,7 @@ int parse_tree(struct tree *tree);
|
||||||
struct tree *parse_tree_indirect(const unsigned char *sha1);
|
struct tree *parse_tree_indirect(const unsigned char *sha1);
|
||||||
|
|
||||||
#define READ_TREE_RECURSIVE 1
|
#define READ_TREE_RECURSIVE 1
|
||||||
typedef int (*read_tree_fn_t)(unsigned char *, const char *, int, const char *, unsigned int, int);
|
typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int);
|
||||||
|
|
||||||
extern int read_tree_recursive(struct tree *tree,
|
extern int read_tree_recursive(struct tree *tree,
|
||||||
const char *base, int baselen,
|
const char *base, int baselen,
|
||||||
|
|
Loading…
Reference in a new issue