This patch adds a unique identifier for each file shown by "git status". Subsequent operation (add/rm/checkout/commit/reset) may use these ids to simplify specifying the files, provided that they are taught about the --id option as well. Example: $ git status --id # On branch local # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: builtin-add.c (m1) # modified: builtin-checkout.c (m2) # modified: builtin-commit.c (m3) # modified: builtin-reset.c (m4) # modified: builtin-rm.c (m5) # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # makefile.debug (x1) # nazri.sh (x2) no changes added to commit (use "git add" and/or "git commit -a") $ git add --id m1 # Short for "git add builtin-add.c $ git add --id m3,m5 # Short for "git add builtin-commit.c builtin-rm.c" # Even shorter: -d is equivalent to --id $ git add -d m3,m5 Signed-off-by: Nazri Ramliy <ayiehere@xxxxxxxxx> --- cache.h | 1 + path.c | 44 ++++++++++++++++++ wt-status.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- wt-status.h | 1 + 4 files changed, 181 insertions(+), 11 deletions(-) diff --git a/cache.h b/cache.h index e6c7f33..05817e3 100644 --- a/cache.h +++ b/cache.h @@ -649,6 +649,7 @@ const char *make_relative_path(const char *abs, const char *base); int normalize_path_copy(char *dst, const char *src); int longest_ancestor_length(const char *path, const char *prefix_list); char *strip_path_suffix(const char *path, const char *suffix); +char ** expand_file_ids(const char *file_id, int *argc, char **argv); /* Read and unpack a sha1 file into memory, write memory to a sha1 file */ extern int sha1_object_info(const unsigned char *, unsigned long *); diff --git a/path.c b/path.c index 047fdb0..7824c4a 100644 --- a/path.c +++ b/path.c @@ -564,3 +564,47 @@ char *strip_path_suffix(const char *path, const char *suffix) return NULL; return xstrndup(path, chomp_trailing_dir_sep(path, path_len)); } + +char ** expand_file_ids(const char *file_id, int *argc, char **argv) +{ + FILE *fp; + const char *filename = git_path("FILE_IDS"); + struct strbuf sb = STRBUF_INIT; + int i; + + char **new_argv; + + new_argv = (char **) xmalloc(*argc * sizeof(char *)); + for (i = 0; i < *argc; i++) { + new_argv[i] = (char *) argv[i]; + } + + fp = fopen(filename, "r"); + if (!fp) + die("cannot open %s: %s\n", filename, strerror(errno)); + + while (strbuf_getline(&sb, fp, '\n') == 0) { + char *b, *e; + if (sb.len == 0) + continue; + b = e = sb.buf; + while(*e && *e != ' ') + e++; + *e = '\0'; + if(strstr(file_id, b)) { + (*argc)++; + new_argv = xrealloc(new_argv, (*argc) * sizeof(char *)); + new_argv[*argc - 1] = xstrdup(e+1); + } + } + strbuf_release(&sb); + + /* + * parse_options adds a NULL terminator at end of argv. Do the same for + * new_argv. + */ + new_argv = xrealloc(new_argv, *argc + 1 * sizeof(char *)); + new_argv[*argc] = NULL; + + return new_argv; +} diff --git a/wt-status.c b/wt-status.c index 47735d8..6013fbd 100644 --- a/wt-status.c +++ b/wt-status.c @@ -96,6 +96,106 @@ static void wt_status_print_trailer(struct wt_status *s) color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#"); } +struct id_list { + struct id_list *next; + char status; + int nr; + char *name; +}; + +static struct id_list *wt_files = NULL; +static struct id_list *wt_files_last = NULL; +static int n_id_list = 0; + +static int get_id_list_id(char status) +{ + static int added = 0; + static int copied = 0; + static int deleted = 0; + static int modified = 0; + static int renamed = 0; + static int type_changed = 0; + static int unknown = 0; + static int unmerged = 0; + + switch(status) { + case DIFF_STATUS_ADDED: + return ++added; + case DIFF_STATUS_COPIED: + return ++copied; + case DIFF_STATUS_DELETED: + return ++deleted; + case DIFF_STATUS_MODIFIED: + return ++modified; + case DIFF_STATUS_RENAMED: + return ++renamed; + case DIFF_STATUS_TYPE_CHANGED: + return ++type_changed; + case DIFF_STATUS_UNKNOWN: + return ++unknown; + case DIFF_STATUS_UNMERGED: + return ++unmerged; + } + die("bug: unhandled diff status %c", status); +} + +static int add_to_id_list(char status, const char *name) +{ + struct id_list *new_entry; + if(wt_files_last == NULL) { + wt_files = xcalloc(1, sizeof(*wt_files)); + wt_files_last = wt_files; + new_entry = wt_files_last; + } else { + wt_files_last->next = xcalloc(1, sizeof(*wt_files)); + new_entry = wt_files_last->next; + wt_files_last = wt_files_last->next; + } + new_entry->name = xstrdup(name); + new_entry->nr = get_id_list_id(status); + new_entry->status = status; + new_entry->next = NULL; + + n_id_list++; + + return new_entry->nr; +} + +static void store_id_list() +{ + FILE *fp; + struct id_list *p = wt_files; + const char *filename = git_path("FILE_IDS"); + + fp = fopen(filename, "w"); + if (!fp) + die("cannot open %s: %s\n", filename, strerror(errno)); + + while (p) { + fprintf(fp, "%c%d %s\n",tolower(p->status), p->nr, p->name); + p = p->next; + } + fclose(fp); +} + +static void free_id_list() +{ + struct id_list *p = wt_files; + struct id_list *next = p; + while (p) { + next = p->next; + free(p->name); + free(p); + p = next; + } + wt_files = NULL; +} + +static void format_id(char *buf, char status, int nr) +{ + sprintf(buf, " (%c%d)", tolower(status), nr); +} + #define quote_path quote_path_relative static void wt_status_print_filepair(struct wt_status *s, @@ -104,35 +204,48 @@ static void wt_status_print_filepair(struct wt_status *s, const char *c = color(t); const char *one, *two; struct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT; + char id[64] = ""; /* arbitrary limit, 64 should be enough for everybody ... */ + int nr; one = quote_path(p->one->path, -1, &onebuf, s->prefix); two = quote_path(p->two->path, -1, &twobuf, s->prefix); + if (s->show_file_id) { + if ( p->status == DIFF_STATUS_RENAMED + || p->status == DIFF_STATUS_COPIED) + nr = add_to_id_list(p->status, two); + else + nr = add_to_id_list(p->status, one); + format_id(id, p->status, nr); + } + + color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t"); switch (p->status) { case DIFF_STATUS_ADDED: - color_fprintf(s->fp, c, "new file: %s", one); + color_fprintf(s->fp, c, "new file: %s%s", one, id); break; case DIFF_STATUS_COPIED: - color_fprintf(s->fp, c, "copied: %s -> %s", one, two); + color_fprintf(s->fp, c, "copied: %s -> %s%s", one, two, id); break; case DIFF_STATUS_DELETED: - color_fprintf(s->fp, c, "deleted: %s", one); + color_fprintf(s->fp, c, "deleted: %s%s", one, id); break; case DIFF_STATUS_MODIFIED: - color_fprintf(s->fp, c, "modified: %s", one); + color_fprintf(s->fp, c, "modified: %s%s", one, id); + break; case DIFF_STATUS_RENAMED: - color_fprintf(s->fp, c, "renamed: %s -> %s", one, two); + color_fprintf(s->fp, c, "renamed: %s -> %s%s", one, two, id); break; case DIFF_STATUS_TYPE_CHANGED: - color_fprintf(s->fp, c, "typechange: %s", one); + color_fprintf(s->fp, c, "typechange: %s%s", one, id); break; case DIFF_STATUS_UNKNOWN: - color_fprintf(s->fp, c, "unknown: %s", one); + color_fprintf(s->fp, c, "unknown: %s%s", one, id); break; case DIFF_STATUS_UNMERGED: - color_fprintf(s->fp, c, "unmerged: %s", one); + color_fprintf(s->fp, c, "unmerged: %s%s", one, id); break; default: die("bug: unhandled diff status %c", p->status); @@ -247,6 +360,9 @@ static void wt_status_print_untracked(struct wt_status *s) int i; int shown_header = 0; struct strbuf buf = STRBUF_INIT; + char id[64] = ""; /* arbitrary limit, 64 should be enough for everybody ... */ + char *quoted; + int nr; memset(&dir, 0, sizeof(dir)); @@ -266,9 +382,13 @@ 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", - quote_path(ent->name, ent->len, - &buf, s->prefix)); + quoted = quote_path(ent->name, ent->len, &buf, s->prefix); + if (s->show_file_id) { + nr = add_to_id_list(DIFF_STATUS_UNKNOWN, quoted); + format_id(id, DIFF_STATUS_UNKNOWN, nr); + } + color_fprintf_ln(s->fp, color(WT_STATUS_UNTRACKED), "%s%s", + quoted, id); } strbuf_release(&buf); } @@ -370,6 +490,10 @@ void wt_status_print(struct wt_status *s) else printf("nothing to commit (working directory clean)\n"); } + if (s->show_file_id) { + store_id_list(); + free_id_list(); + } } int git_status_config(const char *k, const char *v, void *cb) diff --git a/wt-status.h b/wt-status.h index 78add09..efcb566 100644 --- a/wt-status.h +++ b/wt-status.h @@ -23,6 +23,7 @@ struct wt_status { char *branch; const char *reference; int verbose; + int show_file_id; int amend; int untracked; int nowarn; -- 1.6.4.13.ge6580 -- 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