This commits introduces a optimization by avoiding calling the same functions again. For example, `git stash push -u` would call at some points the following functions: * `check_changes()` * `do_create_stash()`, which calls: `check_changes()` and `get_untracked_files()` Note that `check_changes()` also calls `get_untracked_files()`. So, `check_changes()` is called 2 times and `get_untracked_files()` 3 times. By checking at the beginning of the function if we already performed a check, we can avoid making useless calls. --- builtin/stash.c | 50 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/builtin/stash.c b/builtin/stash.c index 0ef88408a..4d5c0d16e 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -819,13 +819,23 @@ static int store_stash(int argc, const char **argv, const char *prefix) } /* - * `out` will be filled with the names of untracked files. The return value is: + * `has_untracked_files` is: + * -2 if `get_untracked_files()` hasn't been called + * -1 if there were errors + * 0 if there are no untracked files + * 1 if there are untracked files + * + * `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 struct strbuf untracked_files = STRBUF_INIT; +static int has_untracked_files = -2; + static int get_untracked_files(const char **argv, const char *prefix, - int include_untracked, struct strbuf *out) + int include_untracked) { int max_len; int i; @@ -833,6 +843,9 @@ static int get_untracked_files(const char **argv, const char *prefix, struct dir_struct dir; struct pathspec pathspec; + if (has_untracked_files != -2) + return has_untracked_files; + memset(&dir, 0, sizeof(dir)); if (include_untracked != 2) setup_standard_excludes(&dir); @@ -849,7 +862,7 @@ static int get_untracked_files(const char **argv, const char *prefix, free(ent); continue; } - strbuf_addf(out, "%s\n", ent->name); + strbuf_addf(&untracked_files, "%s\n", ent->name); free(ent); } @@ -857,16 +870,25 @@ static int get_untracked_files(const char **argv, const char *prefix, free(dir.ignored); clear_directory(&dir); free(seen); - return out->len; + has_untracked_files = untracked_files.len; + return untracked_files.len; } /* + * `changes` is: + * -2 if `check_changes()` hasn't been called + * -1 if there were any errors + * 0 if there are no changes + * 1 if there are changes + * * 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 changes = -2; + static int check_changes(const char **argv, int include_untracked, const char *prefix) { @@ -874,9 +896,11 @@ static int check_changes(const char **argv, int include_untracked, int ret = 0; struct rev_info rev; struct object_id dummy; - struct strbuf out = STRBUF_INIT; struct argv_array args = ARGV_ARRAY_INIT; + if (changes != -2) + return changes; + init_revisions(&rev, prefix); parse_pathspec(&rev.prune_data, 0, PATHSPEC_PREFER_FULL, prefix, argv); @@ -912,17 +936,16 @@ static int check_changes(const char **argv, int include_untracked, } if (include_untracked && get_untracked_files(argv, prefix, - include_untracked, &out)) + include_untracked)) ret = 1; done: - strbuf_release(&out); + changes = ret; argv_array_clear(&args); return ret; } -static int save_untracked_files(struct stash_info *info, struct strbuf *msg, - struct strbuf *out) +static int save_untracked_files(struct stash_info *info, struct strbuf *msg) { int ret = 0; struct strbuf untracked_msg = STRBUF_INIT; @@ -937,7 +960,8 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg, stash_index_path.buf); strbuf_addf(&untracked_msg, "untracked files on %s\n", msg->buf); - if (pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0)) { + if (pipe_command(&cp, untracked_files.buf, untracked_files.len, + NULL, 0, NULL, 0)) { ret = -1; goto done; } @@ -1116,7 +1140,6 @@ static int do_create_stash(int argc, const char **argv, const char *prefix, struct commit_list *parents = NULL; struct strbuf msg = STRBUF_INIT; struct strbuf commit_tree_label = STRBUF_INIT; - struct strbuf out = STRBUF_INIT; struct strbuf final_stash_msg = STRBUF_INIT; read_cache_preload(NULL); @@ -1158,8 +1181,8 @@ static int do_create_stash(int argc, const char **argv, const char *prefix, } if (include_untracked && get_untracked_files(argv, prefix, - include_untracked, &out)) { - if (save_untracked_files(info, &msg, &out)) { + include_untracked)) { + if (save_untracked_files(info, &msg)) { if (!quiet) printf_ln("Cannot save the untracked files"); ret = -1; @@ -1213,7 +1236,6 @@ static int do_create_stash(int argc, const char **argv, const char *prefix, done: strbuf_release(&commit_tree_label); strbuf_release(&msg); - strbuf_release(&out); strbuf_release(&final_stash_msg); return ret; } -- 2.18.0.573.g56500d98f