Merge branch 'nd/ls-tree-pathspec'
"git ls-tree" does not support path selection based on negative pathspecs, but did not error out when negative pathspecs are given. * nd/ls-tree-pathspec: t3102: style modernization t3102: document that ls-tree does not yet support negated pathspec ls-tree: disable negative pathspec because it's not supported ls-tree: remove path filtering logic in show_tree tree.c: update read_tree_recursive callback to pass strbuf as basemaint
						commit
						570077231f
					
				
							
								
								
									
										34
									
								
								archive.c
								
								
								
								
							
							
						
						
									
										34
									
								
								archive.c
								
								
								
								
							| 
						 | 
				
			
			@ -157,18 +157,26 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
 | 
			
		|||
	return write_entry(args, sha1, path.buf, path.len, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int write_archive_entry_buf(const unsigned char *sha1, struct strbuf *base,
 | 
			
		||||
		const char *filename, unsigned mode, int stage,
 | 
			
		||||
		void *context)
 | 
			
		||||
{
 | 
			
		||||
	return write_archive_entry(sha1, base->buf, base->len,
 | 
			
		||||
				     filename, mode, stage, context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void queue_directory(const unsigned char *sha1,
 | 
			
		||||
		const char *base, int baselen, const char *filename,
 | 
			
		||||
		struct strbuf *base, const char *filename,
 | 
			
		||||
		unsigned mode, int stage, struct archiver_context *c)
 | 
			
		||||
{
 | 
			
		||||
	struct directory *d;
 | 
			
		||||
	d = xmallocz(sizeof(*d) + baselen + 1 + strlen(filename));
 | 
			
		||||
	d = xmallocz(sizeof(*d) + base->len + 1 + strlen(filename));
 | 
			
		||||
	d->up	   = c->bottom;
 | 
			
		||||
	d->baselen = baselen;
 | 
			
		||||
	d->baselen = base->len;
 | 
			
		||||
	d->mode	   = mode;
 | 
			
		||||
	d->stage   = stage;
 | 
			
		||||
	c->bottom  = d;
 | 
			
		||||
	d->len = sprintf(d->path, "%.*s%s/", baselen, base, filename);
 | 
			
		||||
	d->len = sprintf(d->path, "%.*s%s/", (int)base->len, base->buf, filename);
 | 
			
		||||
	hashcpy(d->sha1, sha1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -191,28 +199,28 @@ static int write_directory(struct archiver_context *c)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static int queue_or_write_archive_entry(const unsigned char *sha1,
 | 
			
		||||
		const char *base, int baselen, const char *filename,
 | 
			
		||||
		struct strbuf *base, const char *filename,
 | 
			
		||||
		unsigned mode, int stage, void *context)
 | 
			
		||||
{
 | 
			
		||||
	struct archiver_context *c = context;
 | 
			
		||||
 | 
			
		||||
	while (c->bottom &&
 | 
			
		||||
	       !(baselen >= c->bottom->len &&
 | 
			
		||||
		 !strncmp(base, c->bottom->path, c->bottom->len))) {
 | 
			
		||||
	       !(base->len >= c->bottom->len &&
 | 
			
		||||
		 !strncmp(base->buf, c->bottom->path, c->bottom->len))) {
 | 
			
		||||
		struct directory *next = c->bottom->up;
 | 
			
		||||
		free(c->bottom);
 | 
			
		||||
		c->bottom = next;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (S_ISDIR(mode)) {
 | 
			
		||||
		queue_directory(sha1, base, baselen, filename,
 | 
			
		||||
		queue_directory(sha1, base, filename,
 | 
			
		||||
				mode, stage, c);
 | 
			
		||||
		return READ_TREE_RECURSIVE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (write_directory(c))
 | 
			
		||||
		return -1;
 | 
			
		||||
	return write_archive_entry(sha1, base, baselen, filename, mode,
 | 
			
		||||
	return write_archive_entry(sha1, base->buf, base->len, filename, mode,
 | 
			
		||||
				   stage, context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -260,7 +268,7 @@ int write_archive_entries(struct archiver_args *args,
 | 
			
		|||
	err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec,
 | 
			
		||||
				  args->pathspec.has_wildcard ?
 | 
			
		||||
				  queue_or_write_archive_entry :
 | 
			
		||||
				  write_archive_entry,
 | 
			
		||||
				  write_archive_entry_buf,
 | 
			
		||||
				  &context);
 | 
			
		||||
	if (err == READ_TREE_RECURSIVE)
 | 
			
		||||
		err = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -286,14 +294,14 @@ static const struct archiver *lookup_archiver(const char *name)
 | 
			
		|||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int reject_entry(const unsigned char *sha1, const char *base,
 | 
			
		||||
			int baselen, const char *filename, unsigned mode,
 | 
			
		||||
static int reject_entry(const unsigned char *sha1, struct strbuf *base,
 | 
			
		||||
			const char *filename, unsigned mode,
 | 
			
		||||
			int stage, void *context)
 | 
			
		||||
{
 | 
			
		||||
	int ret = -1;
 | 
			
		||||
	if (S_ISDIR(mode)) {
 | 
			
		||||
		struct strbuf sb = STRBUF_INIT;
 | 
			
		||||
		strbuf_addstr(&sb, base);
 | 
			
		||||
		strbuf_addbuf(&sb, base);
 | 
			
		||||
		strbuf_addstr(&sb, filename);
 | 
			
		||||
		if (!match_pathspec(context, sb.buf, sb.len, 0, NULL, 1))
 | 
			
		||||
			ret = READ_TREE_RECURSIVE;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int update_some(const unsigned char *sha1, const char *base, int baselen,
 | 
			
		||||
static int update_some(const unsigned char *sha1, struct strbuf *base,
 | 
			
		||||
		const char *pathname, unsigned mode, int stage, void *context)
 | 
			
		||||
{
 | 
			
		||||
	int len;
 | 
			
		||||
| 
						 | 
				
			
			@ -72,11 +72,11 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
 | 
			
		|||
	if (S_ISDIR(mode))
 | 
			
		||||
		return READ_TREE_RECURSIVE;
 | 
			
		||||
 | 
			
		||||
	len = baselen + strlen(pathname);
 | 
			
		||||
	len = base->len + strlen(pathname);
 | 
			
		||||
	ce = xcalloc(1, cache_entry_size(len));
 | 
			
		||||
	hashcpy(ce->sha1, sha1);
 | 
			
		||||
	memcpy(ce->name, base, baselen);
 | 
			
		||||
	memcpy(ce->name + baselen, pathname, len - baselen);
 | 
			
		||||
	memcpy(ce->name, base->buf, base->len);
 | 
			
		||||
	memcpy(ce->name + base->len, pathname, len - base->len);
 | 
			
		||||
	ce->ce_flags = create_ce_flags(0) | CE_UPDATE;
 | 
			
		||||
	ce->ce_namelen = len;
 | 
			
		||||
	ce->ce_mode = create_ce_mode(mode);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -489,7 +489,7 @@ static int show_tag_object(const unsigned char *sha1, struct rev_info *rev)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static int show_tree_object(const unsigned char *sha1,
 | 
			
		||||
		const char *base, int baselen,
 | 
			
		||||
		struct strbuf *base,
 | 
			
		||||
		const char *pathname, unsigned mode, int stage, void *context)
 | 
			
		||||
{
 | 
			
		||||
	printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,10 +61,11 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int show_tree(const unsigned char *sha1, const char *base, int baselen,
 | 
			
		||||
static int show_tree(const unsigned char *sha1, struct strbuf *base,
 | 
			
		||||
		const char *pathname, unsigned mode, int stage, void *context)
 | 
			
		||||
{
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
	int baselen;
 | 
			
		||||
	const char *type = blob_type;
 | 
			
		||||
 | 
			
		||||
	if (S_ISGITLINK(mode)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +80,7 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
 | 
			
		|||
		 */
 | 
			
		||||
		type = commit_type;
 | 
			
		||||
	} else if (S_ISDIR(mode)) {
 | 
			
		||||
		if (show_recursive(base, baselen, pathname)) {
 | 
			
		||||
		if (show_recursive(base->buf, base->len, pathname)) {
 | 
			
		||||
			retval = READ_TREE_RECURSIVE;
 | 
			
		||||
			if (!(ls_options & LS_SHOW_TREES))
 | 
			
		||||
				return retval;
 | 
			
		||||
| 
						 | 
				
			
			@ -89,10 +90,6 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
 | 
			
		|||
	else if (ls_options & LS_TREE_ONLY)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (chomp_prefix &&
 | 
			
		||||
	    (baselen < chomp_prefix || memcmp(ls_tree_prefix, base, chomp_prefix)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!(ls_options & LS_NAME_ONLY)) {
 | 
			
		||||
		if (ls_options & LS_SHOW_SIZE) {
 | 
			
		||||
			char size_text[24];
 | 
			
		||||
| 
						 | 
				
			
			@ -112,8 +109,12 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
 | 
			
		|||
			printf("%06o %s %s\t", mode, type,
 | 
			
		||||
			       find_unique_abbrev(sha1, abbrev));
 | 
			
		||||
	}
 | 
			
		||||
	write_name_quotedpfx(base + chomp_prefix, baselen - chomp_prefix,
 | 
			
		||||
			  pathname, stdout, line_termination);
 | 
			
		||||
	baselen = base->len;
 | 
			
		||||
	strbuf_addstr(base, pathname);
 | 
			
		||||
	write_name_quoted_relative(base->buf,
 | 
			
		||||
				   chomp_prefix ? ls_tree_prefix : NULL,
 | 
			
		||||
				   stdout, line_termination);
 | 
			
		||||
	strbuf_setlen(base, baselen);
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +174,8 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 | 
			
		|||
	 * cannot be lifted until it is converted to use
 | 
			
		||||
	 * match_pathspec() or tree_entry_interesting()
 | 
			
		||||
	 */
 | 
			
		||||
	parse_pathspec(&pathspec, PATHSPEC_GLOB | PATHSPEC_ICASE,
 | 
			
		||||
	parse_pathspec(&pathspec, PATHSPEC_GLOB | PATHSPEC_ICASE |
 | 
			
		||||
				  PATHSPEC_EXCLUDE,
 | 
			
		||||
		       PATHSPEC_PREFER_CWD,
 | 
			
		||||
		       prefix, argv + 1);
 | 
			
		||||
	for (i = 0; i < pathspec.nr; i++)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -275,23 +275,20 @@ struct tree *write_tree_from_memory(struct merge_options *o)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static int save_files_dirs(const unsigned char *sha1,
 | 
			
		||||
		const char *base, int baselen, const char *path,
 | 
			
		||||
		struct strbuf *base, const char *path,
 | 
			
		||||
		unsigned int mode, int stage, void *context)
 | 
			
		||||
{
 | 
			
		||||
	int len = strlen(path);
 | 
			
		||||
	char *newpath = xmalloc(baselen + len + 1);
 | 
			
		||||
	int baselen = base->len;
 | 
			
		||||
	struct merge_options *o = context;
 | 
			
		||||
 | 
			
		||||
	memcpy(newpath, base, baselen);
 | 
			
		||||
	memcpy(newpath + baselen, path, len);
 | 
			
		||||
	newpath[baselen + len] = '\0';
 | 
			
		||||
	strbuf_addstr(base, path);
 | 
			
		||||
 | 
			
		||||
	if (S_ISDIR(mode))
 | 
			
		||||
		string_list_insert(&o->current_directory_set, newpath);
 | 
			
		||||
		string_list_insert(&o->current_directory_set, base->buf);
 | 
			
		||||
	else
 | 
			
		||||
		string_list_insert(&o->current_file_set, newpath);
 | 
			
		||||
	free(newpath);
 | 
			
		||||
		string_list_insert(&o->current_file_set, base->buf);
 | 
			
		||||
 | 
			
		||||
	strbuf_setlen(base, baselen);
 | 
			
		||||
	return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								quote.c
								
								
								
								
							
							
						
						
									
										21
									
								
								quote.c
								
								
								
								
							| 
						 | 
				
			
			@ -274,27 +274,6 @@ void write_name_quoted(const char *name, FILE *fp, int terminator)
 | 
			
		|||
	fputc(terminator, fp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void write_name_quotedpfx(const char *pfx, size_t pfxlen,
 | 
			
		||||
			  const char *name, FILE *fp, int terminator)
 | 
			
		||||
{
 | 
			
		||||
	int needquote = 0;
 | 
			
		||||
 | 
			
		||||
	if (terminator) {
 | 
			
		||||
		needquote = next_quote_pos(pfx, pfxlen) < pfxlen
 | 
			
		||||
			|| name[next_quote_pos(name, -1)];
 | 
			
		||||
	}
 | 
			
		||||
	if (needquote) {
 | 
			
		||||
		fputc('"', fp);
 | 
			
		||||
		quote_c_style_counted(pfx, pfxlen, NULL, fp, 1);
 | 
			
		||||
		quote_c_style(name, NULL, fp, 1);
 | 
			
		||||
		fputc('"', fp);
 | 
			
		||||
	} else {
 | 
			
		||||
		fwrite(pfx, pfxlen, 1, fp);
 | 
			
		||||
		fputs(name, fp);
 | 
			
		||||
	}
 | 
			
		||||
	fputc(terminator, fp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void write_name_quoted_relative(const char *name, const char *prefix,
 | 
			
		||||
				FILE *fp, int terminator)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								quote.h
								
								
								
								
							
							
						
						
									
										2
									
								
								quote.h
								
								
								
								
							| 
						 | 
				
			
			@ -56,8 +56,6 @@ extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq
 | 
			
		|||
extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
 | 
			
		||||
 | 
			
		||||
extern void write_name_quoted(const char *name, FILE *, int terminator);
 | 
			
		||||
extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
 | 
			
		||||
                                 const char *name, FILE *, int terminator);
 | 
			
		||||
extern void write_name_quoted_relative(const char *name, const char *prefix,
 | 
			
		||||
		FILE *fp, int terminator);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,11 +12,25 @@ test_expect_success 'setup' '
 | 
			
		|||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'ls-tree a[a] matches literally' '
 | 
			
		||||
	cat >expected <<EOF &&
 | 
			
		||||
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	a[a]/three
 | 
			
		||||
EOF
 | 
			
		||||
	cat >expect <<-\EOF &&
 | 
			
		||||
	100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	a[a]/three
 | 
			
		||||
	EOF
 | 
			
		||||
	git ls-tree -r HEAD "a[a]" >actual &&
 | 
			
		||||
	test_cmp expected actual
 | 
			
		||||
	test_cmp expect actual
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'ls-tree outside prefix' '
 | 
			
		||||
	cat >expect <<-\EOF &&
 | 
			
		||||
	100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	../a[a]/three
 | 
			
		||||
	EOF
 | 
			
		||||
	( cd aa && git ls-tree -r HEAD "../a[a]"; ) >actual &&
 | 
			
		||||
	test_cmp expect actual
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_failure 'ls-tree does not yet support negated pathspec' '
 | 
			
		||||
	git ls-files ":(exclude)a" "a*" >expect &&
 | 
			
		||||
	git ls-tree --name-only -r HEAD ":(exclude)a" "a*" >actual &&
 | 
			
		||||
	test_cmp expect actual
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_done
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								tree.c
								
								
								
								
							
							
						
						
									
										16
									
								
								tree.c
								
								
								
								
							| 
						 | 
				
			
			@ -30,9 +30,12 @@ static int read_one_entry_opt(const unsigned char *sha1, const char *base, int b
 | 
			
		|||
	return add_cache_entry(ce, opt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)
 | 
			
		||||
static int read_one_entry(const unsigned char *sha1, struct strbuf *base,
 | 
			
		||||
			  const char *pathname, unsigned mode, int stage,
 | 
			
		||||
			  void *context)
 | 
			
		||||
{
 | 
			
		||||
	return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,
 | 
			
		||||
	return read_one_entry_opt(sha1, base->buf, base->len, pathname,
 | 
			
		||||
				  mode, stage,
 | 
			
		||||
				  ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,9 +43,12 @@ static int read_one_entry(const unsigned char *sha1, const char *base, int basel
 | 
			
		|||
 * This is used when the caller knows there is no existing entries at
 | 
			
		||||
 * the stage that will conflict with the entry being added.
 | 
			
		||||
 */
 | 
			
		||||
static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)
 | 
			
		||||
static int read_one_entry_quick(const unsigned char *sha1, struct strbuf *base,
 | 
			
		||||
				const char *pathname, unsigned mode, int stage,
 | 
			
		||||
				void *context)
 | 
			
		||||
{
 | 
			
		||||
	return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,
 | 
			
		||||
	return read_one_entry_opt(sha1, base->buf, base->len, pathname,
 | 
			
		||||
				  mode, stage,
 | 
			
		||||
				  ADD_CACHE_JUST_APPEND);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +76,7 @@ static int read_tree_1(struct tree *tree, struct strbuf *base,
 | 
			
		|||
				continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch (fn(entry.sha1, base->buf, base->len,
 | 
			
		||||
		switch (fn(entry.sha1, base,
 | 
			
		||||
			   entry.path, entry.mode, stage, context)) {
 | 
			
		||||
		case 0:
 | 
			
		||||
			continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								tree.h
								
								
								
								
							
							
						
						
									
										3
									
								
								tree.h
								
								
								
								
							| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
#include "object.h"
 | 
			
		||||
 | 
			
		||||
extern const char *tree_type;
 | 
			
		||||
struct strbuf;
 | 
			
		||||
 | 
			
		||||
struct tree {
 | 
			
		||||
	struct object object;
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +23,7 @@ void free_tree_buffer(struct tree *tree);
 | 
			
		|||
struct tree *parse_tree_indirect(const unsigned char *sha1);
 | 
			
		||||
 | 
			
		||||
#define READ_TREE_RECURSIVE 1
 | 
			
		||||
typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int, void *);
 | 
			
		||||
typedef int (*read_tree_fn_t)(const unsigned char *, struct strbuf *, const char *, unsigned int, int, void *);
 | 
			
		||||
 | 
			
		||||
extern int read_tree_recursive(struct tree *tree,
 | 
			
		||||
			       const char *base, int baselen,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue