Exemplo n.º 1
0
int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
	      const char *base_str, struct diff_options *opt)
{
	struct strbuf base;
	int baselen = strlen(base_str);
	enum interesting t1_match = entry_not_interesting;
	enum interesting t2_match = entry_not_interesting;

	/* Enable recursion indefinitely */
	opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
	opt->pathspec.max_depth = -1;

	strbuf_init(&base, PATH_MAX);
	strbuf_add(&base, base_str, baselen);

	for (;;) {
		if (diff_can_quit_early(opt))
			break;
		if (opt->pathspec.nr) {
			skip_uninteresting(t1, &base, opt, &t1_match);
			skip_uninteresting(t2, &base, opt, &t2_match);
		}
		if (!t1->size) {
			if (!t2->size)
				break;
			show_entry(opt, "+", t2, &base);
			update_tree_entry(t2);
			continue;
		}
		if (!t2->size) {
			show_entry(opt, "-", t1, &base);
			update_tree_entry(t1);
			continue;
		}
		switch (compare_tree_entry(t1, t2, &base, opt)) {
		case -1:
			update_tree_entry(t1);
			continue;
		case 0:
			update_tree_entry(t1);
			/* Fallthrough */
		case 1:
			update_tree_entry(t2);
			continue;
		}
		die("git diff-tree: internal error");
	}

	strbuf_release(&base);
	return 0;
}
Exemplo n.º 2
0
/* ∀ pi=p[imin]  pi↓ */
static inline void update_tp_entries(struct tree_desc *tp, int nparent)
{
	int i;
	for (i = 0; i < nparent; ++i)
		if (!(tp[i].entry.mode & S_IFXMIN_NEQ))
			update_tree_entry(&tp[i]);
}
Exemplo n.º 3
0
static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode)
{
	int namelen = strlen(name);
	while (t->size) {
		const char *entry;
		const unsigned char *sha1;
		int entrylen, cmp;

		sha1 = tree_entry_extract(t, &entry, mode);
		update_tree_entry(t);
		entrylen = tree_entry_len(entry, sha1);
		if (entrylen > namelen)
			continue;
		cmp = memcmp(name, entry, entrylen);
		if (cmp > 0)
			continue;
		if (cmp < 0)
			break;
		if (entrylen == namelen) {
			hashcpy(result, sha1);
			return 0;
		}
		if (name[entrylen] != '/')
			continue;
		if (!S_ISDIR(*mode))
			break;
		if (++entrylen == namelen) {
			hashcpy(result, sha1);
			return 0;
		}
		return get_tree_entry(sha1, name + entrylen, result, mode);
	}
	return -1;
}
Exemplo n.º 4
0
/*
 * A tree "hash1" has a subdirectory at "prefix".  Come up with a
 * tree object by replacing it with another tree "hash2".
 */
static int splice_tree(const unsigned char *hash1,
		       const char *prefix,
		       const unsigned char *hash2,
		       unsigned char *result)
{
	char *subpath;
	int toplen;
	char *buf;
	unsigned long sz;
	struct tree_desc desc;
	unsigned char *rewrite_here;
	const unsigned char *rewrite_with;
	unsigned char subtree[20];
	enum object_type type;
	int status;

	subpath = strchrnul(prefix, '/');
	toplen = subpath - prefix;
	if (*subpath)
		subpath++;

	buf = read_sha1_file(hash1, &type, &sz);
	if (!buf)
		die("cannot read tree %s", sha1_to_hex(hash1));
	init_tree_desc(&desc, buf, sz);

	rewrite_here = NULL;
	while (desc.size) {
		const char *name;
		unsigned mode;
		const unsigned char *sha1;

		sha1 = tree_entry_extract(&desc, &name, &mode);
		if (strlen(name) == toplen &&
		    !memcmp(name, prefix, toplen)) {
			if (!S_ISDIR(mode))
				die("entry %s in tree %s is not a tree",
				    name, sha1_to_hex(hash1));
			rewrite_here = (unsigned char *) sha1;
			break;
		}
		update_tree_entry(&desc);
	}
	if (!rewrite_here)
		die("entry %.*s not found in tree %s",
		    toplen, prefix, sha1_to_hex(hash1));
	if (*subpath) {
		status = splice_tree(rewrite_here, subpath, hash2, subtree);
		if (status)
			return status;
		rewrite_with = subtree;
	}
	else
		rewrite_with = hash2;
	hashcpy(rewrite_here, rewrite_with);
	status = write_sha1_file(buf, sz, tree_type, result);
	free(buf);
	return status;
}
Exemplo n.º 5
0
/* A whole sub-tree went away or appeared */
static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base)
{
	while (desc->size) {
		if (interesting(desc, base))
			show_entry(opt, prefix, desc, base);
		update_tree_entry(desc);
	}
}
Exemplo n.º 6
0
int tree_entry(struct tree_desc *desc, struct name_entry *entry)
{
	if (!desc->size)
		return 0;

	*entry = desc->entry;
	update_tree_entry(desc);
	return 1;
}
Exemplo n.º 7
0
static void update_extended_entry(struct tree_desc_x *t, struct name_entry *a)
{
	if (t->d.entry.path == a->path) {
		update_tree_entry(&t->d);
	} else {
		/* we have returned this entry early */
		struct tree_desc_skip *skip = xmalloc(sizeof(*skip));
		skip->ptr = a->path;
		skip->prev = t->skip;
		t->skip = skip;
	}
}
Exemplo n.º 8
0
int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
{
	int baselen = strlen(base);

	for (;;) {
		if (DIFF_OPT_TST(opt, QUICK) &&
		    DIFF_OPT_TST(opt, HAS_CHANGES))
			break;
		if (opt->nr_paths) {
			skip_uninteresting(t1, base, baselen, opt);
			skip_uninteresting(t2, base, baselen, opt);
		}
		if (!t1->size) {
			if (!t2->size)
				break;
			show_entry(opt, "+", t2, base, baselen);
			update_tree_entry(t2);
			continue;
		}
		if (!t2->size) {
			show_entry(opt, "-", t1, base, baselen);
			update_tree_entry(t1);
			continue;
		}
		switch (compare_tree_entry(t1, t2, base, baselen, opt)) {
		case -1:
			update_tree_entry(t1);
			continue;
		case 0:
			update_tree_entry(t1);
			/* Fallthrough */
		case 1:
			update_tree_entry(t2);
			continue;
		}
		die("git diff-tree: internal error");
	}
	return 0;
}
Exemplo n.º 9
0
static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
			       struct diff_options *opt, int *match)
{
	while (t->size) {
		*match = tree_entry_interesting(&t->entry, base, 0, &opt->pathspec);
		if (*match) {
			if (*match < 0)
				t->size = 0;
			break;
		}
		update_tree_entry(t);
	}
}
Exemplo n.º 10
0
/*
 * Match one itself and its subtrees with two and pick the best match.
 */
static void match_trees(const unsigned char *hash1,
			const unsigned char *hash2,
			int *best_score,
			char **best_match,
			const char *base,
			int recurse_limit)
{
	struct tree_desc one;
	void *one_buf;
	enum object_type type;
	unsigned long size;

	one_buf = read_sha1_file(hash1, &type, &size);
	if (!one_buf)
		die("unable to read tree (%s)", sha1_to_hex(hash1));
	if (type != OBJ_TREE)
		die("%s is not a tree", sha1_to_hex(hash1));
	init_tree_desc(&one, one_buf, size);

	while (one.size) {
		const char *path;
		const unsigned char *elem;
		unsigned mode;
		int score;

		elem = tree_entry_extract(&one, &path, &mode);
		if (!S_ISDIR(mode))
			goto next;
		score = score_trees(elem, hash2);
		if (*best_score < score) {
			char *newpath;
			newpath = xmalloc(strlen(base) + strlen(path) + 1);
			sprintf(newpath, "%s%s", base, path);
			free(*best_match);
			*best_match = newpath;
			*best_score = score;
		}
		if (recurse_limit) {
			char *newbase;
			newbase = xmalloc(strlen(base) + strlen(path) + 2);
			sprintf(newbase, "%s%s/", base, path);
			match_trees(elem, hash2, best_score, best_match,
				    newbase, recurse_limit - 1);
			free(newbase);
		}

	next:
		update_tree_entry(&one);
	}
	free(one_buf);
}
Exemplo n.º 11
0
static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
			       struct diff_options *opt)
{
	enum interesting match;

	while (t->size) {
		match = tree_entry_interesting(&t->entry, base, 0, &opt->pathspec);
		if (match) {
			if (match == all_entries_not_interesting)
				t->size = 0;
			break;
		}
		update_tree_entry(t);
	}
}
Exemplo n.º 12
0
/* A whole sub-tree went away or appeared */
static void show_tree(struct diff_options *opt, const char *prefix,
		      struct tree_desc *desc, struct strbuf *base)
{
	enum interesting match = entry_not_interesting;
	for (; desc->size; update_tree_entry(desc)) {
		if (match != all_entries_interesting) {
			match = tree_entry_interesting(&desc->entry, base, 0,
						       &opt->pathspec);
			if (match == all_entries_not_interesting)
				break;
			if (match == entry_not_interesting)
				continue;
		}
		show_entry(opt, prefix, desc, base);
	}
}
Exemplo n.º 13
0
/* A whole sub-tree went away or appeared */
static void show_tree(struct diff_options *opt, const char *prefix,
		      struct tree_desc *desc, struct strbuf *base)
{
	int match = 0;
	for (; desc->size; update_tree_entry(desc)) {
		if (match != 2) {
			match = tree_entry_interesting(&desc->entry, base, 0,
						       &opt->pathspec);
			if (match < 0)
				break;
			if (match == 0)
				continue;
		}
		show_entry(opt, prefix, desc, base);
	}
}
Exemplo n.º 14
0
/*
 * Match one itself and its subtrees with two and pick the best match.
 */
static void match_trees(const unsigned char *hash1,
			const unsigned char *hash2,
			int *best_score,
			char **best_match,
			const char *base,
			int recurse_limit)
{
	struct tree_desc one;
	void *one_buf = fill_tree_desc_strict(&one, hash1);

	while (one.size) {
		const char *path;
		const unsigned char *elem;
		unsigned mode;
		int score;

		elem = tree_entry_extract(&one, &path, &mode);
		if (!S_ISDIR(mode))
			goto next;
		score = score_trees(elem, hash2);
		if (*best_score < score) {
			char *newpath;
			newpath = xmalloc(strlen(base) + strlen(path) + 1);
			sprintf(newpath, "%s%s", base, path);
			free(*best_match);
			*best_match = newpath;
			*best_score = score;
		}
		if (recurse_limit) {
			char *newbase;
			newbase = xmalloc(strlen(base) + strlen(path) + 2);
			sprintf(newbase, "%s%s/", base, path);
			match_trees(elem, hash2, best_score, best_match,
				    newbase, recurse_limit - 1);
			free(newbase);
		}

	next:
		update_tree_entry(&one);
	}
	free(one_buf);
}
Exemplo n.º 15
0
/* A whole sub-tree went away or appeared */
static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen)
{
	int all_interesting = 0;
	while (desc->size) {
		int show;

		if (all_interesting)
			show = 1;
		else {
			show = tree_entry_interesting(desc, base, baselen,
						      opt);
			if (show == 2)
				all_interesting = 1;
		}
		if (show < 0)
			break;
		if (show)
			show_entry(opt, prefix, desc, base, baselen);
		update_tree_entry(desc);
	}
}
Exemplo n.º 16
0
static void skip_uninteresting(struct tree_desc *t, const char *base, int baselen, struct diff_options *opt)
{
	int all_interesting = 0;
	while (t->size) {
		int show;

		if (all_interesting)
			show = 1;
		else {
			show = tree_entry_interesting(t, base, baselen, opt);
			if (show == 2)
				all_interesting = 1;
		}
		if (!show) {
			update_tree_entry(t);
			continue;
		}
		/* Skip it all? */
		if (show < 0)
			t->size = 0;
		return;
	}
}
Exemplo n.º 17
0
int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
{
	while (t1->size | t2->size) {
		if (nr_paths && t1->size && !interesting(t1, base)) {
			update_tree_entry(t1);
			continue;
		}
		if (nr_paths && t2->size && !interesting(t2, base)) {
			update_tree_entry(t2);
			continue;
		}
		if (!t1->size) {
			show_entry(opt, "+", t2, base);
			update_tree_entry(t2);
			continue;
		}
		if (!t2->size) {
			show_entry(opt, "-", t1, base);
			update_tree_entry(t1);
			continue;
		}
		switch (compare_tree_entry(t1, t2, base, opt)) {
		case -1:
			update_tree_entry(t1);
			continue;
		case 0:
			update_tree_entry(t1);
			/* Fallthrough */
		case 1:
			update_tree_entry(t2);
			continue;
		}
		die("git-diff-tree: internal error");
	}
	return 0;
}
Exemplo n.º 18
0
Arquivo: fsck.c Projeto: xq-sunny/git
static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
{
    int retval;
    int has_full_path = 0;
    int has_empty_name = 0;
    int has_zero_pad = 0;
    int has_bad_modes = 0;
    int has_dup_entries = 0;
    int not_properly_sorted = 0;
    struct tree_desc desc;
    unsigned o_mode;
    const char *o_name;

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

    o_mode = 0;
    o_name = NULL;

    while (desc.size) {
        unsigned mode;
        const char *name;

        tree_entry_extract(&desc, &name, &mode);

        if (strchr(name, '/'))
            has_full_path = 1;
        if (!*name)
            has_empty_name = 1;
        has_zero_pad |= *(char *)desc.buffer == '0';
        update_tree_entry(&desc);

        switch (mode) {
        /*
         * Standard modes..
         */
        case S_IFREG | 0755:
        case S_IFREG | 0644:
        case S_IFLNK:
        case S_IFDIR:
        case S_IFGITLINK:
            break;
        /*
         * This is nonstandard, but we had a few of these
         * early on when we honored the full set of mode
         * bits..
         */
        case S_IFREG | 0664:
            if (!strict)
                break;
        default:
            has_bad_modes = 1;
        }

        if (o_name) {
            switch (verify_ordered(o_mode, o_name, mode, name)) {
            case TREE_UNORDERED:
                not_properly_sorted = 1;
                break;
            case TREE_HAS_DUPS:
                has_dup_entries = 1;
                break;
            default:
                break;
            }
        }

        o_mode = mode;
        o_name = name;
    }

    retval = 0;
    if (has_full_path)
        retval += error_func(&item->object, FSCK_WARN, "contains full pathnames");
    if (has_empty_name)
        retval += error_func(&item->object, FSCK_WARN, "contains empty pathname");
    if (has_zero_pad)
        retval += error_func(&item->object, FSCK_WARN, "contains zero-padded file modes");
    if (has_bad_modes)
        retval += error_func(&item->object, FSCK_WARN, "contains bad file modes");
    if (has_dup_entries)
        retval += error_func(&item->object, FSCK_ERROR, "contains duplicate file entries");
    if (not_properly_sorted)
        retval += error_func(&item->object, FSCK_ERROR, "not properly sorted");
    return retval;
}
Exemplo n.º 19
0
static struct combine_diff_path *ll_diff_tree_paths(
	struct combine_diff_path *p, const unsigned char *sha1,
	const unsigned char **parents_sha1, int nparent,
	struct strbuf *base, struct diff_options *opt)
{
	struct tree_desc t, *tp;
	void *ttree, **tptree;
	int i;

	FAST_ARRAY_ALLOC(tp, nparent);
	FAST_ARRAY_ALLOC(tptree, nparent);

	/*
	 * load parents first, as they are probably already cached.
	 *
	 * ( log_tree_diff() parses commit->parent before calling here via
	 *   diff_tree_sha1(parent, commit) )
	 */
	for (i = 0; i < nparent; ++i)
		tptree[i] = fill_tree_descriptor(&tp[i], parents_sha1[i]);
	ttree = fill_tree_descriptor(&t, sha1);

	/* Enable recursion indefinitely */
	opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);

	for (;;) {
		int imin, cmp;

		if (diff_can_quit_early(opt))
			break;

		if (opt->pathspec.nr) {
			skip_uninteresting(&t, base, opt);
			for (i = 0; i < nparent; i++)
				skip_uninteresting(&tp[i], base, opt);
		}

		/* comparing is finished when all trees are done */
		if (!t.size) {
			int done = 1;
			for (i = 0; i < nparent; ++i)
				if (tp[i].size) {
					done = 0;
					break;
				}
			if (done)
				break;
		}

		/*
		 * lookup imin = argmin(p1...pn),
		 * mark entries whether they =p[imin] along the way
		 */
		imin = 0;
		tp[0].entry.mode &= ~S_IFXMIN_NEQ;

		for (i = 1; i < nparent; ++i) {
			cmp = tree_entry_pathcmp(&tp[i], &tp[imin]);
			if (cmp < 0) {
				imin = i;
				tp[i].entry.mode &= ~S_IFXMIN_NEQ;
			}
			else if (cmp == 0) {
				tp[i].entry.mode &= ~S_IFXMIN_NEQ;
			}
			else {
				tp[i].entry.mode |= S_IFXMIN_NEQ;
			}
		}

		/* fixup markings for entries before imin */
		for (i = 0; i < imin; ++i)
			tp[i].entry.mode |= S_IFXMIN_NEQ;	/* pi > p[imin] */



		/* compare t vs p[imin] */
		cmp = tree_entry_pathcmp(&t, &tp[imin]);

		/* t = p[imin] */
		if (cmp == 0) {
			/* are either pi > p[imin] or diff(t,pi) != ø ? */
			if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER)) {
				for (i = 0; i < nparent; ++i) {
					/* p[i] > p[imin] */
					if (tp[i].entry.mode & S_IFXMIN_NEQ)
						continue;

					/* diff(t,pi) != ø */
					if (oidcmp(t.entry.oid, tp[i].entry.oid) ||
					    (t.entry.mode != tp[i].entry.mode))
						continue;

					goto skip_emit_t_tp;
				}
			}

			/* D += {δ(t,pi) if pi=p[imin];  "+a" if pi > p[imin]} */
			p = emit_path(p, base, opt, nparent,
					&t, tp, imin);

		skip_emit_t_tp:
			/* t↓,  ∀ pi=p[imin]  pi↓ */
			update_tree_entry(&t);
			update_tp_entries(tp, nparent);
		}

		/* t < p[imin] */
		else if (cmp < 0) {
			/* D += "+t" */
			p = emit_path(p, base, opt, nparent,
					&t, /*tp=*/NULL, -1);

			/* t↓ */
			update_tree_entry(&t);
		}

		/* t > p[imin] */
		else {
			/* ∀i pi=p[imin] -> D += "-p[imin]" */
			if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER)) {
				for (i = 0; i < nparent; ++i)
					if (tp[i].entry.mode & S_IFXMIN_NEQ)
						goto skip_emit_tp;
			}

			p = emit_path(p, base, opt, nparent,
					/*t=*/NULL, tp, imin);

		skip_emit_tp:
			/* ∀ pi=p[imin]  pi↓ */
			update_tp_entries(tp, nparent);
		}
	}

	free(ttree);
	for (i = nparent-1; i >= 0; i--)
		free(tptree[i]);
	FAST_ARRAY_FREE(tptree, nparent);
	FAST_ARRAY_FREE(tp, nparent);

	return p;
}
Exemplo n.º 20
0
static void extended_entry_extract(struct tree_desc_x *t,
				   struct name_entry *a,
				   const char *first,
				   int first_len)
{
	const char *path;
	int len;
	struct tree_desc probe;
	struct tree_desc_skip *skip;

	/*
	 * Extract the first entry from the tree_desc, but skip the
	 * ones that we already returned in earlier rounds.
	 */
	while (1) {
		if (!t->d.size) {
			entry_clear(a);
			break; /* not found */
		}
		entry_extract(&t->d, a);
		for (skip = t->skip; skip; skip = skip->prev)
			if (a->path == skip->ptr)
				break; /* found */
		if (!skip)
			break;
		/* We have processed this entry already. */
		update_tree_entry(&t->d);
	}

	if (!first || !a->path)
		return;

	/*
	 * The caller wants "first" from this tree, or nothing.
	 */
	path = a->path;
	len = tree_entry_len(a->path, a->sha1);
	switch (check_entry_match(first, first_len, path, len)) {
	case -1:
		entry_clear(a);
	case 0:
		return;
	default:
		break;
	}

	/*
	 * We need to look-ahead -- we suspect that a subtree whose
	 * name is "first" may be hiding behind the current entry "path".
	 */
	probe = t->d;
	while (probe.size) {
		entry_extract(&probe, a);
		path = a->path;
		len = tree_entry_len(a->path, a->sha1);
		switch (check_entry_match(first, first_len, path, len)) {
		case -1:
			entry_clear(a);
		case 0:
			return;
		default:
			update_tree_entry(&probe);
			break;
		}
		/* keep looking */
	}
	entry_clear(a);
}
Exemplo n.º 21
0
Arquivo: fsck.c Projeto: AndSoAway/git
static int fsck_tree(struct tree *item, struct fsck_options *options)
{
	int retval;
	int has_null_sha1 = 0;
	int has_full_path = 0;
	int has_empty_name = 0;
	int has_dot = 0;
	int has_dotdot = 0;
	int has_dotgit = 0;
	int has_zero_pad = 0;
	int has_bad_modes = 0;
	int has_dup_entries = 0;
	int not_properly_sorted = 0;
	struct tree_desc desc;
	unsigned o_mode;
	const char *o_name;

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

	o_mode = 0;
	o_name = NULL;

	while (desc.size) {
		unsigned mode;
		const char *name;
		const unsigned char *sha1;

		sha1 = tree_entry_extract(&desc, &name, &mode);

		has_null_sha1 |= is_null_sha1(sha1);
		has_full_path |= !!strchr(name, '/');
		has_empty_name |= !*name;
		has_dot |= !strcmp(name, ".");
		has_dotdot |= !strcmp(name, "..");
		has_dotgit |= (!strcmp(name, ".git") ||
			       is_hfs_dotgit(name) ||
			       is_ntfs_dotgit(name));
		has_zero_pad |= *(char *)desc.buffer == '0';
		update_tree_entry(&desc);

		switch (mode) {
		/*
		 * Standard modes..
		 */
		case S_IFREG | 0755:
		case S_IFREG | 0644:
		case S_IFLNK:
		case S_IFDIR:
		case S_IFGITLINK:
			break;
		/*
		 * This is nonstandard, but we had a few of these
		 * early on when we honored the full set of mode
		 * bits..
		 */
		case S_IFREG | 0664:
			if (!options->strict)
				break;
		default:
			has_bad_modes = 1;
		}

		if (o_name) {
			switch (verify_ordered(o_mode, o_name, mode, name)) {
			case TREE_UNORDERED:
				not_properly_sorted = 1;
				break;
			case TREE_HAS_DUPS:
				has_dup_entries = 1;
				break;
			default:
				break;
			}
		}

		o_mode = mode;
		o_name = name;
	}

	retval = 0;
	if (has_null_sha1)
		retval += report(options, &item->object, FSCK_MSG_NULL_SHA1, "contains entries pointing to null sha1");
	if (has_full_path)
		retval += report(options, &item->object, FSCK_MSG_FULL_PATHNAME, "contains full pathnames");
	if (has_empty_name)
		retval += report(options, &item->object, FSCK_MSG_EMPTY_NAME, "contains empty pathname");
	if (has_dot)
		retval += report(options, &item->object, FSCK_MSG_HAS_DOT, "contains '.'");
	if (has_dotdot)
		retval += report(options, &item->object, FSCK_MSG_HAS_DOTDOT, "contains '..'");
	if (has_dotgit)
		retval += report(options, &item->object, FSCK_MSG_HAS_DOTGIT, "contains '.git'");
	if (has_zero_pad)
		retval += report(options, &item->object, FSCK_MSG_ZERO_PADDED_FILEMODE, "contains zero-padded file modes");
	if (has_bad_modes)
		retval += report(options, &item->object, FSCK_MSG_BAD_FILEMODE, "contains bad file modes");
	if (has_dup_entries)
		retval += report(options, &item->object, FSCK_MSG_DUPLICATE_ENTRIES, "contains duplicate file entries");
	if (not_properly_sorted)
		retval += report(options, &item->object, FSCK_MSG_TREE_NOT_SORTED, "not properly sorted");
	return retval;
}
Exemplo n.º 22
0
int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
{
	int ret = 0;
	struct name_entry *entry = xmalloc(n*sizeof(*entry));

	for (;;) {
		unsigned long mask = 0;
		unsigned long dirmask = 0;
		int i, last;

		last = -1;
		for (i = 0; i < n; i++) {
			if (!t[i].size)
				continue;
			entry_extract(t+i, entry+i);
			if (last >= 0) {
				int cmp = entry_compare(entry+i, entry+last);

				/*
				 * Is the new name bigger than the old one?
				 * Ignore it
				 */
				if (cmp > 0)
					continue;
				/*
				 * Is the new name smaller than the old one?
				 * Ignore all old ones
				 */
				if (cmp < 0)
					mask = 0;
			}
			mask |= 1ul << i;
			if (S_ISDIR(entry[i].mode))
				dirmask |= 1ul << i;
			last = i;
		}
		if (!mask)
			break;
		dirmask &= mask;

		/*
		 * Clear all the unused name-entries.
		 */
		for (i = 0; i < n; i++) {
			if (mask & (1ul << i))
				continue;
			entry_clear(entry + i);
		}
		ret = info->fn(n, mask, dirmask, entry, info);
		if (ret < 0)
			break;
		if (ret)
			mask &= ret;
		ret = 0;
		for (i = 0; i < n; i++) {
			if (mask & (1ul << i))
				update_tree_entry(t + i);
		}
	}
	free(entry);
	return ret;
}
Exemplo n.º 23
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, *two_buf;
	int score = 0;
	enum object_type type;
	unsigned long size;

	one_buf = read_sha1_file(hash1, &type, &size);
	if (!one_buf)
		die("unable to read tree (%s)", sha1_to_hex(hash1));
	if (type != OBJ_TREE)
		die("%s is not a tree", sha1_to_hex(hash1));
	init_tree_desc(&one, one_buf, size);
	two_buf = read_sha1_file(hash2, &type, &size);
	if (!two_buf)
		die("unable to read tree (%s)", sha1_to_hex(hash2));
	if (type != OBJ_TREE)
		die("%s is not a tree", sha1_to_hex(hash2));
	init_tree_desc(&two, two_buf, size);
	while (one.size | two.size) {
		const unsigned char *elem1 = elem1;
		const unsigned char *elem2 = elem2;
		const char *path1 = path1;
		const char *path2 = path2;
		unsigned mode1 = mode1;
		unsigned mode2 = mode2;
		int cmp;

		if (one.size)
			elem1 = tree_entry_extract(&one, &path1, &mode1);
		if (two.size)
			elem2 = tree_entry_extract(&two, &path2, &mode2);

		if (!one.size) {
			/* two has more entries */
			score += score_missing(mode2, path2);
			update_tree_entry(&two);
			continue;
		}
		if (!two.size) {
			/* two lacks this entry */
			score += score_missing(mode1, path1);
			update_tree_entry(&one);
			continue;
		}
		cmp = base_name_compare(path1, strlen(path1), mode1,
					path2, strlen(path2), mode2);
		if (cmp < 0) {
			/* path1 does not appear in two */
			score += score_missing(mode1, path1);
			update_tree_entry(&one);
			continue;
		}
		else if (cmp > 0) {
			/* path2 does not appear in one */
			score += score_missing(mode2, path2);
			update_tree_entry(&two);
			continue;
		}
		else if (hashcmp(elem1, elem2))
			/* they are different */
			score += score_differs(mode1, mode2, path1);
		else
			/* same subtree or blob */
			score += score_matches(mode1, mode2, path1);
		update_tree_entry(&one);
		update_tree_entry(&two);
	}
	free(one_buf);
	free(two_buf);
	return score;
}