On Wed, Feb 4, 2009 at 11:05 PM, Tuncer Ayaz <tuncer.ayaz@xxxxxxxxx> 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@xxxxxxxxx> > --- > > .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 */ > -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html