git status: show relative paths when run in a subdirectory
authorJohannes Schindelin <Johannes.Schindelin@gmx.de>
Sun, 11 Nov 2007 17:35:41 +0000 (17:35 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 23 Nov 2007 01:05:03 +0000 (17:05 -0800)
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>
builtin-commit.c
builtin-runstatus.c
t/t7502-status.sh [new file with mode: 0755]
wt-status.c
wt-status.h

index a84a729da1fddc83e3ced1c2b5b9156ce52294e0..400ee93a936342ad379b110b41bab1334f65eb85 100644 (file)
@@ -118,11 +118,12 @@ static char *prepare_index(const char **files, const char *prefix)
        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;
 
        wt_status_prepare(&s);
+       s.prefix = prefix;
 
        if (amend) {
                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 int prepare_log_message(const char *index_file)
+static int prepare_log_message(const char *index_file, const char *prefix)
 {
        struct stat statbuf;
        int commitable;
@@ -216,7 +217,7 @@ static int prepare_log_message(const char *index_file)
        if (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);
 
@@ -409,7 +410,7 @@ int cmd_status(int argc, const char **argv, const char *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);
 
@@ -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))
                exit(1);
 
-       if (!prepare_log_message(index_file) && !in_merge) {
-               run_status(stdout, index_file);
+       if (!prepare_log_message(index_file, prefix) && !in_merge) {
+               run_status(stdout, index_file, prefix);
                unlink(commit_editmsg);
                return 1;
        }
index 2db25c88bf648e4d5f2f41502fd29c5f7324e56b..8d167a9674e70a36662528c98165bd3be8a9f431 100644 (file)
@@ -14,6 +14,7 @@ int cmd_runstatus(int argc, const char **argv, const char *prefix)
 
        git_config(git_status_config);
        wt_status_prepare(&s);
+       s.prefix = prefix;
 
        for (i = 1; i < argc; i++) {
                if (!strcmp(argv[i], "--color"))
diff --git a/t/t7502-status.sh b/t/t7502-status.sh
new file mode 100755 (executable)
index 0000000..269b334
--- /dev/null
@@ -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
index 9a6ef4a89ae659855ae0d2fa3006daf080190ed4..d3c10b8b8d2fcb0421cde0589e2eb96e8f534c87 100644 (file)
@@ -81,33 +81,46 @@ static void wt_status_print_trailer(struct wt_status *s)
        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;
-       char *out;
-       const char *ret = in;
+       if (len > 0)
+               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 (scan = in, out = buf; *scan; scan++) {
-               int ch = *scan;
-               int quoted;
+       for (; (len < 0 && *in) || len > 0; in++, len--) {
+               int ch = *in;
 
                switch (ch) {
                case '\n':
-                       quoted = 'n';
+                       strbuf_addstr(out, "\\n");
                        break;
                case '\r':
-                       quoted = 'r';
+                       strbuf_addstr(out, "\\r");
                        break;
                default:
-                       *out++ = ch;
+                       strbuf_addch(out, ch);
                        continue;
                }
-               *out++ = '\\';
-               *out++ = quoted;
-               ret = buf;
        }
-       *out = '\0';
-       return ret;
+
+       return out->buf;
 }
 
 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 *one, *two;
-       char onebuf[PATH_MAX], twobuf[PATH_MAX];
+       struct strbuf onebuf, twobuf;
 
-       one = quote_crlf(p->one->path, onebuf, sizeof(onebuf));
-       two = quote_crlf(p->two->path, twobuf, sizeof(twobuf));
+       strbuf_init(&onebuf, 0);
+       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");
        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);
        }
        fprintf(s->fp, "\n");
+       strbuf_release(&onebuf);
+       strbuf_release(&twobuf);
 }
 
 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)
 {
        int i;
-       char buf[PATH_MAX];
+       struct strbuf buf;
 
+       strbuf_init(&buf, 0);
        wt_read_cache(s);
        if (active_nr) {
                s->commitable = 1;
@@ -214,11 +232,12 @@ static void wt_status_print_initial(struct wt_status *s)
        for (i = 0; i < active_nr; i++) {
                color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t");
                color_fprintf_ln(s->fp, color(WT_STATUS_UPDATED), "new file: %s",
-                               quote_crlf(active_cache[i]->name,
-                                          buf, sizeof(buf)));
+                               quote_path(active_cache[i]->name, -1,
+                                          &buf, s->prefix));
        }
        if (active_nr)
                wt_status_print_trailer(s);
+       strbuf_release(&buf);
 }
 
 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;
        int i;
        int shown_header = 0;
+       struct strbuf buf;
 
+       strbuf_init(&buf, 0);
        memset(&dir, 0, sizeof(dir));
 
        if (!s->untracked) {
@@ -284,9 +305,11 @@ static void wt_status_print_untracked(struct wt_status *s)
                        shown_header = 1;
                }
                color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t");
-               color_fprintf_ln(s->fp, color(WT_STATUS_UNTRACKED), "%.*s",
-                               ent->len, ent->name);
+               color_fprintf_ln(s->fp, color(WT_STATUS_UNTRACKED), "%s",
+                               quote_path(ent->name, ent->len,
+                                       &buf, s->prefix));
        }
+       strbuf_release(&buf);
 }
 
 static void wt_status_print_verbose(struct wt_status *s)
index 77449326dbec5c3f83559c300aec2922445829ef..f58ebcbb23f214c1fea8f4cb8e10c3491b8e0469 100644 (file)
@@ -23,6 +23,7 @@ struct wt_status {
        int workdir_untracked;
        const char *index_file;
        FILE *fp;
+       const char *prefix;
 };
 
 int git_status_config(const char *var, const char *value);