[GSoC][PATCH v7 24/26] stash: optimize `get_untracked_files()` and `check_changes()`

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux