Пример #1
0
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
{
	struct tree_desc desc;
	struct name_entry entry;
	int cnt;

	hashcpy(it->sha1, tree->object.sha1);
	init_tree_desc(&desc, tree->buffer, tree->size);
	cnt = 0;
	while (tree_entry(&desc, &entry)) {
		if (!S_ISDIR(entry.mode))
			cnt++;
		else {
			struct cache_tree_sub *sub;
			struct tree *subtree = lookup_tree(entry.sha1);
			if (!subtree->object.parsed)
				parse_tree(subtree);
			sub = cache_tree_sub(it, entry.path);
			sub->cache_tree = cache_tree();
			prime_cache_tree_rec(sub->cache_tree, subtree);
			cnt += sub->cache_tree->entry_count;
		}
	}
	it->entry_count = cnt;
}
Пример #2
0
static int process_tree(struct walker *walker, struct tree *tree)
{
	struct tree_desc desc;
	struct name_entry entry;

	if (parse_tree(tree))
		return -1;

	init_tree_desc(&desc, tree->buffer, tree->size);
	while (tree_entry(&desc, &entry)) {
		struct object *obj = NULL;

		/* submodule commits are not stored in the superproject */
		if (S_ISGITLINK(entry.mode))
			continue;
		if (S_ISDIR(entry.mode)) {
			struct tree *tree = lookup_tree(entry.sha1);
			if (tree)
				obj = &tree->object;
		}
		else {
			struct blob *blob = lookup_blob(entry.sha1);
			if (blob)
				obj = &blob->object;
		}
		if (!obj || process(walker, obj))
			return -1;
	}
	free(tree->buffer);
	tree->buffer = NULL;
	tree->size = 0;
	tree->object.parsed = 0;
	return 0;
}
Пример #3
0
inline comm_tree_t* comm_tree_getComm(tree_node_t* node)
{
	if(node == NULL)
		return NULL;

	return tree_entry(node, comm_tree_t, node);
}
Пример #4
0
static int fsck_walk_tree(struct tree *tree, fsck_walk_func walk, void *data)
{
    struct tree_desc desc;
    struct name_entry entry;
    int res = 0;

    if (parse_tree(tree))
        return -1;

    init_tree_desc(&desc, tree->buffer, tree->size);
    while (tree_entry(&desc, &entry)) {
        int result;

        if (S_ISGITLINK(entry.mode))
            continue;
        if (S_ISDIR(entry.mode))
            result = walk(&lookup_tree(entry.sha1)->object, OBJ_TREE, data);
        else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode))
            result = walk(&lookup_blob(entry.sha1)->object, OBJ_BLOB, data);
        else {
            result = error("in tree %s: entry %s has bad mode %.6o\n",
                           sha1_to_hex(tree->object.sha1), entry.path, entry.mode);
        }
        if (result < 0)
            return result;
        if (!res)
            res = result;
    }
    return res;
}
Пример #5
0
static int grep_tree(struct grep_opt *opt, const char **paths,
		     struct tree_desc *tree,
		     const char *tree_name, const char *base)
{
	int len;
	int hit = 0;
	struct name_entry entry;
	char *down;
	int tn_len = strlen(tree_name);
	struct strbuf pathbuf;

	strbuf_init(&pathbuf, PATH_MAX + tn_len);

	if (tn_len) {
		strbuf_add(&pathbuf, tree_name, tn_len);
		strbuf_addch(&pathbuf, ':');
		tn_len = pathbuf.len;
	}
	strbuf_addstr(&pathbuf, base);
	len = pathbuf.len;

	while (tree_entry(tree, &entry)) {
		int te_len = tree_entry_len(entry.path, entry.sha1);
		pathbuf.len = len;
		strbuf_add(&pathbuf, entry.path, te_len);

		if (S_ISDIR(entry.mode))
			/* Match "abc/" against pathspec to
			 * decide if we want to descend into "abc"
			 * directory.
			 */
			strbuf_addch(&pathbuf, '/');

		down = pathbuf.buf + tn_len;
		if (!pathspec_matches(paths, down, opt->max_depth))
			;
		else if (S_ISREG(entry.mode))
			hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
		else if (S_ISDIR(entry.mode)) {
			enum object_type type;
			struct tree_desc sub;
			void *data;
			unsigned long size;

			data = lock_and_read_sha1_file(entry.sha1, &type, &size);
			if (!data)
				die("unable to read tree (%s)",
				    sha1_to_hex(entry.sha1));
			init_tree_desc(&sub, data, size);
			hit |= grep_tree(opt, paths, &sub, tree_name, down);
			free(data);
		}
		if (hit && opt->status_only)
			break;
	}
	strbuf_release(&pathbuf);
	return hit;
}
Пример #6
0
static inline vres_event_t *vres_event_lookup(vres_event_group_t *group, vres_event_desc_t *desc)
{
    rbtree_node_t *node = NULL;

    if (!rbtree_find(&group->tree, desc, &node))
        return tree_entry(node, vres_event_t, node);
    else
        return NULL;
}
Пример #7
0
/*
 * Inspect two trees, and give a score that tells how similar they are.
 */
static int score_trees(const unsigned char *hash1, const unsigned char *hash2)
{
	struct tree_desc one;
	struct tree_desc two;
	void *one_buf = fill_tree_desc_strict(&one, hash1);
	void *two_buf = fill_tree_desc_strict(&two, hash2);
	int score = 0;

	for (;;) {
		struct name_entry e1, e2;
		int got_entry_from_one = tree_entry(&one, &e1);
		int got_entry_from_two = tree_entry(&two, &e2);
		int cmp;

		if (got_entry_from_one && got_entry_from_two)
			cmp = base_name_entries_compare(&e1, &e2);
		else if (got_entry_from_one)
			/* two lacks this entry */
			cmp = -1;
		else if (got_entry_from_two)
			/* two has more entries */
			cmp = 1;
		else
			break;

		if (cmp < 0)
			/* path1 does not appear in two */
			score += score_missing(e1.mode, e1.path);
		else if (cmp > 0)
			/* path2 does not appear in one */
			score += score_missing(e2.mode, e2.path);
		else if (hashcmp(e1.sha1, e2.sha1))
			/* they are different */
			score += score_differs(e1.mode, e2.mode, e1.path);
		else
			/* same subtree or blob */
			score += score_matches(e1.mode, e2.mode, e1.path);
	}
	free(one_buf);
	free(two_buf);
	return score;
}
Пример #8
0
static inline vres_file_t *vres_file_lookup_file(const char *path)
{
    vres_file_t *file = NULL;
    rbtree_node_t *node = NULL;

    pthread_rwlock_rdlock(&vres_file_flock);
    if (!rbtree_find(&vres_file_ftree, path, &node))
        file = tree_entry(node, vres_file_t, f_node);
    pthread_rwlock_unlock(&vres_file_flock);
    return file;
}
Пример #9
0
Файл: grep.c Проект: Gregg1/git
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
		     struct tree_desc *tree, struct strbuf *base, int tn_len,
		     int check_attr)
{
	int hit = 0;
	enum interesting match = entry_not_interesting;
	struct name_entry entry;
	int old_baselen = base->len;

	while (tree_entry(tree, &entry)) {
		int te_len = tree_entry_len(&entry);

		if (match != all_entries_interesting) {
			match = tree_entry_interesting(&entry, base, tn_len, pathspec);
			if (match == all_entries_not_interesting)
				break;
			if (match == entry_not_interesting)
				continue;
		}

		strbuf_add(base, entry.path, te_len);

		if (S_ISREG(entry.mode)) {
			hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len,
					 check_attr ? base->buf + tn_len : NULL);
		}
		else if (S_ISDIR(entry.mode)) {
			enum object_type type;
			struct tree_desc sub;
			void *data;
			unsigned long size;

			data = lock_and_read_sha1_file(entry.sha1, &type, &size);
			if (!data)
				die(_("unable to read tree (%s)"),
				    sha1_to_hex(entry.sha1));

			strbuf_addch(base, '/');
			init_tree_desc(&sub, data, size);
			hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
					 check_attr);
			free(data);
		}
		strbuf_setlen(base, old_baselen);

		if (hit && opt->status_only)
			break;
	}
	return hit;
}
Пример #10
0
static inline void vres_file_delete_file(const char *path)
{
    vres_file_t *file = NULL;
    rbtree_node_t *node = NULL;

    pthread_rwlock_wrlock(&vres_file_flock);
    if (!rbtree_find(&vres_file_ftree, path, &node)) {
        file = tree_entry(node, vres_file_t, f_node);
        rbtree_remove_node(&vres_file_ftree, node);
    }
    pthread_rwlock_unlock(&vres_file_flock);
    if (file)
        free(file);
    log_file_delete_file(path);
}
Пример #11
0
int vres_file_release_dir(vres_file_dir_t *dir)
{
    int ret = 0;

    pthread_rwlock_wrlock(&dir->d_lock);
    while (dir->d_count > 0) {
        char *name;
        size_t len;
        rbtree_node_t *node;
        vres_file_name_t *ptr;
        char path[FILE_PATH_MAX];

        node = dir->d_tree.root;
        if (!node) {
            log_err("invalid directory");
            ret = -1;
            goto out;
        }
        name = (char *)node->key;
        len = strlen(name);
        if (!len || (len >= FILE_PATH_MAX)) {
            log_err("invalid path");
            ret = -1;
            goto out;
        }
        ptr = tree_entry(node, vres_file_name_t, node);
        sprintf(path, "%s%s", dir->d_path, name);
        if (FILE_SEPARATOR == name[len - 1]) {
            if (vres_file_rmdir(path)) {
                log_err("failed to remove %s", path);
                ret = -1;
                goto out;
            }
        } else {
            vres_file_delete_file(path);
            rbtree_remove_node(&dir->d_tree, node);
            dir->d_count--;
            free(ptr);
        }
    }
    vres_file_delete_dir(dir->d_path);
out:
    pthread_rwlock_unlock(&dir->d_lock);
    if (!ret)
        free(dir);
    return ret;
}
Пример #12
0
int read_tree_recursive(struct tree *tree,
			const char *base, int baselen,
			int stage, const char **match,
			read_tree_fn_t fn)
{
	struct tree_desc desc;
	struct name_entry entry;

	if (parse_tree(tree))
		return -1;

	init_tree_desc(&desc, tree->buffer, tree->size);

	while (tree_entry(&desc, &entry)) {
		if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
			continue;

		switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage)) {
		case 0:
			continue;
		case READ_TREE_RECURSIVE:
			break;;
		default:
			return -1;
		}
		if (S_ISDIR(entry.mode)) {
			int retval;
			char *newbase;
			unsigned int pathlen = tree_entry_len(entry.path, entry.sha1);

			newbase = xmalloc(baselen + 1 + pathlen);
			memcpy(newbase, base, baselen);
			memcpy(newbase + baselen, entry.path, pathlen);
			newbase[baselen + pathlen] = '/';
			retval = read_tree_recursive(lookup_tree(entry.sha1),
						     newbase,
						     baselen + pathlen + 1,
						     stage, match, fn);
			free(newbase);
			if (retval)
				return -1;
			continue;
		}
	}
	return 0;
}
Пример #13
0
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
		     struct tree_desc *tree, struct strbuf *base, int tn_len)
{
	int hit = 0, matched = 0;
	struct name_entry entry;
	int old_baselen = base->len;

	while (tree_entry(tree, &entry)) {
		int te_len = tree_entry_len(entry.path, entry.sha1);

		if (matched != 2) {
			matched = tree_entry_interesting(&entry, base, tn_len, pathspec);
			if (matched == -1)
				break; /* no more matches */
			if (!matched)
				continue;
		}

		strbuf_add(base, entry.path, te_len);

		if (S_ISREG(entry.mode)) {
			hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len);
		}
		else if (S_ISDIR(entry.mode)) {
			enum object_type type;
			struct tree_desc sub;
			void *data;
			unsigned long size;

			data = lock_and_read_sha1_file(entry.sha1, &type, &size);
			if (!data)
				die("unable to read tree (%s)",
				    sha1_to_hex(entry.sha1));

			strbuf_addch(base, '/');
			init_tree_desc(&sub, data, size);
			hit |= grep_tree(opt, pathspec, &sub, base, tn_len);
			free(data);
		}
		strbuf_setlen(base, old_baselen);

		if (hit && opt->status_only)
			break;
	}
	return hit;
}
Пример #14
0
static void process_tree(struct rev_info *revs,
			 struct tree *tree,
			 struct object_array *p,
			 struct name_path *path,
			 const char *name)
{
	struct object *obj = &tree->object;
	struct tree_desc desc;
	struct name_entry entry;
	struct name_path me;

	if (!revs->tree_objects)
		return;
	if (!obj)
		die("bad tree object");
	if (obj->flags & (UNINTERESTING | SEEN))
		return;
	if (parse_tree(tree) < 0)
		die("bad tree object %s", sha1_to_hex(obj->sha1));
	obj->flags |= SEEN;
	name = xstrdup(name);
	add_object(obj, p, path, name);
	me.up = path;
	me.elem = name;
	me.elem_len = strlen(name);

	init_tree_desc(&desc, tree->buffer, tree->size);

	while (tree_entry(&desc, &entry)) {
		if (S_ISDIR(entry.mode))
			process_tree(revs,
				     lookup_tree(entry.sha1),
				     p, &me, entry.path);
		else if (S_ISGITLINK(entry.mode))
			process_gitlink(revs, entry.sha1,
					p, &me, entry.path);
		else
			process_blob(revs,
				     lookup_blob(entry.sha1),
				     p, &me, entry.path);
	}
	free(tree->buffer);
	tree->buffer = NULL;
}
Пример #15
0
static int tree_is_complete(const struct object_id *oid)
{
	struct tree_desc desc;
	struct name_entry entry;
	int complete;
	struct tree *tree;

	tree = lookup_tree(the_repository, oid);
	if (!tree)
		return 0;
	if (tree->object.flags & SEEN)
		return 1;
	if (tree->object.flags & INCOMPLETE)
		return 0;

	if (!tree->buffer) {
		enum object_type type;
		unsigned long size;
		void *data = read_object_file(oid, &type, &size);
		if (!data) {
			tree->object.flags |= INCOMPLETE;
			return 0;
		}
		tree->buffer = data;
		tree->size = size;
	}
	init_tree_desc(&desc, tree->buffer, tree->size);
	complete = 1;
	while (tree_entry(&desc, &entry)) {
		if (!has_object_file(&entry.oid) ||
		    (S_ISDIR(entry.mode) && !tree_is_complete(&entry.oid))) {
			tree->object.flags |= INCOMPLETE;
			complete = 0;
		}
	}
	free_tree_buffer(tree);

	if (complete)
		tree->object.flags |= SEEN;
	return complete;
}
Пример #16
0
int vres_event_do_handle(vres_t *resource, rbtree_node_t *node, vres_event_callback_t func)
{
    int ret;
    vres_event_t *event;

    if (!node)
        return 0;

    if (node->right) {
        ret = vres_event_do_handle(resource, node->right, func);
        if (ret)
            return ret;
    }
    if (node->left) {
        ret = vres_event_do_handle(resource, node->left, func);
        if (ret)
            return ret;
    }
    event = tree_entry(node, vres_event_t, node);
    return func(resource, event);
}
Пример #17
0
void mark_tree_uninteresting(struct tree *tree)
{
	struct tree_desc desc;
	struct name_entry entry;
	struct object *obj = &tree->object;

	if (!tree)
		return;
	if (obj->flags & UNINTERESTING)
		return;
	obj->flags |= UNINTERESTING;
	if (!has_sha1_file(obj->sha1))
		return;
	if (parse_tree(tree) < 0)
		die("bad tree %s", sha1_to_hex(obj->sha1));

	init_tree_desc(&desc, tree->buffer, tree->size);
	while (tree_entry(&desc, &entry)) {
		switch (object_type(entry.mode)) {
		case OBJ_TREE:
			mark_tree_uninteresting(lookup_tree(entry.sha1));
			break;
		case OBJ_BLOB:
			mark_blob_uninteresting(lookup_blob(entry.sha1));
			break;
		default:
			/* Subproject commit - not in this repository */
			break;
		}
	}

	/*
	 * We don't care about the tree any more
	 * after it has been marked uninteresting.
	 */
	free(tree->buffer);
	tree->buffer = NULL;
}
Пример #18
0
static inline int vres_file_pop(char *path)
{
    size_t len;
    char *filename;
    char dirname[FILE_PATH_MAX];

    if (vres_file_dirname(path, dirname)) {
        log_err("invalid path, path=%s", path);
        return -1;
    }
    filename = path + strlen(dirname);
    len = strlen(filename);
    if ((len > 0) && (len + filename - path < FILE_PATH_MAX)) {
        vres_file_dir_t *dir = vres_file_lookup_dir(dirname);

        if (!dir)
            return -1;
        pthread_rwlock_wrlock(&dir->d_lock);
        if (dir->d_count > 0) {
            rbtree_node_t *node = NULL;

            if (!rbtree_find(&dir->d_tree, filename, &node)) {
                vres_file_name_t *name = tree_entry(node, vres_file_name_t, node);

                rbtree_remove_node(&dir->d_tree, node);
                dir->d_count--;
                free(name);
            }
        }
        pthread_rwlock_unlock(&dir->d_lock);
    } else {
        log_err("invalid path, path=%s", path);
        return -1;
    }
    return 0;
}
Пример #19
0
static inline vres_file_dir_t *vres_file_lookup_dir(const char *path)
{
    void *key = NULL;
    size_t len = strlen(path);
    rbtree_node_t *node = NULL;
    vres_file_dir_t *dir = NULL;
    char dirname[FILE_PATH_MAX] = {0};

    if (FILE_SEPARATOR == path[len - 1])
        key = (void *)path;
    else {
        if (FILE_PATH_MAX - 1 == len) {
            log_err("invalid path");
            return NULL;
        }
        sprintf(dirname, "%s%c", path, FILE_SEPARATOR);
        key = (void *)dirname;
    }
    pthread_rwlock_rdlock(&vres_file_dlock);
    if (!rbtree_find(&vres_file_dtree, key, &node))
        dir = tree_entry(node, vres_file_dir_t, d_node);
    pthread_rwlock_unlock(&vres_file_dlock);
    return dir;
}
Пример #20
0
static int read_tree_1(struct tree *tree, struct strbuf *base,
		       int stage, const struct pathspec *pathspec,
		       read_tree_fn_t fn, void *context)
{
	struct tree_desc desc;
	struct name_entry entry;
	unsigned char sha1[20];
	int len, oldlen = base->len;
	enum interesting retval = entry_not_interesting;

	if (parse_tree(tree))
		return -1;

	init_tree_desc(&desc, tree->buffer, tree->size);

	while (tree_entry(&desc, &entry)) {
		if (retval != all_entries_interesting) {
			retval = tree_entry_interesting(&entry, base, 0, pathspec);
			if (retval == all_entries_not_interesting)
				break;
			if (retval == entry_not_interesting)
				continue;
		}

		switch (fn(entry.sha1, base,
			   entry.path, entry.mode, stage, context)) {
		case 0:
			continue;
		case READ_TREE_RECURSIVE:
			break;
		default:
			return -1;
		}

		if (S_ISDIR(entry.mode))
			hashcpy(sha1, entry.sha1);
		else if (S_ISGITLINK(entry.mode)) {
			struct commit *commit;

			commit = lookup_commit(entry.sha1);
			if (!commit)
				die("Commit %s in submodule path %s%s not found",
				    sha1_to_hex(entry.sha1),
				    base->buf, entry.path);

			if (parse_commit(commit))
				die("Invalid commit %s in submodule path %s%s",
				    sha1_to_hex(entry.sha1),
				    base->buf, entry.path);

			hashcpy(sha1, commit->tree->object.sha1);
		}
		else
			continue;

		len = tree_entry_len(&entry);
		strbuf_add(base, entry.path, len);
		strbuf_addch(base, '/');
		retval = read_tree_1(lookup_tree(sha1),
				     base, stage, pathspec,
				     fn, context);
		strbuf_setlen(base, oldlen);
		if (retval)
			return -1;
	}
	return 0;
}
Пример #21
0
Файл: notes.c Проект: sanj/git
static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
		struct int_node *node, unsigned int n)
{
	unsigned char object_sha1[20];
	unsigned int prefix_len;
	void *buf;
	struct tree_desc desc;
	struct name_entry entry;
	int len, path_len;
	unsigned char type;
	struct leaf_node *l;

	buf = fill_tree_descriptor(&desc, subtree->val_sha1);
	if (!buf)
		die("Could not read %s for notes-index",
		     sha1_to_hex(subtree->val_sha1));

	prefix_len = subtree->key_sha1[19];
	assert(prefix_len * 2 >= n);
	memcpy(object_sha1, subtree->key_sha1, prefix_len);
	while (tree_entry(&desc, &entry)) {
		path_len = strlen(entry.path);
		len = get_sha1_hex_segment(entry.path, path_len,
				object_sha1 + prefix_len, 20 - prefix_len);
		if (len < 0)
			goto handle_non_note; /* entry.path is not a SHA1 */
		len += prefix_len;

		/*
		 * If object SHA1 is complete (len == 20), assume note object
		 * If object SHA1 is incomplete (len < 20), and current
		 * component consists of 2 hex chars, assume note subtree
		 */
		if (len <= 20) {
			type = PTR_TYPE_NOTE;
			l = (struct leaf_node *)
				xcalloc(sizeof(struct leaf_node), 1);
			hashcpy(l->key_sha1, object_sha1);
			hashcpy(l->val_sha1, entry.sha1);
			if (len < 20) {
				if (!S_ISDIR(entry.mode) || path_len != 2)
					goto handle_non_note; /* not subtree */
				l->key_sha1[19] = (unsigned char) len;
				type = PTR_TYPE_SUBTREE;
			}
			note_tree_insert(t, node, n, l, type,
					 combine_notes_concatenate);
		}
		continue;

handle_non_note:
		/*
		 * Determine full path for this non-note entry:
		 * The filename is already found in entry.path, but the
		 * directory part of the path must be deduced from the subtree
		 * containing this entry. We assume here that the overall notes
		 * tree follows a strict byte-based progressive fanout
		 * structure (i.e. using 2/38, 2/2/36, etc. fanouts, and not
		 * e.g. 4/36 fanout). This means that if a non-note is found at
		 * path "dead/beef", the following code will register it as
		 * being found on "de/ad/beef".
		 * On the other hand, if you use such non-obvious non-note
		 * paths in the middle of a notes tree, you deserve what's
		 * coming to you ;). Note that for non-notes that are not
		 * SHA1-like at the top level, there will be no problems.
		 *
		 * To conclude, it is strongly advised to make sure non-notes
		 * have at least one non-hex character in the top-level path
		 * component.
		 */
		{
			char non_note_path[PATH_MAX];
			char *p = non_note_path;
			const char *q = sha1_to_hex(subtree->key_sha1);
			int i;
			for (i = 0; i < prefix_len; i++) {
				*p++ = *q++;
				*p++ = *q++;
				*p++ = '/';
			}
			strcpy(p, entry.path);
			add_non_note(t, non_note_path, entry.mode, entry.sha1);
		}
	}
	free(buf);
}
Пример #22
0
void resolve_tree_islands(struct repository *r,
			  int progress,
			  struct packing_data *to_pack)
{
	struct progress *progress_state = NULL;
	struct tree_islands_todo *todo;
	int nr = 0;
	int i;

	if (!island_marks)
		return;

	/*
	 * We process only trees, as commits and tags have already been handled
	 * (and passed their marks on to root trees, as well. We must make sure
	 * to process them in descending tree-depth order so that marks
	 * propagate down the tree properly, even if a sub-tree is found in
	 * multiple parent trees.
	 */
	ALLOC_ARRAY(todo, to_pack->nr_objects);
	for (i = 0; i < to_pack->nr_objects; i++) {
		if (oe_type(&to_pack->objects[i]) == OBJ_TREE) {
			todo[nr].entry = &to_pack->objects[i];
			todo[nr].depth = oe_tree_depth(to_pack, &to_pack->objects[i]);
			nr++;
		}
	}
	QSORT(todo, nr, tree_depth_compare);

	if (progress)
		progress_state = start_progress(_("Propagating island marks"), nr);

	for (i = 0; i < nr; i++) {
		struct object_entry *ent = todo[i].entry;
		struct island_bitmap *root_marks;
		struct tree *tree;
		struct tree_desc desc;
		struct name_entry entry;
		khiter_t pos;

		pos = kh_get_sha1(island_marks, ent->idx.oid.hash);
		if (pos >= kh_end(island_marks))
			continue;

		root_marks = kh_value(island_marks, pos);

		tree = lookup_tree(r, &ent->idx.oid);
		if (!tree || parse_tree(tree) < 0)
			die(_("bad tree object %s"), oid_to_hex(&ent->idx.oid));

		init_tree_desc(&desc, tree->buffer, tree->size);
		while (tree_entry(&desc, &entry)) {
			struct object *obj;

			if (S_ISGITLINK(entry.mode))
				continue;

			obj = lookup_object(r, entry.oid->hash);
			if (!obj)
				continue;

			set_island_marks(obj, root_marks);
		}

		free_tree_buffer(tree);

		display_progress(progress_state, i+1);
	}

	stop_progress(&progress_state);
	free(todo);
}
Пример #23
0
static void process_tree(struct rev_info *revs,
			 struct tree *tree,
			 show_object_fn show,
			 struct name_path *path,
			 struct strbuf *base,
			 const char *name)
{
	struct object *obj = &tree->object;
	struct tree_desc desc;
	struct name_entry entry;
	struct name_path me;
	int all_interesting = (revs->diffopt.pathspec.nr == 0);
	int baselen = base->len;

	if (!revs->tree_objects)
		return;
	if (!obj)
		die("bad tree object");
	if (obj->flags & (UNINTERESTING | SEEN))
		return;
	if (parse_tree(tree) < 0)
		die("bad tree object %s", sha1_to_hex(obj->sha1));
	obj->flags |= SEEN;
	show(obj, path, name);
	me.up = path;
	me.elem = name;
	me.elem_len = strlen(name);

	if (!all_interesting) {
		strbuf_addstr(base, name);
		if (base->len)
			strbuf_addch(base, '/');
	}

	init_tree_desc(&desc, tree->buffer, tree->size);

	while (tree_entry(&desc, &entry)) {
		if (!all_interesting) {
			int showit = tree_entry_interesting(&entry,
							    base, 0,
							    &revs->diffopt.pathspec);

			if (showit < 0)
				break;
			else if (!showit)
				continue;
			else if (showit == 2)
				all_interesting = 1;
		}

		if (S_ISDIR(entry.mode))
			process_tree(revs,
				     lookup_tree(entry.sha1),
				     show, &me, base, entry.path);
		else if (S_ISGITLINK(entry.mode))
			process_gitlink(revs, entry.sha1,
					show, &me, entry.path);
		else
			process_blob(revs,
				     lookup_blob(entry.sha1),
				     show, &me, entry.path);
	}
	strbuf_setlen(base, baselen);
	free(tree->buffer);
	tree->buffer = NULL;
}
Пример #24
0
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
		     struct tree_desc *tree, struct strbuf *base, int tn_len,
		     int check_attr)
{
	int hit = 0;
	enum interesting match = entry_not_interesting;
	struct name_entry entry;
	int old_baselen = base->len;
	struct strbuf name = STRBUF_INIT;
	int name_base_len = 0;
	if (super_prefix) {
		strbuf_addstr(&name, super_prefix);
		name_base_len = name.len;
	}

	while (tree_entry(tree, &entry)) {
		int te_len = tree_entry_len(&entry);

		if (match != all_entries_interesting) {
			strbuf_addstr(&name, base->buf + tn_len);
			match = tree_entry_interesting(&entry, &name,
						       0, pathspec);
			strbuf_setlen(&name, name_base_len);

			if (match == all_entries_not_interesting)
				break;
			if (match == entry_not_interesting)
				continue;
		}

		strbuf_add(base, entry.path, te_len);

		if (S_ISREG(entry.mode)) {
			hit |= grep_sha1(opt, entry.oid->hash, base->buf, tn_len,
					 check_attr ? base->buf + tn_len : NULL);
		} else if (S_ISDIR(entry.mode)) {
			enum object_type type;
			struct tree_desc sub;
			void *data;
			unsigned long size;

			data = lock_and_read_sha1_file(entry.oid->hash, &type, &size);
			if (!data)
				die(_("unable to read tree (%s)"),
				    oid_to_hex(entry.oid));

			strbuf_addch(base, '/');
			init_tree_desc(&sub, data, size);
			hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
					 check_attr);
			free(data);
		} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
			hit |= grep_submodule(opt, entry.oid->hash, base->buf,
					      base->buf + tn_len);
		}

		strbuf_setlen(base, old_baselen);

		if (hit && opt->status_only)
			break;
	}

	strbuf_release(&name);
	return hit;
}
Пример #25
0
Файл: tree.c Проект: Oblomov/tig
static bool
tree_read(struct view *view, struct buffer *buf)
{
	struct tree_state *state = view->private;
	struct tree_entry *data;
	struct line *entry, *line;
	enum line_type type;
	char *path;
	size_t size;

	if (state->read_date || !buf)
		return tree_read_date(view, buf, state);

	if (buf->size <= SIZEOF_TREE_ATTR)
		return FALSE;
	if (view->lines == 0 &&
	    !tree_entry(view, LINE_HEADER, view->env->directory, NULL, NULL, 0))
		return FALSE;

	size = parse_size(buf->data + SIZEOF_TREE_ATTR);
	path = strchr(buf->data + SIZEOF_TREE_ATTR, '\t');
	if (!path)
		return FALSE;
	path++;

	/* Strip the path part ... */
	if (*view->env->directory) {
		size_t pathlen = strlen(path);
		size_t striplen = strlen(view->env->directory);

		if (pathlen > striplen)
			memmove(path, path + striplen,
				pathlen - striplen + 1);

		/* Insert "link" to parent directory. */
		if (view->lines == 1 &&
		    !tree_entry(view, LINE_DIRECTORY, "..", "040000", view->ref, 0))
			return FALSE;
	}

	type = buf->data[SIZEOF_TREE_MODE] == 't' ? LINE_DIRECTORY : LINE_FILE;
	entry = tree_entry(view, type, path, buf->data, buf->data + TREE_ID_OFFSET, size);
	if (!entry)
		return FALSE;
	data = entry->data;
	view_column_info_update(view, entry);

	/* Skip "Directory ..." and ".." line. */
	for (line = &view->line[1 + !!*view->env->directory]; line < entry; line++) {
		if (tree_compare_entry(line, entry) <= 0)
			continue;

		memmove(line + 1, line, (entry - line) * sizeof(*entry));

		line->data = data;
		line->type = type;
		line->dirty = line->cleareol = 1;
		for (line++; line <= entry; line++) {
			line->dirty = line->cleareol = 1;
			line->lineno++;
		}
		return TRUE;
	}

	/* Move the current line to the first tree entry. */
	if (!check_position(&view->prev_pos) && !check_position(&view->pos))
		goto_view_line(view, 0, 1);

	return TRUE;
}
Пример #26
0
Файл: tree.c Проект: Oblomov/tig
static bool
tree_read_date(struct view *view, struct buffer *buf, struct tree_state *state)
{
	char *text = buf ? buf->data : NULL;

	if (!text && state->read_date) {
		state->read_date = FALSE;
		return TRUE;

	} else if (!text) {
		/* Find next entry to process */
		const char *log_file[] = {
			"git", "log", encoding_arg, "--no-color", "--pretty=raw",
				"--cc", "--raw", view->ops->id, "--", "%(directory)", NULL
		};

		if (!view->lines) {
			tree_entry(view, LINE_HEADER, view->env->directory, NULL, NULL, 0);
			tree_entry(view, LINE_DIRECTORY, "..", "040000", view->ref, 0);
			report("Tree is empty");
			return TRUE;
		}

		if (!begin_update(view, repo.cdup, log_file, OPEN_EXTRA)) {
			report("Failed to load tree data");
			return TRUE;
		}

		state->read_date = TRUE;
		return FALSE;

	} else if (*text == 'c' && get_line_type(text) == LINE_COMMIT) {
		string_copy_rev_from_commit_line(state->commit, text);

	} else if (*text == 'a' && get_line_type(text) == LINE_AUTHOR) {
		parse_author_line(text + STRING_SIZE("author "),
				  &state->author, &state->author_time);

	} else if (*text == ':') {
		char *pos;
		size_t annotated = 1;
		size_t i;

		pos = strrchr(text, '\t');
		if (!pos)
			return TRUE;
		text = pos + 1;
		if (*view->env->directory && !strncmp(text, view->env->directory, strlen(view->env->directory)))
			text += strlen(view->env->directory);
		pos = strchr(text, '/');
		if (pos)
			*pos = 0;

		for (i = 1; i < view->lines; i++) {
			struct line *line = &view->line[i];
			struct tree_entry *entry = line->data;

			annotated += !!entry->author;
			if (entry->author || strcmp(entry->name, text))
				continue;

			string_copy_rev(entry->commit, state->commit);
			entry->author = state->author;
			entry->time = state->author_time;
			line->dirty = 1;
			view_column_info_update(view, line);
			break;
		}

		if (annotated == view->lines)
			io_kill(view->pipe);
	}
	return TRUE;
}
Пример #27
0
static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
		struct int_node *node, unsigned int n)
{
	struct object_id object_oid;
	size_t prefix_len;
	void *buf;
	struct tree_desc desc;
	struct name_entry entry;

	buf = fill_tree_descriptor(&desc, &subtree->val_oid);
	if (!buf)
		die("Could not read %s for notes-index",
		     oid_to_hex(&subtree->val_oid));

	prefix_len = subtree->key_oid.hash[KEY_INDEX];
	if (prefix_len >= GIT_SHA1_RAWSZ)
		BUG("prefix_len (%"PRIuMAX") is out of range", (uintmax_t)prefix_len);
	if (prefix_len * 2 < n)
		BUG("prefix_len (%"PRIuMAX") is too small", (uintmax_t)prefix_len);
	memcpy(object_oid.hash, subtree->key_oid.hash, prefix_len);
	while (tree_entry(&desc, &entry)) {
		unsigned char type;
		struct leaf_node *l;
		size_t path_len = strlen(entry.path);

		if (path_len == 2 * (GIT_SHA1_RAWSZ - prefix_len)) {
			/* This is potentially the remainder of the SHA-1 */

			if (!S_ISREG(entry.mode))
				/* notes must be blobs */
				goto handle_non_note;

			if (hex_to_bytes(object_oid.hash + prefix_len, entry.path,
					 GIT_SHA1_RAWSZ - prefix_len))
				goto handle_non_note; /* entry.path is not a SHA1 */

			type = PTR_TYPE_NOTE;
		} else if (path_len == 2) {
			/* This is potentially an internal node */
			size_t len = prefix_len;

			if (!S_ISDIR(entry.mode))
				/* internal nodes must be trees */
				goto handle_non_note;

			if (hex_to_bytes(object_oid.hash + len++, entry.path, 1))
				goto handle_non_note; /* entry.path is not a SHA1 */

			/*
			 * Pad the rest of the SHA-1 with zeros,
			 * except for the last byte, where we write
			 * the length:
			 */
			memset(object_oid.hash + len, 0, GIT_SHA1_RAWSZ - len - 1);
			object_oid.hash[KEY_INDEX] = (unsigned char)len;

			type = PTR_TYPE_SUBTREE;
		} else {
			/* This can't be part of a note */
			goto handle_non_note;
		}

		l = xcalloc(1, sizeof(*l));
		oidcpy(&l->key_oid, &object_oid);
		oidcpy(&l->val_oid, &entry.oid);
		if (note_tree_insert(t, node, n, l, type,
				     combine_notes_concatenate))
			die("Failed to load %s %s into notes tree "
			    "from %s",
			    type == PTR_TYPE_NOTE ? "note" : "subtree",
			    oid_to_hex(&l->key_oid), t->ref);

		continue;

handle_non_note:
		/*
		 * Determine full path for this non-note entry. The
		 * filename is already found in entry.path, but the
		 * directory part of the path must be deduced from the
		 * subtree containing this entry based on our
		 * knowledge that the overall notes tree follows a
		 * strict byte-based progressive fanout structure
		 * (i.e. using 2/38, 2/2/36, etc. fanouts).
		 */
		{
			struct strbuf non_note_path = STRBUF_INIT;
			const char *q = oid_to_hex(&subtree->key_oid);
			size_t i;
			for (i = 0; i < prefix_len; i++) {
				strbuf_addch(&non_note_path, *q++);
				strbuf_addch(&non_note_path, *q++);
				strbuf_addch(&non_note_path, '/');
			}
			strbuf_addstr(&non_note_path, entry.path);
			add_non_note(t, strbuf_detach(&non_note_path, NULL),
				     entry.mode, entry.oid.hash);
		}
	}
	free(buf);
}
Пример #28
0
static void process_tree(struct rev_info *revs,
			 struct tree *tree,
			 show_object_fn show,
			 struct strbuf *base,
			 const char *name,
			 void *cb_data)
{
	struct object *obj = &tree->object;
	struct tree_desc desc;
	struct name_entry entry;
	enum interesting match = revs->diffopt.pathspec.nr == 0 ?
		all_entries_interesting: entry_not_interesting;
	int baselen = base->len;

	if (!revs->tree_objects)
		return;
	if (!obj)
		die("bad tree object");
	if (obj->flags & (UNINTERESTING | SEEN))
		return;
	if (parse_tree_gently(tree, revs->ignore_missing_links) < 0) {
		if (revs->ignore_missing_links)
			return;
		die("bad tree object %s", oid_to_hex(&obj->oid));
	}

	obj->flags |= SEEN;
	strbuf_addstr(base, name);
	show(obj, base->buf, cb_data);
	if (base->len)
		strbuf_addch(base, '/');

	init_tree_desc(&desc, tree->buffer, tree->size);

	while (tree_entry(&desc, &entry)) {
		if (match != all_entries_interesting) {
			match = tree_entry_interesting(&entry, base, 0,
						       &revs->diffopt.pathspec);
			if (match == all_entries_not_interesting)
				break;
			if (match == entry_not_interesting)
				continue;
		}

		if (S_ISDIR(entry.mode))
			process_tree(revs,
				     lookup_tree(entry.sha1),
				     show, base, entry.path,
				     cb_data);
		else if (S_ISGITLINK(entry.mode))
			process_gitlink(revs, entry.sha1,
					show, base, entry.path,
					cb_data);
		else
			process_blob(revs,
				     lookup_blob(entry.sha1),
				     show, base, entry.path,
				     cb_data);
	}
	strbuf_setlen(base, baselen);
	free_tree_buffer(tree);
}