* [PATCH] ls-files: allow relative pathspec
@ 2010-05-22 16:35 Clemens Buchacher
2010-05-26 5:07 ` Junio C Hamano
0 siblings, 1 reply; 3+ messages in thread
From: Clemens Buchacher @ 2010-05-22 16:35 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
git ls-files used to error out if given paths which point outside
the current working directory, such as '../'. We now allow such
paths and the output is analogous to git grep -l.
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
---
builtin/ls-files.c | 61 +++++++++++++++++++++++++++++-----------------------
t/t7010-setup.sh | 12 +++------
2 files changed, 38 insertions(+), 35 deletions(-)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index c0fbcdc..441da81 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -26,7 +26,8 @@ static int show_killed;
static int show_valid_bit;
static int line_terminator = '\n';
-static int prefix_len;
+static const char *prefix;
+static int max_prefix_len;
static int prefix_offset;
static const char **pathspec;
static int error_unmatch;
@@ -43,10 +44,19 @@ static const char *tag_modified = "";
static const char *tag_skip_worktree = "";
static const char *tag_resolve_undo = "";
+static void write_name(const char* name, size_t len)
+{
+ struct strbuf path = STRBUF_INIT;
+ if (prefix_offset > 0)
+ quote_path_relative(name, len, &path, prefix);
+ else
+ strbuf_add(&path, name, len);
+ write_name_quoted(strbuf_detach(&path, NULL), stdout, line_terminator);
+}
+
static void show_dir_entry(const char *tag, struct dir_entry *ent)
{
- int len = prefix_len;
- int offset = prefix_offset;
+ int len = max_prefix_len;
if (len >= ent->len)
die("git ls-files: internal error - directory entry not superset of prefix");
@@ -55,7 +65,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
return;
fputs(tag, stdout);
- write_name_quoted(ent->name + offset, stdout, line_terminator);
+ write_name(ent->name, ent->len);
}
static void show_other_files(struct dir_struct *dir)
@@ -121,8 +131,7 @@ static void show_killed_files(struct dir_struct *dir)
static void show_ce_entry(const char *tag, struct cache_entry *ce)
{
- int len = prefix_len;
- int offset = prefix_offset;
+ int len = max_prefix_len;
if (len >= ce_namelen(ce))
die("git ls-files: internal error - cache entry not superset of prefix");
@@ -156,20 +165,19 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
find_unique_abbrev(ce->sha1,abbrev),
ce_stage(ce));
}
- write_name_quoted(ce->name + offset, stdout, line_terminator);
+ write_name(ce->name, ce_namelen(ce));
}
static int show_one_ru(struct string_list_item *item, void *cbdata)
{
- int offset = prefix_offset;
const char *path = item->string;
struct resolve_undo_info *ui = item->util;
int i, len;
len = strlen(path);
- if (len < prefix_len)
+ if (len < max_prefix_len)
return 0; /* outside of the prefix */
- if (!match_pathspec(pathspec, path, len, prefix_len, ps_matched))
+ if (!match_pathspec(pathspec, path, len, max_prefix_len, ps_matched))
return 0; /* uninterested */
for (i = 0; i < 3; i++) {
if (!ui->mode[i])
@@ -177,19 +185,19 @@ static int show_one_ru(struct string_list_item *item, void *cbdata)
printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
find_unique_abbrev(ui->sha1[i], abbrev),
i + 1);
- write_name_quoted(path + offset, stdout, line_terminator);
+ write_name(path, len);
}
return 0;
}
-static void show_ru_info(const char *prefix)
+static void show_ru_info()
{
if (!the_index.resolve_undo)
return;
for_each_string_list(show_one_ru, the_index.resolve_undo, NULL);
}
-static void show_files(struct dir_struct *dir, const char *prefix)
+static void show_files(struct dir_struct *dir)
{
int i;
@@ -243,7 +251,7 @@ static void show_files(struct dir_struct *dir, const char *prefix)
*/
static void prune_cache(const char *prefix)
{
- int pos = cache_name_pos(prefix, prefix_len);
+ int pos = cache_name_pos(prefix, max_prefix_len);
unsigned int first, last;
if (pos < 0)
@@ -256,7 +264,7 @@ static void prune_cache(const char *prefix)
while (last > first) {
int next = (last + first) >> 1;
struct cache_entry *ce = active_cache[next];
- if (!strncmp(ce->name, prefix, prefix_len)) {
+ if (!strncmp(ce->name, prefix, max_prefix_len)) {
first = next+1;
continue;
}
@@ -265,7 +273,7 @@ static void prune_cache(const char *prefix)
active_nr = last;
}
-static const char *verify_pathspec(const char *prefix)
+static const char *verify_pathspec(const char* prefix)
{
const char **p, *n, *prev;
unsigned long max;
@@ -291,10 +299,7 @@ static const char *verify_pathspec(const char *prefix)
}
}
- if (prefix_offset > max || memcmp(prev, prefix, prefix_offset))
- die("git ls-files: cannot generate relative filenames containing '..'");
-
- prefix_len = max;
+ max_prefix_len = max;
return max ? xmemdupz(prev, max) : NULL;
}
@@ -456,9 +461,10 @@ static int option_parse_exclude_standard(const struct option *opt,
return 0;
}
-int cmd_ls_files(int argc, const char **argv, const char *prefix)
+int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
{
int require_work_tree = 0, show_tag = 0;
+ const char *max_prefix;
struct dir_struct dir;
struct option builtin_ls_files_options[] = {
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
@@ -516,6 +522,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
};
memset(&dir, 0, sizeof(dir));
+ prefix = cmd_prefix;
if (prefix)
prefix_offset = strlen(prefix);
git_config(git_default_config, NULL);
@@ -557,7 +564,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
/* Verify that the pathspec matches the prefix */
if (pathspec)
- prefix = verify_pathspec(prefix);
+ max_prefix = verify_pathspec(prefix);
/* Treat unmatching pathspec elements as errors */
if (pathspec && error_unmatch) {
@@ -575,8 +582,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
show_killed | show_modified | show_resolve_undo))
show_cached = 1;
- if (prefix)
- prune_cache(prefix);
+ if (max_prefix)
+ prune_cache(max_prefix);
if (with_tree) {
/*
* Basic sanity check; show-stages and show-unmerged
@@ -584,11 +591,11 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
*/
if (show_stage || show_unmerged)
die("ls-files --with-tree is incompatible with -s or -u");
- overlay_tree_on_cache(with_tree, prefix);
+ overlay_tree_on_cache(with_tree, max_prefix);
}
- show_files(&dir, prefix);
+ show_files(&dir);
if (show_resolve_undo)
- show_ru_info(prefix);
+ show_ru_info();
if (ps_matched) {
int bad;
diff --git a/t/t7010-setup.sh b/t/t7010-setup.sh
index d8a7c79..0335a9a 100755
--- a/t/t7010-setup.sh
+++ b/t/t7010-setup.sh
@@ -103,14 +103,10 @@ test_expect_success 'git ls-files (relative #3)' '
git add a &&
(
cd a/b &&
- if git ls-files "../e/f"
- then
- echo Gaah, should have failed
- exit 1
- else
- : happy
- fi
- )
+ git ls-files "../e/f"
+ ) >current &&
+ echo ../e/f >expect &&
+ test_cmp expect current
'
--
1.7.0.5.3.ga76e
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] ls-files: allow relative pathspec
2010-05-22 16:35 [PATCH] ls-files: allow relative pathspec Clemens Buchacher
@ 2010-05-26 5:07 ` Junio C Hamano
2010-05-26 21:05 ` [PATCH v2] " Clemens Buchacher
0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2010-05-26 5:07 UTC (permalink / raw)
To: Clemens Buchacher; +Cc: git, Junio C Hamano
Clemens Buchacher <drizzd@aon.at> writes:
> git ls-files used to error out if given paths which point outside
> the current working directory, such as '../'. We now allow such
> paths and the output is analogous to git grep -l.
>
> Signed-off-by: Clemens Buchacher <drizzd@aon.at>
> ---
> builtin/ls-files.c | 61 +++++++++++++++++++++++++++++-----------------------
> t/t7010-setup.sh | 12 +++------
> 2 files changed, 38 insertions(+), 35 deletions(-)
>
> diff --git a/builtin/ls-files.c b/builtin/ls-files.c
> index c0fbcdc..441da81 100644
> --- a/builtin/ls-files.c
> +++ b/builtin/ls-files.c
> ...
> @@ -177,19 +185,19 @@ static int show_one_ru(struct string_list_item *item, void *cbdata)
> printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
> find_unique_abbrev(ui->sha1[i], abbrev),
> i + 1);
> - write_name_quoted(path + offset, stdout, line_terminator);
> + write_name(path, len);
> }
> return 0;
> }
>
> -static void show_ru_info(const char *prefix)
> +static void show_ru_info()
s/info()/info(void)/;
> @@ -265,7 +273,7 @@ static void prune_cache(const char *prefix)
> active_nr = last;
> }
>
> -static const char *verify_pathspec(const char *prefix)
> +static const char *verify_pathspec(const char* prefix)
Please don't; this is not C++.
> @@ -456,9 +461,10 @@ static int option_parse_exclude_standard(const struct option *opt,
> return 0;
> }
>
> -int cmd_ls_files(int argc, const char **argv, const char *prefix)
> +int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
> {
> int require_work_tree = 0, show_tag = 0;
> + const char *max_prefix;
This variable is used uninitialized when pathspec is NULL, I think.
Other than that, the patch feels sane. Thanks.
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2] ls-files: allow relative pathspec
2010-05-26 5:07 ` Junio C Hamano
@ 2010-05-26 21:05 ` Clemens Buchacher
0 siblings, 0 replies; 3+ messages in thread
From: Clemens Buchacher @ 2010-05-26 21:05 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
git ls-files used to error out if given paths which point outside the current
working directory, such as '../'. We now allow such paths and the output is
analogous to git grep -l.
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
---
On Tue, May 25, 2010 at 10:07:39PM -0700, Junio C Hamano wrote:
> Clemens Buchacher <drizzd@aon.at> writes:
>
> > @@ -456,9 +461,10 @@ static int option_parse_exclude_standard(const struct option *opt,
> > return 0;
> > }
> >
> > -int cmd_ls_files(int argc, const char **argv, const char *prefix)
> > +int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
> > {
> > int require_work_tree = 0, show_tag = 0;
> > + const char *max_prefix;
>
> This variable is used uninitialized when pathspec is NULL, I think.
Indeed, thank you for reviewing.
I also renamed verify_pathspec to pathspec_prefix, since it does
not actually verify anything.
Clemens
builtin/ls-files.c | 69 ++++++++++++++++++++++++++++++----------------------
t/t7010-setup.sh | 12 +++------
2 files changed, 44 insertions(+), 37 deletions(-)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index c0fbcdc..30ebe2c 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -26,7 +26,8 @@ static int show_killed;
static int show_valid_bit;
static int line_terminator = '\n';
-static int prefix_len;
+static const char *prefix;
+static int max_prefix_len;
static int prefix_offset;
static const char **pathspec;
static int error_unmatch;
@@ -43,10 +44,19 @@ static const char *tag_modified = "";
static const char *tag_skip_worktree = "";
static const char *tag_resolve_undo = "";
+static void write_name(const char* name, size_t len)
+{
+ struct strbuf path = STRBUF_INIT;
+ if (prefix_offset > 0)
+ quote_path_relative(name, len, &path, prefix);
+ else
+ strbuf_add(&path, name, len);
+ write_name_quoted(strbuf_detach(&path, NULL), stdout, line_terminator);
+}
+
static void show_dir_entry(const char *tag, struct dir_entry *ent)
{
- int len = prefix_len;
- int offset = prefix_offset;
+ int len = max_prefix_len;
if (len >= ent->len)
die("git ls-files: internal error - directory entry not superset of prefix");
@@ -55,7 +65,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
return;
fputs(tag, stdout);
- write_name_quoted(ent->name + offset, stdout, line_terminator);
+ write_name(ent->name, ent->len);
}
static void show_other_files(struct dir_struct *dir)
@@ -121,8 +131,7 @@ static void show_killed_files(struct dir_struct *dir)
static void show_ce_entry(const char *tag, struct cache_entry *ce)
{
- int len = prefix_len;
- int offset = prefix_offset;
+ int len = max_prefix_len;
if (len >= ce_namelen(ce))
die("git ls-files: internal error - cache entry not superset of prefix");
@@ -156,20 +165,19 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
find_unique_abbrev(ce->sha1,abbrev),
ce_stage(ce));
}
- write_name_quoted(ce->name + offset, stdout, line_terminator);
+ write_name(ce->name, ce_namelen(ce));
}
static int show_one_ru(struct string_list_item *item, void *cbdata)
{
- int offset = prefix_offset;
const char *path = item->string;
struct resolve_undo_info *ui = item->util;
int i, len;
len = strlen(path);
- if (len < prefix_len)
+ if (len < max_prefix_len)
return 0; /* outside of the prefix */
- if (!match_pathspec(pathspec, path, len, prefix_len, ps_matched))
+ if (!match_pathspec(pathspec, path, len, max_prefix_len, ps_matched))
return 0; /* uninterested */
for (i = 0; i < 3; i++) {
if (!ui->mode[i])
@@ -177,19 +185,19 @@ static int show_one_ru(struct string_list_item *item, void *cbdata)
printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
find_unique_abbrev(ui->sha1[i], abbrev),
i + 1);
- write_name_quoted(path + offset, stdout, line_terminator);
+ write_name(path, len);
}
return 0;
}
-static void show_ru_info(const char *prefix)
+static void show_ru_info(void)
{
if (!the_index.resolve_undo)
return;
for_each_string_list(show_one_ru, the_index.resolve_undo, NULL);
}
-static void show_files(struct dir_struct *dir, const char *prefix)
+static void show_files(struct dir_struct *dir)
{
int i;
@@ -243,7 +251,7 @@ static void show_files(struct dir_struct *dir, const char *prefix)
*/
static void prune_cache(const char *prefix)
{
- int pos = cache_name_pos(prefix, prefix_len);
+ int pos = cache_name_pos(prefix, max_prefix_len);
unsigned int first, last;
if (pos < 0)
@@ -256,7 +264,7 @@ static void prune_cache(const char *prefix)
while (last > first) {
int next = (last + first) >> 1;
struct cache_entry *ce = active_cache[next];
- if (!strncmp(ce->name, prefix, prefix_len)) {
+ if (!strncmp(ce->name, prefix, max_prefix_len)) {
first = next+1;
continue;
}
@@ -265,11 +273,16 @@ static void prune_cache(const char *prefix)
active_nr = last;
}
-static const char *verify_pathspec(const char *prefix)
+static const char *pathspec_prefix(const char *prefix)
{
const char **p, *n, *prev;
unsigned long max;
+ if (!pathspec) {
+ max_prefix_len = prefix ? strlen(prefix) : 0;
+ return prefix;
+ }
+
prev = NULL;
max = PATH_MAX;
for (p = pathspec; (n = *p) != NULL; p++) {
@@ -291,10 +304,7 @@ static const char *verify_pathspec(const char *prefix)
}
}
- if (prefix_offset > max || memcmp(prev, prefix, prefix_offset))
- die("git ls-files: cannot generate relative filenames containing '..'");
-
- prefix_len = max;
+ max_prefix_len = max;
return max ? xmemdupz(prev, max) : NULL;
}
@@ -456,9 +466,10 @@ static int option_parse_exclude_standard(const struct option *opt,
return 0;
}
-int cmd_ls_files(int argc, const char **argv, const char *prefix)
+int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
{
int require_work_tree = 0, show_tag = 0;
+ const char *max_prefix;
struct dir_struct dir;
struct option builtin_ls_files_options[] = {
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
@@ -516,6 +527,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
};
memset(&dir, 0, sizeof(dir));
+ prefix = cmd_prefix;
if (prefix)
prefix_offset = strlen(prefix);
git_config(git_default_config, NULL);
@@ -555,9 +567,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
if (pathspec)
strip_trailing_slash_from_submodules();
- /* Verify that the pathspec matches the prefix */
- if (pathspec)
- prefix = verify_pathspec(prefix);
+ /* Find common prefix for all pathspec's */
+ max_prefix = pathspec_prefix(prefix);
/* Treat unmatching pathspec elements as errors */
if (pathspec && error_unmatch) {
@@ -575,8 +586,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
show_killed | show_modified | show_resolve_undo))
show_cached = 1;
- if (prefix)
- prune_cache(prefix);
+ if (max_prefix)
+ prune_cache(max_prefix);
if (with_tree) {
/*
* Basic sanity check; show-stages and show-unmerged
@@ -584,11 +595,11 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
*/
if (show_stage || show_unmerged)
die("ls-files --with-tree is incompatible with -s or -u");
- overlay_tree_on_cache(with_tree, prefix);
+ overlay_tree_on_cache(with_tree, max_prefix);
}
- show_files(&dir, prefix);
+ show_files(&dir);
if (show_resolve_undo)
- show_ru_info(prefix);
+ show_ru_info();
if (ps_matched) {
int bad;
diff --git a/t/t7010-setup.sh b/t/t7010-setup.sh
index d8a7c79..0335a9a 100755
--- a/t/t7010-setup.sh
+++ b/t/t7010-setup.sh
@@ -103,14 +103,10 @@ test_expect_success 'git ls-files (relative #3)' '
git add a &&
(
cd a/b &&
- if git ls-files "../e/f"
- then
- echo Gaah, should have failed
- exit 1
- else
- : happy
- fi
- )
+ git ls-files "../e/f"
+ ) >current &&
+ echo ../e/f >expect &&
+ test_cmp expect current
'
--
1.7.0.5.3.ga76e
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2010-05-26 21:05 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-22 16:35 [PATCH] ls-files: allow relative pathspec Clemens Buchacher
2010-05-26 5:07 ` Junio C Hamano
2010-05-26 21:05 ` [PATCH v2] " Clemens Buchacher
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).