git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC/PATCH] shortstatus v0
@ 2009-02-04 22:05 Tuncer Ayaz
  2009-02-04 22:17 ` Tuncer Ayaz
  0 siblings, 1 reply; 2+ messages in thread
From: Tuncer Ayaz @ 2009-02-04 22:05 UTC (permalink / raw)
  To: git; +Cc: gitster

As discussed recently I started taking Junio's shortstatus patch
from October 25th 2008 and integrated it into current master.

The following patch revision does work but does not print the
'M ' prefixes yet due to either a patching error on my side or
missing code in the forward port of the patch. I still have
to analyze that.

What this patch still needs to implement is something like
'shortstatus --mini' which prints:
   anything modified          -> *
   anything added             -> +
   anything untracked/unknown -> ?

So if you have a repo where one file is modified,
a new file is added and an unknown file exists and
is not ignored 'shortstatus --mini' shall print:
+*?.

This is really useful for enhancing a Git enabled
shell prompt with small but important information.

Right now this is basically Junio's shortstatus
from Oct 25th 2008 with no substantial change
except a line or two.


Signed-off-by: Tuncer Ayaz <tuncer.ayaz@gmail.com>
---

  .gitignore       |    1 +
  Makefile         |    1 +
  builtin-commit.c |   45 +++++++++++-
  builtin-revert.c |    1 +
  builtin.h        |    1 +
  git.c            |    1 +
  wt-status.c      |  213 ++++++++++++++++++++++++++++++++++++++++++ 
+-----------
  wt-status.h      |    9 +++
  8 files changed, 227 insertions(+), 45 deletions(-)

diff --git a/.gitignore b/.gitignore
index 1c57d4c..5666325 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,6 +114,7 @@ git-send-pack
  git-sh-setup
  git-shell
  git-shortlog
+git-shortstatus
  git-show
  git-show-branch
  git-show-index
diff --git a/Makefile b/Makefile
index 9f3a8ab..304f15d 100644
--- a/Makefile
+++ b/Makefile
@@ -329,6 +329,7 @@ BUILT_INS += git-repo-config$X
  BUILT_INS += git-show$X
  BUILT_INS += git-stage$X
  BUILT_INS += git-status$X
+BUILT_INS += git-shortstatus$X
  BUILT_INS += git-whatchanged$X

  # what 'all' will build and 'install' will install, in gitexecdir
diff --git a/builtin-commit.c b/builtin-commit.c
index d6a3a62..624568c 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -14,6 +14,7 @@
  #include "diffcore.h"
  #include "commit.h"
  #include "revision.h"
+#include "string-list.h"
  #include "wt-status.h"
  #include "run-command.h"
  #include "refs.h"
@@ -21,7 +22,6 @@
  #include "strbuf.h"
  #include "utf8.h"
  #include "parse-options.h"
-#include "string-list.h"
  #include "rerere.h"
  #include "unpack-trees.h"

@@ -821,6 +821,49 @@ static int parse_and_validate_options(int argc,  
const char *argv[],
  	return argc;
  }

+int cmd_shortstatus(int argc, const char **argv, const char *prefix)
+{
+	struct wt_status s;
+	int i;
+
+	read_cache();
+	refresh_cache(REFRESH_QUIET);
+	wt_status_prepare(&s);
+	wt_status_collect_changes(&s);
+	for (i = 0; i < s.change.nr; i++) {
+		struct wt_status_change_data *d;
+		struct string_list_item *it;
+		char pfx[1 + 3 + 1 + 1];
+
+		it = &(s.change.items[i]);
+		d = it->util;
+		switch (d->index_status) {
+			case DIFF_STATUS_COPIED:
+			case DIFF_STATUS_RENAMED:
+				sprintf(pfx, "%c%3d",
+						d->index_status,
+						(int)(d->index_score * 100 / MAX_SCORE));
+				break;
+			case 0:
+				memcpy(pfx, "	", 4);
+				break;
+			default:
+				sprintf(pfx, "%c	  ", d->index_status);
+				break;
+		}
+		if (!d->worktree_status)
+			pfx[4] = ' ';
+		else
+			pfx[4] = d->worktree_status;
+		pfx[5] = '\0';
+		printf("%s ", pfx);
+		if (d->head_path)
+			printf("%s -> ", d->head_path);
+		printf("%s\n", it->string);
+	}
+	return 0;
+}
+
  int cmd_status(int argc, const char **argv, const char *prefix)
  {
  	const char *index_file;
diff --git a/builtin-revert.c b/builtin-revert.c
index d48313c..7dd7646 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -3,6 +3,7 @@
  #include "object.h"
  #include "commit.h"
  #include "tag.h"
+#include "string-list.h"
  #include "wt-status.h"
  #include "run-command.h"
  #include "exec_cmd.h"
diff --git a/builtin.h b/builtin.h
index 1495cf6..f054fc7 100644
--- a/builtin.h
+++ b/builtin.h
@@ -94,6 +94,7 @@ extern int cmd_shortlog(int argc, const char **argv,  
const char *prefix);
  extern int cmd_show(int argc, const char **argv, const char *prefix);
  extern int cmd_show_branch(int argc, const char **argv, const char  
*prefix);
  extern int cmd_status(int argc, const char **argv, const char  
*prefix);
+extern int cmd_shortstatus(int argc, const char **argv, const char  
*prefix);
  extern int cmd_stripspace(int argc, const char **argv, const char  
*prefix);
  extern int cmd_symbolic_ref(int argc, const char **argv, const char  
*prefix);
  extern int cmd_tag(int argc, const char **argv, const char *prefix);
diff --git a/git.c b/git.c
index c2b181e..4c0fa44 100644
--- a/git.c
+++ b/git.c
@@ -344,6 +344,7 @@ static void handle_internal_command(int argc,  
const char **argv)
  		{ "rm", cmd_rm, RUN_SETUP },
  		{ "send-pack", cmd_send_pack, RUN_SETUP },
  		{ "shortlog", cmd_shortlog, USE_PAGER },
+		{ "shortstatus", cmd_shortstatus, RUN_SETUP | NEED_WORK_TREE },
  		{ "show-branch", cmd_show_branch, RUN_SETUP },
  		{ "show", cmd_show, RUN_SETUP | USE_PAGER },
  		{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
diff --git a/wt-status.c b/wt-status.c
index 96ff2f8..18042dc 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1,4 +1,5 @@
  #include "cache.h"
+#include "string-list.h"
  #include "wt-status.h"
  #include "color.h"
  #include "object.h"
@@ -56,6 +57,7 @@ void wt_status_prepare(struct wt_status *s)
  	s->reference = "HEAD";
  	s->fp = stdout;
  	s->index_file = get_index_file();
+	s->change.strdup_strings = 1;
  }

  static void wt_status_print_cached_header(struct wt_status *s)
@@ -98,18 +100,23 @@ static void wt_status_print_trailer(struct  
wt_status *s)

  #define quote_path quote_path_relative

-static void wt_status_print_filepair(struct wt_status *s,
-				     int t, struct diff_filepair *p)
+static void wt_status_print_change_data(struct wt_status *s,
+						int t,
+						int status,
+						char *one_name,
+						char *two_name,
+						int score)
  {
  	const char *c = color(t);
  	const char *one, *two;
  	struct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT;

-	one = quote_path(p->one->path, -1, &onebuf, s->prefix);
-	two = quote_path(p->two->path, -1, &twobuf, s->prefix);
+	one = quote_path(one_name, -1, &onebuf, s->prefix);
+	two = quote_path(two_name, -1, &twobuf, s->prefix);
+

  	color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t");
-	switch (p->status) {
+	switch (status) {
  	case DIFF_STATUS_ADDED:
  		color_fprintf(s->fp, c, "new file:   %s", one);
  		break;
@@ -135,64 +142,88 @@ static void wt_status_print_filepair(struct  
wt_status *s,
  		color_fprintf(s->fp, c, "unmerged:   %s", one);
  		break;
  	default:
-		die("bug: unhandled diff status %c", p->status);
+		die("bug: unhandled diff status %c", status);
  	}
  	fprintf(s->fp, "\n");
  	strbuf_release(&onebuf);
  	strbuf_release(&twobuf);
  }

-static void wt_status_print_updated_cb(struct diff_queue_struct *q,
-		struct diff_options *options,
-		void *data)
+static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
+							struct diff_options *options,
+							void *data)
  {
  	struct wt_status *s = data;
-	int shown_header = 0;
  	int i;
+
+	if (!q->nr)
+		return;
+	s->workdir_dirty = 1;
  	for (i = 0; i < q->nr; i++) {
-		if (q->queue[i]->status == 'U')
-			continue;
-		if (!shown_header) {
-			wt_status_print_cached_header(s);
-			s->commitable = 1;
-			shown_header = 1;
-		}
-		wt_status_print_filepair(s, WT_STATUS_UPDATED, q->queue[i]);
+		struct diff_filepair *p;
+		struct string_list_item *it;
+		struct wt_status_change_data *d;
+
+		p = q->queue[i];
+
+		d = xcalloc(1, sizeof(*d));
+		d->worktree_status = p->status;
+		it = string_list_insert(p->one->path, &s->change);
+		it->util = d;
  	}
-	if (shown_header)
-		wt_status_print_trailer(s);
  }

-static void wt_status_print_changed_cb(struct diff_queue_struct *q,
-                        struct diff_options *options,
-                        void *data)
+static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
+							struct diff_options *options,
+							void *data)
  {
  	struct wt_status *s = data;
  	int i;
-	if (q->nr) {
-		int has_deleted = 0;
-		s->workdir_dirty = 1;
-		for (i = 0; i < q->nr; i++)
-			if (q->queue[i]->status == DIFF_STATUS_DELETED) {
-				has_deleted = 1;
+
+	for (i = 0; i < q->nr; i++) {
+		struct diff_filepair *p;
+		struct string_list_item *it;
+		struct wt_status_change_data *d;
+
+		p = q->queue[i];
+		it = string_list_insert(p->two->path, &s->change);
+		d = it->util;
+		if (!d) {
+			d = xcalloc(1, sizeof(*d));
+			it->util = d;
+		}
+		d->index_status = p->status;
+		switch (p->status) {
+			case DIFF_STATUS_COPIED:
+			case DIFF_STATUS_RENAMED:
+				d->head_path = xstrdup(p->one->path);
+				d->index_score = p->score;
  				break;
-			}
-		wt_status_print_dirty_header(s, has_deleted);
+		}
  	}
-	for (i = 0; i < q->nr; i++)
-		wt_status_print_filepair(s, WT_STATUS_CHANGED, q->queue[i]);
-	if (q->nr)
-		wt_status_print_trailer(s);
  }

-static void wt_status_print_updated(struct wt_status *s)
+static void wt_status_collect_changes_worktree(struct wt_status *s)
  {
  	struct rev_info rev;
+
+	init_revisions(&rev, NULL);
+	setup_revisions(0, NULL, &rev, NULL);
+	rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
+	rev.diffopt.format_callback = wt_status_collect_changed_cb;
+	rev.diffopt.format_callback_data = s;
+	run_diff_files(&rev, 0);
+}
+
+static void wt_status_collect_changes_index(struct wt_status *s)
+{
+	struct rev_info rev;
+
  	init_revisions(&rev, NULL);
  	setup_revisions(0, NULL, &rev,
  		s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference);
  	rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
-	rev.diffopt.format_callback = wt_status_print_updated_cb;
+	rev.diffopt.format_callback = wt_status_collect_updated_cb;
  	rev.diffopt.format_callback_data = s;
  	rev.diffopt.detect_rename = 1;
  	rev.diffopt.rename_limit = 200;
@@ -200,15 +231,107 @@ static void wt_status_print_updated(struct  
wt_status *s)
  	run_diff_index(&rev, 1);
  }

+static void wt_status_collect_changes_initial(struct wt_status *s)
+{
+	int i;
+
+	for (i = 0; i < active_nr; i++) {
+		struct string_list_item *it;
+		struct wt_status_change_data *d;
+
+		it = string_list_insert(active_cache[i]->name, &s->change);
+		d = it->util;
+		if (!d) {
+			d = xcalloc(1, sizeof(*d));
+			it->util = d;
+		}
+		d->index_status = DIFF_STATUS_ADDED;
+	}
+}
+
+void wt_status_collect_changes(struct wt_status *s)
+{
+	wt_status_collect_changes_worktree(s);
+
+	if (s->is_initial)
+		wt_status_collect_changes_initial(s);
+	else
+		wt_status_collect_changes_index(s);
+}
+
+static void wt_status_print_updated(struct wt_status *s)
+{
+	int shown_header = 0;
+	int i;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		struct string_list_item *it;
+		it = &(s->change.items[i]);
+		d = it->util;
+		if (!d->index_status)
+			continue;
+		if (!shown_header) {
+			wt_status_print_cached_header(s);
+			s->commitable = 1;
+			shown_header = 1;
+		}
+		wt_status_print_change_data(s, WT_STATUS_UPDATED,
+				d->index_status,
+				d->head_path ? d->head_path : it->string,
+				it->string,
+				d->index_score);
+	}
+	if (shown_header)
+		wt_status_print_trailer(s);
+}
+
+/*
+ * -1 : has delete
+ *  0 : no change
+ *  1 : some change but no delete
+ */
+static int wt_status_check_worktree_changes(struct wt_status *s)
+{
+	int i;
+	int changes = 0;
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		d = s->change.items[i].util;
+		if (!d->worktree_status)
+			continue;
+		changes = 1;
+		if (d->worktree_status == DIFF_STATUS_DELETED)
+			return -1;
+	}
+	return changes;
+}
+
  static void wt_status_print_changed(struct wt_status *s)
  {
-	struct rev_info rev;
-	init_revisions(&rev, "");
-	setup_revisions(0, NULL, &rev, NULL);
-	rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
-	rev.diffopt.format_callback = wt_status_print_changed_cb;
-	rev.diffopt.format_callback_data = s;
-	run_diff_files(&rev, 0);
+	int i;
+	int worktree_changes = wt_status_check_worktree_changes(s);
+
+	if (!worktree_changes)
+		return;
+
+	wt_status_print_dirty_header(s, worktree_changes < 0);
+
+	for (i = 0; i < s->change.nr; i++) {
+		struct wt_status_change_data *d;
+		struct string_list_item *it;
+		it = &(s->change.items[i]);
+		d = it->util;
+		if (!d->worktree_status)
+			continue;
+		wt_status_print_change_data(s, WT_STATUS_CHANGED,
+				d->worktree_status,
+				it->string,
+				it->string,
+				0);
+	}
+	wt_status_print_trailer(s);
  }

  static void wt_status_print_submodule_summary(struct wt_status *s)
@@ -338,6 +461,8 @@ void wt_status_print(struct wt_status *s)
  			wt_status_print_tracking(s);
  	}

+	wt_status_collect_changes(s);
+
  	if (s->is_initial) {
  		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
  		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "# Initial  
commit");
diff --git a/wt-status.h b/wt-status.h
index 78add09..00508c3 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -18,6 +18,13 @@ enum untracked_status_type {
  };
  extern enum untracked_status_type show_untracked_files;

+struct wt_status_change_data {
+	int worktree_status;
+	int index_status;
+	int index_score;
+	char *head_path;
+};
+
  struct wt_status {
  	int is_initial;
  	char *branch;
@@ -33,6 +40,7 @@ struct wt_status {
  	const char *index_file;
  	FILE *fp;
  	const char *prefix;
+	struct string_list change;
  };

  int git_status_config(const char *var, const char *value, void *cb);
@@ -40,5 +48,6 @@ extern int wt_status_use_color;
  extern int wt_status_relative_paths;
  void wt_status_prepare(struct wt_status *s);
  void wt_status_print(struct wt_status *s);
+void wt_status_collect_changes(struct wt_status *s);

  #endif /* STATUS_H */

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [RFC/PATCH] shortstatus v0
  2009-02-04 22:05 [RFC/PATCH] shortstatus v0 Tuncer Ayaz
@ 2009-02-04 22:17 ` Tuncer Ayaz
  0 siblings, 0 replies; 2+ messages in thread
From: Tuncer Ayaz @ 2009-02-04 22:17 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

On Wed, Feb 4, 2009 at 11:05 PM, Tuncer Ayaz <tuncer.ayaz@gmail.com> wrote:
>

Linebreaks got garbled.
I had problems with Perl on this particular machine and didn't
use send-email. It looks like that was a bad decision :).
I believe it's still readable and as it's just an RFC this
shouldn't pose a difficulty for review.
Next revisions will return to using a working git-send-email
instead of a MUA with interesting automagics.

> As discussed recently I started taking Junio's shortstatus patch
> from October 25th 2008 and integrated it into current master.
>
> The following patch revision does work but does not print the
> 'M ' prefixes yet due to either a patching error on my side or
> missing code in the forward port of the patch. I still have
> to analyze that.
>
> What this patch still needs to implement is something like
> 'shortstatus --mini' which prints:
>  anything modified          -> *
>  anything added             -> +
>  anything untracked/unknown -> ?
>
> So if you have a repo where one file is modified,
> a new file is added and an unknown file exists and
> is not ignored 'shortstatus --mini' shall print:
> +*?.
>
> This is really useful for enhancing a Git enabled
> shell prompt with small but important information.
>
> Right now this is basically Junio's shortstatus
> from Oct 25th 2008 with no substantial change
> except a line or two.
>
>
> Signed-off-by: Tuncer Ayaz <tuncer.ayaz@gmail.com>
> ---
>
>  .gitignore       |    1 +
>  Makefile         |    1 +
>  builtin-commit.c |   45 +++++++++++-
>  builtin-revert.c |    1 +
>  builtin.h        |    1 +
>  git.c            |    1 +
>  wt-status.c      |  213 +++++++++++++++++++++++++++++++++++++++++++-----------
>  wt-status.h      |    9 +++
>  8 files changed, 227 insertions(+), 45 deletions(-)
>
> diff --git a/.gitignore b/.gitignore
> index 1c57d4c..5666325 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -114,6 +114,7 @@ git-send-pack
>  git-sh-setup
>  git-shell
>  git-shortlog
> +git-shortstatus
>  git-show
>  git-show-branch
>  git-show-index
> diff --git a/Makefile b/Makefile
> index 9f3a8ab..304f15d 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -329,6 +329,7 @@ BUILT_INS += git-repo-config$X
>  BUILT_INS += git-show$X
>  BUILT_INS += git-stage$X
>  BUILT_INS += git-status$X
> +BUILT_INS += git-shortstatus$X
>  BUILT_INS += git-whatchanged$X
>
>  # what 'all' will build and 'install' will install, in gitexecdir
> diff --git a/builtin-commit.c b/builtin-commit.c
> index d6a3a62..624568c 100644
> --- a/builtin-commit.c
> +++ b/builtin-commit.c
> @@ -14,6 +14,7 @@
>  #include "diffcore.h"
>  #include "commit.h"
>  #include "revision.h"
> +#include "string-list.h"
>  #include "wt-status.h"
>  #include "run-command.h"
>  #include "refs.h"
> @@ -21,7 +22,6 @@
>  #include "strbuf.h"
>  #include "utf8.h"
>  #include "parse-options.h"
> -#include "string-list.h"
>  #include "rerere.h"
>  #include "unpack-trees.h"
>
> @@ -821,6 +821,49 @@ static int parse_and_validate_options(int argc, const char *argv[],
>        return argc;
>  }
>
> +int cmd_shortstatus(int argc, const char **argv, const char *prefix)
> +{
> +       struct wt_status s;
> +       int i;
> +
> +       read_cache();
> +       refresh_cache(REFRESH_QUIET);
> +       wt_status_prepare(&s);
> +       wt_status_collect_changes(&s);
> +       for (i = 0; i < s.change.nr; i++) {
> +               struct wt_status_change_data *d;
> +               struct string_list_item *it;
> +               char pfx[1 + 3 + 1 + 1];
> +
> +               it = &(s.change.items[i]);
> +               d = it->util;
> +               switch (d->index_status) {
> +                       case DIFF_STATUS_COPIED:
> +                       case DIFF_STATUS_RENAMED:
> +                               sprintf(pfx, "%c%3d",
> +                                               d->index_status,
> +                                               (int)(d->index_score * 100 / MAX_SCORE));
> +                               break;
> +                       case 0:
> +                               memcpy(pfx, "   ", 4);
> +                               break;
> +                       default:
> +                               sprintf(pfx, "%c          ", d->index_status);
> +                               break;
> +               }
> +               if (!d->worktree_status)
> +                       pfx[4] = ' ';
> +               else
> +                       pfx[4] = d->worktree_status;
> +               pfx[5] = '\0';
> +               printf("%s ", pfx);
> +               if (d->head_path)
> +                       printf("%s -> ", d->head_path);
> +               printf("%s\n", it->string);
> +       }
> +       return 0;
> +}
> +
>  int cmd_status(int argc, const char **argv, const char *prefix)
>  {
>        const char *index_file;
> diff --git a/builtin-revert.c b/builtin-revert.c
> index d48313c..7dd7646 100644
> --- a/builtin-revert.c
> +++ b/builtin-revert.c
> @@ -3,6 +3,7 @@
>  #include "object.h"
>  #include "commit.h"
>  #include "tag.h"
> +#include "string-list.h"
>  #include "wt-status.h"
>  #include "run-command.h"
>  #include "exec_cmd.h"
> diff --git a/builtin.h b/builtin.h
> index 1495cf6..f054fc7 100644
> --- a/builtin.h
> +++ b/builtin.h
> @@ -94,6 +94,7 @@ extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
>  extern int cmd_show(int argc, const char **argv, const char *prefix);
>  extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
>  extern int cmd_status(int argc, const char **argv, const char *prefix);
> +extern int cmd_shortstatus(int argc, const char **argv, const char *prefix);
>  extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
>  extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
>  extern int cmd_tag(int argc, const char **argv, const char *prefix);
> diff --git a/git.c b/git.c
> index c2b181e..4c0fa44 100644
> --- a/git.c
> +++ b/git.c
> @@ -344,6 +344,7 @@ static void handle_internal_command(int argc, const char **argv)
>                { "rm", cmd_rm, RUN_SETUP },
>                { "send-pack", cmd_send_pack, RUN_SETUP },
>                { "shortlog", cmd_shortlog, USE_PAGER },
> +               { "shortstatus", cmd_shortstatus, RUN_SETUP | NEED_WORK_TREE },
>                { "show-branch", cmd_show_branch, RUN_SETUP },
>                { "show", cmd_show, RUN_SETUP | USE_PAGER },
>                { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
> diff --git a/wt-status.c b/wt-status.c
> index 96ff2f8..18042dc 100644
> --- a/wt-status.c
> +++ b/wt-status.c
> @@ -1,4 +1,5 @@
>  #include "cache.h"
> +#include "string-list.h"
>  #include "wt-status.h"
>  #include "color.h"
>  #include "object.h"
> @@ -56,6 +57,7 @@ void wt_status_prepare(struct wt_status *s)
>        s->reference = "HEAD";
>        s->fp = stdout;
>        s->index_file = get_index_file();
> +       s->change.strdup_strings = 1;
>  }
>
>  static void wt_status_print_cached_header(struct wt_status *s)
> @@ -98,18 +100,23 @@ static void wt_status_print_trailer(struct wt_status *s)
>
>  #define quote_path quote_path_relative
>
> -static void wt_status_print_filepair(struct wt_status *s,
> -                                    int t, struct diff_filepair *p)
> +static void wt_status_print_change_data(struct wt_status *s,
> +                                               int t,
> +                                               int status,
> +                                               char *one_name,
> +                                               char *two_name,
> +                                               int score)
>  {
>        const char *c = color(t);
>        const char *one, *two;
>        struct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT;
>
> -       one = quote_path(p->one->path, -1, &onebuf, s->prefix);
> -       two = quote_path(p->two->path, -1, &twobuf, s->prefix);
> +       one = quote_path(one_name, -1, &onebuf, s->prefix);
> +       two = quote_path(two_name, -1, &twobuf, s->prefix);
> +
>
>        color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t");
> -       switch (p->status) {
> +       switch (status) {
>        case DIFF_STATUS_ADDED:
>                color_fprintf(s->fp, c, "new file:   %s", one);
>                break;
> @@ -135,64 +142,88 @@ static void wt_status_print_filepair(struct wt_status *s,
>                color_fprintf(s->fp, c, "unmerged:   %s", one);
>                break;
>        default:
> -               die("bug: unhandled diff status %c", p->status);
> +               die("bug: unhandled diff status %c", status);
>        }
>        fprintf(s->fp, "\n");
>        strbuf_release(&onebuf);
>        strbuf_release(&twobuf);
>  }
>
> -static void wt_status_print_updated_cb(struct diff_queue_struct *q,
> -               struct diff_options *options,
> -               void *data)
> +static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
> +                                                       struct diff_options *options,
> +                                                       void *data)
>  {
>        struct wt_status *s = data;
> -       int shown_header = 0;
>        int i;
> +
> +       if (!q->nr)
> +               return;
> +       s->workdir_dirty = 1;
>        for (i = 0; i < q->nr; i++) {
> -               if (q->queue[i]->status == 'U')
> -                       continue;
> -               if (!shown_header) {
> -                       wt_status_print_cached_header(s);
> -                       s->commitable = 1;
> -                       shown_header = 1;
> -               }
> -               wt_status_print_filepair(s, WT_STATUS_UPDATED, q->queue[i]);
> +               struct diff_filepair *p;
> +               struct string_list_item *it;
> +               struct wt_status_change_data *d;
> +
> +               p = q->queue[i];
> +
> +               d = xcalloc(1, sizeof(*d));
> +               d->worktree_status = p->status;
> +               it = string_list_insert(p->one->path, &s->change);
> +               it->util = d;
>        }
> -       if (shown_header)
> -               wt_status_print_trailer(s);
>  }
>
> -static void wt_status_print_changed_cb(struct diff_queue_struct *q,
> -                        struct diff_options *options,
> -                        void *data)
> +static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
> +                                                       struct diff_options *options,
> +                                                       void *data)
>  {
>        struct wt_status *s = data;
>        int i;
> -       if (q->nr) {
> -               int has_deleted = 0;
> -               s->workdir_dirty = 1;
> -               for (i = 0; i < q->nr; i++)
> -                       if (q->queue[i]->status == DIFF_STATUS_DELETED) {
> -                               has_deleted = 1;
> +
> +       for (i = 0; i < q->nr; i++) {
> +               struct diff_filepair *p;
> +               struct string_list_item *it;
> +               struct wt_status_change_data *d;
> +
> +               p = q->queue[i];
> +               it = string_list_insert(p->two->path, &s->change);
> +               d = it->util;
> +               if (!d) {
> +                       d = xcalloc(1, sizeof(*d));
> +                       it->util = d;
> +               }
> +               d->index_status = p->status;
> +               switch (p->status) {
> +                       case DIFF_STATUS_COPIED:
> +                       case DIFF_STATUS_RENAMED:
> +                               d->head_path = xstrdup(p->one->path);
> +                               d->index_score = p->score;
>                                break;
> -                       }
> -               wt_status_print_dirty_header(s, has_deleted);
> +               }
>        }
> -       for (i = 0; i < q->nr; i++)
> -               wt_status_print_filepair(s, WT_STATUS_CHANGED, q->queue[i]);
> -       if (q->nr)
> -               wt_status_print_trailer(s);
>  }
>
> -static void wt_status_print_updated(struct wt_status *s)
> +static void wt_status_collect_changes_worktree(struct wt_status *s)
>  {
>        struct rev_info rev;
> +
> +       init_revisions(&rev, NULL);
> +       setup_revisions(0, NULL, &rev, NULL);
> +       rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
> +       rev.diffopt.format_callback = wt_status_collect_changed_cb;
> +       rev.diffopt.format_callback_data = s;
> +       run_diff_files(&rev, 0);
> +}
> +
> +static void wt_status_collect_changes_index(struct wt_status *s)
> +{
> +       struct rev_info rev;
> +
>        init_revisions(&rev, NULL);
>        setup_revisions(0, NULL, &rev,
>                s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference);
>        rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
> -       rev.diffopt.format_callback = wt_status_print_updated_cb;
> +       rev.diffopt.format_callback = wt_status_collect_updated_cb;
>        rev.diffopt.format_callback_data = s;
>        rev.diffopt.detect_rename = 1;
>        rev.diffopt.rename_limit = 200;
> @@ -200,15 +231,107 @@ static void wt_status_print_updated(struct wt_status *s)
>        run_diff_index(&rev, 1);
>  }
>
> +static void wt_status_collect_changes_initial(struct wt_status *s)
> +{
> +       int i;
> +
> +       for (i = 0; i < active_nr; i++) {
> +               struct string_list_item *it;
> +               struct wt_status_change_data *d;
> +
> +               it = string_list_insert(active_cache[i]->name, &s->change);
> +               d = it->util;
> +               if (!d) {
> +                       d = xcalloc(1, sizeof(*d));
> +                       it->util = d;
> +               }
> +               d->index_status = DIFF_STATUS_ADDED;
> +       }
> +}
> +
> +void wt_status_collect_changes(struct wt_status *s)
> +{
> +       wt_status_collect_changes_worktree(s);
> +
> +       if (s->is_initial)
> +               wt_status_collect_changes_initial(s);
> +       else
> +               wt_status_collect_changes_index(s);
> +}
> +
> +static void wt_status_print_updated(struct wt_status *s)
> +{
> +       int shown_header = 0;
> +       int i;
> +
> +       for (i = 0; i < s->change.nr; i++) {
> +               struct wt_status_change_data *d;
> +               struct string_list_item *it;
> +               it = &(s->change.items[i]);
> +               d = it->util;
> +               if (!d->index_status)
> +                       continue;
> +               if (!shown_header) {
> +                       wt_status_print_cached_header(s);
> +                       s->commitable = 1;
> +                       shown_header = 1;
> +               }
> +               wt_status_print_change_data(s, WT_STATUS_UPDATED,
> +                               d->index_status,
> +                               d->head_path ? d->head_path : it->string,
> +                               it->string,
> +                               d->index_score);
> +       }
> +       if (shown_header)
> +               wt_status_print_trailer(s);
> +}
> +
> +/*
> + * -1 : has delete
> + *  0 : no change
> + *  1 : some change but no delete
> + */
> +static int wt_status_check_worktree_changes(struct wt_status *s)
> +{
> +       int i;
> +       int changes = 0;
> +
> +       for (i = 0; i < s->change.nr; i++) {
> +               struct wt_status_change_data *d;
> +               d = s->change.items[i].util;
> +               if (!d->worktree_status)
> +                       continue;
> +               changes = 1;
> +               if (d->worktree_status == DIFF_STATUS_DELETED)
> +                       return -1;
> +       }
> +       return changes;
> +}
> +
>  static void wt_status_print_changed(struct wt_status *s)
>  {
> -       struct rev_info rev;
> -       init_revisions(&rev, "");
> -       setup_revisions(0, NULL, &rev, NULL);
> -       rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
> -       rev.diffopt.format_callback = wt_status_print_changed_cb;
> -       rev.diffopt.format_callback_data = s;
> -       run_diff_files(&rev, 0);
> +       int i;
> +       int worktree_changes = wt_status_check_worktree_changes(s);
> +
> +       if (!worktree_changes)
> +               return;
> +
> +       wt_status_print_dirty_header(s, worktree_changes < 0);
> +
> +       for (i = 0; i < s->change.nr; i++) {
> +               struct wt_status_change_data *d;
> +               struct string_list_item *it;
> +               it = &(s->change.items[i]);
> +               d = it->util;
> +               if (!d->worktree_status)
> +                       continue;
> +               wt_status_print_change_data(s, WT_STATUS_CHANGED,
> +                               d->worktree_status,
> +                               it->string,
> +                               it->string,
> +                               0);
> +       }
> +       wt_status_print_trailer(s);
>  }
>
>  static void wt_status_print_submodule_summary(struct wt_status *s)
> @@ -338,6 +461,8 @@ void wt_status_print(struct wt_status *s)
>                        wt_status_print_tracking(s);
>        }
>
> +       wt_status_collect_changes(s);
> +
>        if (s->is_initial) {
>                color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
>                color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "# Initial commit");
> diff --git a/wt-status.h b/wt-status.h
> index 78add09..00508c3 100644
> --- a/wt-status.h
> +++ b/wt-status.h
> @@ -18,6 +18,13 @@ enum untracked_status_type {
>  };
>  extern enum untracked_status_type show_untracked_files;
>
> +struct wt_status_change_data {
> +       int worktree_status;
> +       int index_status;
> +       int index_score;
> +       char *head_path;
> +};
> +
>  struct wt_status {
>        int is_initial;
>        char *branch;
> @@ -33,6 +40,7 @@ struct wt_status {
>        const char *index_file;
>        FILE *fp;
>        const char *prefix;
> +       struct string_list change;
>  };
>
>  int git_status_config(const char *var, const char *value, void *cb);
> @@ -40,5 +48,6 @@ extern int wt_status_use_color;
>  extern int wt_status_relative_paths;
>  void wt_status_prepare(struct wt_status *s);
>  void wt_status_print(struct wt_status *s);
> +void wt_status_collect_changes(struct wt_status *s);
>
>  #endif /* STATUS_H */
>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-02-04 22:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-04 22:05 [RFC/PATCH] shortstatus v0 Tuncer Ayaz
2009-02-04 22:17 ` Tuncer Ayaz

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).