git status: show relative paths when run in a subdirectory

To show the relative paths, the function formerly called quote_crlf()
(now called quote_path()) takes the prefix as an additional argument.

While at it, the static buffers were replaced by strbufs.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johannes Schindelin 2007-11-11 17:35:41 +00:00 committed by Junio C Hamano
parent d37d320386
commit 367c98866c
5 changed files with 146 additions and 29 deletions

View File

@ -118,11 +118,12 @@ static char *prepare_index(const char **files, const char *prefix)
return next_index_lock->filename; return next_index_lock->filename;
} }
static int run_status(FILE *fp, const char *index_file) static int run_status(FILE *fp, const char *index_file, const char *prefix)
{ {
struct wt_status s; struct wt_status s;
wt_status_prepare(&s); wt_status_prepare(&s);
s.prefix = prefix;
if (amend) { if (amend) {
s.amend = 1; s.amend = 1;
@ -140,7 +141,7 @@ static int run_status(FILE *fp, const char *index_file)
static const char sign_off_header[] = "Signed-off-by: "; static const char sign_off_header[] = "Signed-off-by: ";
static int prepare_log_message(const char *index_file) static int prepare_log_message(const char *index_file, const char *prefix)
{ {
struct stat statbuf; struct stat statbuf;
int commitable; int commitable;
@ -216,7 +217,7 @@ static int prepare_log_message(const char *index_file)
if (only_include_assumed) if (only_include_assumed)
fprintf(fp, "# %s\n", only_include_assumed); fprintf(fp, "# %s\n", only_include_assumed);
commitable = run_status(fp, index_file); commitable = run_status(fp, index_file, prefix);
fclose(fp); fclose(fp);
@ -409,7 +410,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
index_file = prepare_index(argv, prefix); index_file = prepare_index(argv, prefix);
commitable = run_status(stdout, index_file); commitable = run_status(stdout, index_file, prefix);
rollback_lock_file(&lock_file); rollback_lock_file(&lock_file);
@ -503,8 +504,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
if (!no_verify && run_hook(index_file, "pre-commit", NULL)) if (!no_verify && run_hook(index_file, "pre-commit", NULL))
exit(1); exit(1);
if (!prepare_log_message(index_file) && !in_merge) { if (!prepare_log_message(index_file, prefix) && !in_merge) {
run_status(stdout, index_file); run_status(stdout, index_file, prefix);
unlink(commit_editmsg); unlink(commit_editmsg);
return 1; return 1;
} }

View File

@ -14,6 +14,7 @@ int cmd_runstatus(int argc, const char **argv, const char *prefix)
git_config(git_status_config); git_config(git_status_config);
wt_status_prepare(&s); wt_status_prepare(&s);
s.prefix = prefix;
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--color")) if (!strcmp(argv[i], "--color"))

91
t/t7502-status.sh Executable file
View File

@ -0,0 +1,91 @@
#!/bin/sh
#
# Copyright (c) 2007 Johannes E. Schindelin
#
test_description='git-status'
. ./test-lib.sh
test_expect_success 'setup' '
: > tracked &&
: > modified &&
mkdir dir1 &&
: > dir1/tracked &&
: > dir1/modified &&
mkdir dir2 &&
: > dir1/tracked &&
: > dir1/modified &&
git add . &&
test_tick &&
git commit -m initial &&
: > untracked &&
: > dir1/untracked &&
: > dir2/untracked &&
echo 1 > dir1/modified &&
echo 2 > dir2/modified &&
echo 3 > dir2/added &&
git add dir2/added
'
cat > expect << \EOF
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: dir2/added
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: dir1/modified
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# dir1/untracked
# dir2/modified
# dir2/untracked
# expect
# output
# untracked
EOF
test_expect_success 'status' '
git status > output &&
git diff expect output
'
cat > expect << \EOF
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: ../dir2/added
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: ../dir1/modified
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# untracked
# ../dir2/modified
# ../dir2/untracked
# ../expect
# ../output
# ../untracked
EOF
test_expect_success 'status with relative paths' '
(cd dir1 && git status) > output &&
git diff expect output
'
test_done

View File

@ -81,33 +81,46 @@ static void wt_status_print_trailer(struct wt_status *s)
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#"); color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
} }
static const char *quote_crlf(const char *in, char *buf, size_t sz) static char *quote_path(const char *in, int len,
struct strbuf *out, const char *prefix)
{ {
const char *scan; if (len > 0)
char *out; strbuf_grow(out, len);
const char *ret = in; strbuf_setlen(out, 0);
for (scan = in, out = buf; *scan; scan++) { if (prefix) {
int ch = *scan; int off = 0;
int quoted; 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 > 0; in++, len--) {
int ch = *in;
switch (ch) { switch (ch) {
case '\n': case '\n':
quoted = 'n'; strbuf_addstr(out, "\\n");
break; break;
case '\r': case '\r':
quoted = 'r'; strbuf_addstr(out, "\\r");
break; break;
default: default:
*out++ = ch; strbuf_addch(out, ch);
continue; continue;
} }
*out++ = '\\';
*out++ = quoted;
ret = buf;
} }
*out = '\0';
return ret; return out->buf;
} }
static void wt_status_print_filepair(struct wt_status *s, static void wt_status_print_filepair(struct wt_status *s,
@ -115,10 +128,12 @@ static void wt_status_print_filepair(struct wt_status *s,
{ {
const char *c = color(t); const char *c = color(t);
const char *one, *two; const char *one, *two;
char onebuf[PATH_MAX], twobuf[PATH_MAX]; struct strbuf onebuf, twobuf;
one = quote_crlf(p->one->path, onebuf, sizeof(onebuf)); strbuf_init(&onebuf, 0);
two = quote_crlf(p->two->path, twobuf, sizeof(twobuf)); strbuf_init(&twobuf, 0);
one = quote_path(p->one->path, -1, &onebuf, s->prefix);
two = quote_path(p->two->path, -1, &twobuf, s->prefix);
color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t"); color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t");
switch (p->status) { switch (p->status) {
@ -150,6 +165,8 @@ static void wt_status_print_filepair(struct wt_status *s,
die("bug: unhandled diff status %c", p->status); die("bug: unhandled diff status %c", p->status);
} }
fprintf(s->fp, "\n"); fprintf(s->fp, "\n");
strbuf_release(&onebuf);
strbuf_release(&twobuf);
} }
static void wt_status_print_updated_cb(struct diff_queue_struct *q, static void wt_status_print_updated_cb(struct diff_queue_struct *q,
@ -204,8 +221,9 @@ static void wt_read_cache(struct wt_status *s)
static void wt_status_print_initial(struct wt_status *s) static void wt_status_print_initial(struct wt_status *s)
{ {
int i; int i;
char buf[PATH_MAX]; struct strbuf buf;
strbuf_init(&buf, 0);
wt_read_cache(s); wt_read_cache(s);
if (active_nr) { if (active_nr) {
s->commitable = 1; s->commitable = 1;
@ -214,11 +232,12 @@ static void wt_status_print_initial(struct wt_status *s)
for (i = 0; i < active_nr; i++) { for (i = 0; i < active_nr; i++) {
color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t"); color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t");
color_fprintf_ln(s->fp, color(WT_STATUS_UPDATED), "new file: %s", color_fprintf_ln(s->fp, color(WT_STATUS_UPDATED), "new file: %s",
quote_crlf(active_cache[i]->name, quote_path(active_cache[i]->name, -1,
buf, sizeof(buf))); &buf, s->prefix));
} }
if (active_nr) if (active_nr)
wt_status_print_trailer(s); wt_status_print_trailer(s);
strbuf_release(&buf);
} }
static void wt_status_print_updated(struct wt_status *s) static void wt_status_print_updated(struct wt_status *s)
@ -252,7 +271,9 @@ static void wt_status_print_untracked(struct wt_status *s)
struct dir_struct dir; struct dir_struct dir;
int i; int i;
int shown_header = 0; int shown_header = 0;
struct strbuf buf;
strbuf_init(&buf, 0);
memset(&dir, 0, sizeof(dir)); memset(&dir, 0, sizeof(dir));
if (!s->untracked) { if (!s->untracked) {
@ -284,9 +305,11 @@ static void wt_status_print_untracked(struct wt_status *s)
shown_header = 1; shown_header = 1;
} }
color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t"); color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t");
color_fprintf_ln(s->fp, color(WT_STATUS_UNTRACKED), "%.*s", color_fprintf_ln(s->fp, color(WT_STATUS_UNTRACKED), "%s",
ent->len, ent->name); quote_path(ent->name, ent->len,
&buf, s->prefix));
} }
strbuf_release(&buf);
} }
static void wt_status_print_verbose(struct wt_status *s) static void wt_status_print_verbose(struct wt_status *s)

View File

@ -23,6 +23,7 @@ struct wt_status {
int workdir_untracked; int workdir_untracked;
const char *index_file; const char *index_file;
FILE *fp; FILE *fp;
const char *prefix;
}; };
int git_status_config(const char *var, const char *value); int git_status_config(const char *var, const char *value);