Re: [PATCH v9 15/21] stash: convert create to builtin

2018-10-02 Thread Thomas Gummerer
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();
>  }
>  
> +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(, 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(, 0, sizeof(dir));
> + if (include_untracked != INCLUDE_ALL_FILES)
> + setup_standard_excludes();
> +
> + seen = xcalloc(ps.nr, 1);
> +
> + max_len = fill_directory(, the_repository->index, );
> + for (i = 0; i < dir.nr; i++) {
> + struct dir_entry *ent = dir.entries[i];
> + if (dir_path_match(_index, ent, , 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();
> + 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", ))
> + return -1;
> +
> + if (read_cache() < 0)
> + return -1;
> +
> + init_revisions(, NULL);
> + rev.prune_data = ps;
> +
> + rev.diffopt.flags.quick = 1;
> + rev.diffopt.flags.ignore_submodules = 1;
> + rev.abbrev = 0;
> +
> + add_head_to_pending();
> + diff_setup_done();
> +
> + result = run_diff_index(, 1);
> + if (diff_result_code(, result))
> + return 1;
> +
> + object_array_clear();
> + result = run_diff_files(, 0);
> + if (diff_result_code(, result))
> + return 1;
> +
> + if (include_untracked && get_untracked_files(ps, include_untracked,
> + 

[PATCH v9 15/21] stash: convert create to builtin

2018-09-25 Thread Paul-Sebastian Ungureanu
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();
 }
 
+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(, 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(, 0, sizeof(dir));
+   if (include_untracked != INCLUDE_ALL_FILES)
+   setup_standard_excludes();
+
+   seen = xcalloc(ps.nr, 1);
+
+   max_len = fill_directory(, the_repository->index, );
+   for (i = 0; i < dir.nr; i++) {
+   struct dir_entry *ent = dir.entries[i];
+   if (dir_path_match(_index, ent, , 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();
+   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", ))
+   return -1;
+
+   if (read_cache() < 0)
+   return -1;
+
+   init_revisions(, NULL);
+   rev.prune_data = ps;
+
+   rev.diffopt.flags.quick = 1;
+   rev.diffopt.flags.ignore_submodules = 1;
+   rev.abbrev = 0;
+
+   add_head_to_pending();
+   diff_setup_done();
+
+   result = run_diff_index(, 1);
+   if (diff_result_code(, result))
+   return 1;
+
+   object_array_clear();
+   result = run_diff_files(, 0);
+   if (diff_result_code(, result))
+   return 1;
+
+   if (include_untracked && get_untracked_files(ps, include_untracked,
+)) {
+   strbuf_release();
+   return 1;
+   }
+
+   strbuf_release();
+   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_process cp_upd_index = CHILD_PROCESS_INIT;
+   struct child_process cp_write_tree = CHILD_PROCESS_INIT;
+
+