Merge branch 'dp/clean-fix'

* dp/clean-fix:
  git-clean: add tests for relative path
  git-clean: correct printing relative path
  Make private quote_path() in wt-status.c available as quote_path_relative()
  Revert part of d089eba (setup: sanitize absolute and funny paths in get_pathspec())
  Revert part of 1abf095 (git-add: adjust to the get_pathspec() changes)
  Revert part of 744dacd (builtin-mv: minimum fix to avoid losing files)
  get_pathspec(): die when an out-of-tree path is given
This commit is contained in:
Junio C Hamano 2008-03-08 21:29:56 -08:00
commit 175f559551
11 changed files with 123 additions and 94 deletions

View File

@ -228,18 +228,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
goto finish;
}
if (*argv) {
/* Was there an invalid path? */
if (pathspec) {
int num;
for (num = 0; pathspec[num]; num++)
; /* just counting */
if (argc != num)
exit(1); /* error message already given */
} else
exit(1); /* error message already given */
}
fill_directory(&dir, pathspec, ignored_too);
if (show_only) {

View File

@ -10,6 +10,7 @@
#include "cache.h"
#include "dir.h"
#include "parse-options.h"
#include "quote.h"
static int force = -1; /* unset */
@ -34,7 +35,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
struct dir_struct dir;
const char *path, *base;
static const char **pathspec;
int prefix_offset = 0;
struct strbuf buf;
const char *qname;
char *seen = NULL;
struct option options[] = {
OPT__QUIET(&quiet),
@ -56,6 +58,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, options, builtin_clean_usage, 0);
strbuf_init(&buf, 0);
memset(&dir, 0, sizeof(dir));
if (ignored_only)
dir.show_ignored = 1;
@ -72,8 +75,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (!ignored)
setup_standard_excludes(&dir);
if (prefix)
prefix_offset = strlen(prefix);
pathspec = get_pathspec(prefix, argv);
read_cache();
@ -134,39 +135,34 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (S_ISDIR(st.st_mode)) {
strbuf_addstr(&directory, ent->name);
qname = quote_path_relative(directory.buf, directory.len, &buf, prefix);
if (show_only && (remove_directories || matches)) {
printf("Would remove %s\n",
directory.buf + prefix_offset);
printf("Would remove %s\n", qname);
} else if (remove_directories || matches) {
if (!quiet)
printf("Removing %s\n",
directory.buf + prefix_offset);
printf("Removing %s\n", qname);
if (remove_dir_recursively(&directory, 0) != 0) {
warning("failed to remove '%s'",
directory.buf + prefix_offset);
warning("failed to remove '%s'", qname);
errors++;
}
} else if (show_only) {
printf("Would not remove %s\n",
directory.buf + prefix_offset);
printf("Would not remove %s\n", qname);
} else {
printf("Not removing %s\n",
directory.buf + prefix_offset);
printf("Not removing %s\n", qname);
}
strbuf_reset(&directory);
} else {
if (pathspec && !matches)
continue;
qname = quote_path_relative(ent->name, -1, &buf, prefix);
if (show_only) {
printf("Would remove %s\n",
ent->name + prefix_offset);
printf("Would remove %s\n", qname);
continue;
} else if (!quiet) {
printf("Removing %s\n",
ent->name + prefix_offset);
printf("Removing %s\n", qname);
}
if (unlink(ent->name) != 0) {
warning("failed to remove '%s'", ent->name);
warning("failed to remove '%s'", qname);
errors++;
}
}

View File

@ -574,17 +574,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
pathspec = get_pathspec(prefix, argv + i);
/* Verify that the pathspec matches the prefix */
if (pathspec) {
if (argc != i) {
int cnt;
for (cnt = 0; pathspec[cnt]; cnt++)
;
if (cnt != (argc - i))
exit(1); /* error message already given */
}
if (pathspec)
prefix = verify_pathspec(prefix);
} else if (argc != i)
exit(1); /* error message already given */
/* Treat unmatching pathspec elements as errors */
if (pathspec && error_unmatch) {

View File

@ -19,7 +19,6 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
int count, int base_name)
{
int i;
int len = prefix ? strlen(prefix) : 0;
const char **result = xmalloc((count + 1) * sizeof(const char *));
memcpy(result, pathspec, count * sizeof(const char *));
result[count] = NULL;
@ -33,11 +32,8 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
if (last_slash)
result[i] = last_slash + 1;
}
result[i] = prefix_path(prefix, len, result[i]);
if (!result[i])
exit(1); /* error already given */
}
return result;
return get_pathspec(prefix, result);
}
static void show_list(const char *label, struct path_list *list)

42
quote.c
View File

@ -260,6 +260,48 @@ extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
fputc(terminator, fp);
}
/* quote path as relative to the given prefix */
char *quote_path_relative(const char *in, int len,
struct strbuf *out, const char *prefix)
{
int needquote;
if (len < 0)
len = strlen(in);
/* "../" prefix itself does not need quoting, but "in" might. */
needquote = next_quote_pos(in, len) < len;
strbuf_setlen(out, 0);
strbuf_grow(out, len);
if (needquote)
strbuf_addch(out, '"');
if (prefix) {
int off = 0;
while (prefix[off] && off < len && prefix[off] == in[off])
if (prefix[off] == '/') {
prefix += off + 1;
in += off + 1;
len -= off + 1;
off = 0;
} else
off++;
for (; *prefix; prefix++)
if (*prefix == '/')
strbuf_addstr(out, "../");
}
quote_c_style_counted (in, len, out, NULL, 1);
if (needquote)
strbuf_addch(out, '"');
if (!out->len)
strbuf_addstr(out, "./");
return out->buf;
}
/*
* C-style name unquoting.
*

View File

@ -47,6 +47,10 @@ 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);
/* quote path as relative to the given prefix */
char *quote_path_relative(const char *in, int len,
struct strbuf *out, const char *prefix);
/* quoting as a string literal for other languages */
extern void perl_quote_print(FILE *stream, const char *src);
extern void python_quote_print(FILE *stream, const char *src);

View File

@ -202,6 +202,8 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
const char *p = prefix_path(prefix, prefixlen, *src);
if (p)
*(dst++) = p;
else
exit(128); /* error message already given */
src++;
}
*dst = NULL;

View File

@ -120,7 +120,7 @@ EOF
# having 1.txt and path3
test_expect_success \
'ls-tree filter odd names' \
'git ls-tree $tree 1.txt /1.txt //1.txt path3/1.txt /path3/1.txt //path3//1.txt path3 /path3/ path3// >current &&
'git ls-tree $tree 1.txt ./1.txt .//1.txt path3/1.txt path3/./1.txt path3 path3// >current &&
cat >expected <<\EOF &&
100644 blob X 1.txt
100644 blob X path3/1.txt

View File

@ -142,15 +142,16 @@ test_expect_success 'setup deeper work tree' '
test_expect_success 'add a directory outside the work tree' '(
cd tester &&
d1="$(cd .. ; pwd)" &&
git add "$d1"
test_must_fail git add "$d1"
)'
test_expect_success 'add a file outside the work tree, nasty case 1' '(
cd tester &&
f="$(pwd)x" &&
echo "$f" &&
touch "$f" &&
git add "$f"
test_must_fail git add "$f"
)'
test_expect_success 'add a file outside the work tree, nasty case 2' '(
@ -158,7 +159,7 @@ test_expect_success 'add a file outside the work tree, nasty case 2' '(
f="$(pwd | sed "s/.$//")x" &&
echo "$f" &&
touch "$f" &&
git add "$f"
test_must_fail git add "$f"
)'
test_done

View File

@ -89,6 +89,58 @@ test_expect_success 'git-clean with prefix' '
test -f build/lib.so
'
test_expect_success 'git-clean with relative prefix' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
would_clean=$(
cd docs &&
git clean -n ../src |
sed -n -e "s|^Would remove ||p"
) &&
test "$would_clean" = ../src/part3.c || {
echo "OOps <$would_clean>"
false
}
'
test_expect_success 'git-clean with absolute path' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
would_clean=$(
cd docs &&
git clean -n $(pwd)/../src |
sed -n -e "s|^Would remove ||p"
) &&
test "$would_clean" = ../src/part3.c || {
echo "OOps <$would_clean>"
false
}
'
test_expect_success 'git-clean with out of work tree relative path' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
(
cd docs &&
test_must_fail git clean -n ../..
)
'
test_expect_success 'git-clean with out of work tree absolute path' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
dd=$(cd .. && pwd) &&
(
cd docs &&
test_must_fail git clean -n $dd
)
'
test_expect_success 'git-clean -d with prefix and path' '
mkdir -p build docs src/feature &&

View File

@ -7,6 +7,7 @@
#include "diff.h"
#include "revision.h"
#include "diffcore.h"
#include "quote.h"
int wt_status_relative_paths = 1;
int wt_status_use_color = -1;
@ -82,51 +83,7 @@ static void wt_status_print_trailer(struct wt_status *s)
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
}
static char *quote_path(const char *in, int len,
struct strbuf *out, const char *prefix)
{
if (len < 0)
len = strlen(in);
strbuf_grow(out, len);
strbuf_setlen(out, 0);
if (prefix) {
int off = 0;
while (prefix[off] && off < len && prefix[off] == in[off])
if (prefix[off] == '/') {
prefix += off + 1;
in += off + 1;
len -= off + 1;
off = 0;
} else
off++;
for (; *prefix; prefix++)
if (*prefix == '/')
strbuf_addstr(out, "../");
}
for ( ; len > 0; in++, len--) {
int ch = *in;
switch (ch) {
case '\n':
strbuf_addstr(out, "\\n");
break;
case '\r':
strbuf_addstr(out, "\\r");
break;
default:
strbuf_addch(out, ch);
continue;
}
}
if (!out->len)
strbuf_addstr(out, "./");
return out->buf;
}
#define quote_path quote_path_relative
static void wt_status_print_filepair(struct wt_status *s,
int t, struct diff_filepair *p)