[PATCH v9 15/21] stash: convert create to builtin
Add stash create to the helper. Signed-off-by: Paul-Sebastian Ungureanu --- builtin/stash--helper.c | 450 git-stash.sh| 2 +- 2 files changed, 451 insertions(+), 1 deletion(-) diff --git a/builtin/stash--helper.c b/builtin/stash--helper.c index b7421b68aa..49b05f2458 100644 --- a/builtin/stash--helper.c +++ b/builtin/stash--helper.c @@ -12,6 +12,9 @@ #include "rerere.h" #include "revision.h" #include "log-tree.h" +#include "diffcore.h" + +#define INCLUDE_ALL_FILES 2 static const char * const git_stash_helper_usage[] = { N_("git stash--helper list []"), @@ -63,6 +66,11 @@ static const char * const git_stash_helper_store_usage[] = { NULL }; +static const char * const git_stash_helper_create_usage[] = { + N_("git stash--helper create []"), + NULL +}; + static const char *ref_stash = "refs/stash"; static struct strbuf stash_index_path = STRBUF_INIT; @@ -289,6 +297,24 @@ static int reset_head(void) return run_command(&cp); } +static void add_diff_to_buf(struct diff_queue_struct *q, + struct diff_options *options, + void *data) +{ + int i; + + for (i = 0; i < q->nr; i++) { + strbuf_addstr(data, q->queue[i]->one->path); + + /* +* The reason we add "0" at the end of this strbuf +* is because we will pass the output further to +* "git update-index -z ...". +*/ + strbuf_addch(data, 0); + } +} + static int get_newly_staged(struct strbuf *out, struct object_id *c_tree) { struct child_process cp = CHILD_PROCESS_INIT; @@ -786,6 +812,428 @@ static int store_stash(int argc, const char **argv, const char *prefix) return do_store_stash(&obj, stash_msg, quiet); } +static void add_pathspecs(struct argv_array *args, + struct pathspec ps) { + int i; + + for (i = 0; i < ps.nr; i++) + argv_array_push(args, ps.items[i].match); +} + +/* + * `untracked_files` will be filled with the names of untracked files. + * The return value is: + * + * = 0 if there are not any untracked files + * > 0 if there are untracked files + */ +static int get_untracked_files(struct pathspec ps, int include_untracked, + struct strbuf *untracked_files) +{ + int i; + int max_len; + int found = 0; + char *seen; + struct dir_struct dir; + + memset(&dir, 0, sizeof(dir)); + if (include_untracked != INCLUDE_ALL_FILES) + setup_standard_excludes(&dir); + + seen = xcalloc(ps.nr, 1); + + max_len = fill_directory(&dir, the_repository->index, &ps); + for (i = 0; i < dir.nr; i++) { + struct dir_entry *ent = dir.entries[i]; + if (dir_path_match(&the_index, ent, &ps, max_len, seen)) { + found++; + strbuf_addstr(untracked_files, ent->name); + /* NUL-terminate: will be fed to update-index -z */ + strbuf_addch(untracked_files, 0); + } + free(ent); + } + + free(seen); + free(dir.entries); + free(dir.ignored); + clear_directory(&dir); + return found; +} + +/* + * The return value of `check_changes()` can be: + * + * < 0 if there was an error + * = 0 if there are no changes. + * > 0 if there are changes. + */ +static int check_changes(struct pathspec ps, int include_untracked) +{ + int result; + int ret = 0; + struct rev_info rev; + struct object_id dummy; + struct strbuf out = STRBUF_INIT; + + /* No initial commit. */ + if (get_oid("HEAD", &dummy)) + return -1; + + if (read_cache() < 0) + return -1; + + init_revisions(&rev, NULL); + rev.prune_data = ps; + + rev.diffopt.flags.quick = 1; + rev.diffopt.flags.ignore_submodules = 1; + rev.abbrev = 0; + + add_head_to_pending(&rev); + diff_setup_done(&rev.diffopt); + + result = run_diff_index(&rev, 1); + if (diff_result_code(&rev.diffopt, result)) + return 1; + + object_array_clear(&rev.pending); + result = run_diff_files(&rev, 0); + if (diff_result_code(&rev.diffopt, result)) + return 1; + + if (include_untracked && get_untracked_files(ps, include_untracked, +&out)) { + strbuf_release(&out); + return 1; + } + + strbuf_release(&out); + return 0; +} + +static int save_untracked_files(struct stash_info *info, struct strbuf *msg, + struct strbuf files) +{ + int ret = 0; + struct strbuf untracked_msg = STRBUF_INIT; + struct strbuf out = STRBUF_INIT; + struct child_p
Re: [PATCH v9 15/21] stash: convert create to builtin
On 09/26, Paul-Sebastian Ungureanu wrote: > Add stash create to the helper. > > Signed-off-by: Paul-Sebastian Ungureanu > --- > builtin/stash--helper.c | 450 > git-stash.sh| 2 +- > 2 files changed, 451 insertions(+), 1 deletion(-) > > diff --git a/builtin/stash--helper.c b/builtin/stash--helper.c > index b7421b68aa..49b05f2458 100644 > --- a/builtin/stash--helper.c > +++ b/builtin/stash--helper.c > @@ -12,6 +12,9 @@ > #include "rerere.h" > #include "revision.h" > #include "log-tree.h" > +#include "diffcore.h" > + > +#define INCLUDE_ALL_FILES 2 > > static const char * const git_stash_helper_usage[] = { > N_("git stash--helper list []"), > @@ -63,6 +66,11 @@ static const char * const git_stash_helper_store_usage[] = > { > NULL > }; > > +static const char * const git_stash_helper_create_usage[] = { > + N_("git stash--helper create []"), > + NULL > +}; > + > static const char *ref_stash = "refs/stash"; > static struct strbuf stash_index_path = STRBUF_INIT; > > @@ -289,6 +297,24 @@ static int reset_head(void) > return run_command(&cp); > } > > +static void add_diff_to_buf(struct diff_queue_struct *q, > + struct diff_options *options, > + void *data) > +{ > + int i; > + > + for (i = 0; i < q->nr; i++) { > + strbuf_addstr(data, q->queue[i]->one->path); > + > + /* > + * The reason we add "0" at the end of this strbuf > + * is because we will pass the output further to > + * "git update-index -z ...". > + */ > + strbuf_addch(data, 0); I'd find it slightly clearer to pass '\0' instead of 0 here. That makes it immediately clear to the reader that we mean the NUL character (even though it all ends up being the same in the end). > + } > +} > + > static int get_newly_staged(struct strbuf *out, struct object_id *c_tree) > { > struct child_process cp = CHILD_PROCESS_INIT; > @@ -786,6 +812,428 @@ static int store_stash(int argc, const char **argv, > const char *prefix) > return do_store_stash(&obj, stash_msg, quiet); > } > > +static void add_pathspecs(struct argv_array *args, > +struct pathspec ps) { This indentation looks a bit weird. > + int i; > + > + for (i = 0; i < ps.nr; i++) > + argv_array_push(args, ps.items[i].match); > +} > + > +/* > + * `untracked_files` will be filled with the names of untracked files. > + * The return value is: > + * > + * = 0 if there are not any untracked files > + * > 0 if there are untracked files > + */ > +static int get_untracked_files(struct pathspec ps, int include_untracked, > +struct strbuf *untracked_files) > +{ > + int i; > + int max_len; > + int found = 0; > + char *seen; > + struct dir_struct dir; > + > + memset(&dir, 0, sizeof(dir)); > + if (include_untracked != INCLUDE_ALL_FILES) > + setup_standard_excludes(&dir); > + > + seen = xcalloc(ps.nr, 1); > + > + max_len = fill_directory(&dir, the_repository->index, &ps); > + for (i = 0; i < dir.nr; i++) { > + struct dir_entry *ent = dir.entries[i]; > + if (dir_path_match(&the_index, ent, &ps, max_len, seen)) { > + found++; > + strbuf_addstr(untracked_files, ent->name); > + /* NUL-terminate: will be fed to update-index -z */ > + strbuf_addch(untracked_files, 0); > + } > + free(ent); > + } > + > + free(seen); > + free(dir.entries); > + free(dir.ignored); > + clear_directory(&dir); > + return found; > +} > + > +/* > + * The return value of `check_changes()` can be: > + * > + * < 0 if there was an error > + * = 0 if there are no changes. > + * > 0 if there are changes. > + */ > +static int check_changes(struct pathspec ps, int include_untracked) > +{ > + int result; > + int ret = 0; This variable is unused, so compilation with -Werror breaks at this patch. > + struct rev_info rev; > + struct object_id dummy; > + struct strbuf out = STRBUF_INIT; > + > + /* No initial commit. */ > + if (get_oid("HEAD", &dummy)) > + return -1; > + > + if (read_cache() < 0) > + return -1; > + > + init_revisions(&rev, NULL); > + rev.prune_data = ps; > + > + rev.diffopt.flags.quick = 1; > + rev.diffopt.flags.ignore_submodules = 1; > + rev.abbrev = 0; > + > + add_head_to_pending(&rev); > + diff_setup_done(&rev.diffopt); > + > + result = run_diff_index(&rev, 1); > + if (diff_result_code(&rev.diffopt, result)) > + return 1; > + > + object_array_clear(&rev.pending); > + result = run_diff_files(&rev, 0); > + if (diff_result_code(&rev.diffopt, result)) > + return 1; > + > + if (inclu