Hi Paul, On Fri, 31 Aug 2018, Paul-Sebastian Ungureanu wrote: > diff --git a/builtin/stash--helper.c b/builtin/stash--helper.c > index 02b593e0cd..87568b0f34 100644 > --- a/builtin/stash--helper.c > +++ b/builtin/stash--helper.c > @@ -723,6 +728,54 @@ static int show_stash(int argc, const char **argv, const char *prefix) > return diff_result_code(&rev.diffopt, 0); > } > > +static int do_store_stash(const char *w_commit, const char *stash_msg, > + int quiet) > +{ > + int ret = 0; > + int need_to_free = 0; Not worth sending another iteration, but if you end up doing so, I found an alternative paradigm more useful: instead of having a Boolean to indicate whether you need to free, have a `char *to_free` that is initialized to `NULL`, then unconditionally release that: char *to_free = NULL; if (!stash_msg) stash_msg = to_free = xstrdup("Created via \"git stash store\"."); [...] free(to_free); return ret; This works because `free(NULL)` is defined as a no-op. > + struct object_id obj; > + > + if (!stash_msg) { > + need_to_free = 1; > + stash_msg = xstrdup("Created via \"git stash store\"."); > + } > + > + ret = get_oid(w_commit, &obj); Is `get_oid()` non-quiet? If so, we might need to shut it up when the `quiet` variable is non-zero. If it is quiet, we should probably mention something here when `quiet` is zero and `ret` indicates an error with `get_oid()`. > + if (!ret) { > + ret = update_ref(stash_msg, ref_stash, &obj, NULL, > + REF_FORCE_CREATE_REFLOG, > + quiet ? UPDATE_REFS_QUIET_ON_ERR : > + UPDATE_REFS_MSG_ON_ERR); > + } > + if (ret && !quiet) > + fprintf_ln(stderr, _("Cannot update %s with %s"), > + ref_stash, w_commit); > + if (need_to_free) > + free((char *) stash_msg); Okay, so all we need `stash_msg` for is the `update_ref()` call? And the fall-back message is constant. So how about if (!stash_msg) stash_msg = "Created via \"git stash store\"."; ? No need to allocate/release memory at all... > + return ret; > +} > + > +static int store_stash(int argc, const char **argv, const char *prefix) > +{ > + const char *stash_msg = NULL; > + struct option options[] = { > + OPT__QUIET(&quiet, N_("be quiet, only report errors")), > + OPT_STRING('m', "message", &stash_msg, "message", N_("stash message")), > + OPT_END() > + }; > + > + argc = parse_options(argc, argv, prefix, options, > + git_stash_helper_store_usage, > + PARSE_OPT_KEEP_UNKNOWN); > + > + if (argc != 1) { > + fprintf_ln(stderr, _("\"git stash store\" requires one <commit> argument")); > + return -1; > + } > + > + return do_store_stash(argv[0], stash_msg, quiet); > +} I guess `store_stash()` and `do_store_stash()` are separate functions to discern between the higher-level function that parses the command-line, and the lower-level function that is already libified? If so: 1. I like it. Your code is already so much better prepared to serve as a proper internal API than even some Git old-timers'. 2. It might make sense to move the `get_oid()` call to `store_stash()`, as it is also parsing: it is parsing the plain-text representation of the revision into the internal representation (object ID). Neither of these suggestions are blockers, though. Thanks, Dscho > int cmd_stash__helper(int argc, const char **argv, const char *prefix) > { > pid_t pid = getpid(); > @@ -757,6 +810,8 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix) > return !!list_stash(argc, argv, prefix); > else if (!strcmp(argv[0], "show")) > return !!show_stash(argc, argv, prefix); > + else if (!strcmp(argv[0], "store")) > + return !!store_stash(argc, argv, prefix); > > usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]), > git_stash_helper_usage, options); > diff --git a/git-stash.sh b/git-stash.sh > index 0d05cbc1e5..5739c51527 100755 > --- a/git-stash.sh > +++ b/git-stash.sh > @@ -191,45 +191,6 @@ create_stash () { > die "$(gettext "Cannot record working tree state")" > } > > -store_stash () { > - while test $# != 0 > - do > - case "$1" in > - -m|--message) > - shift > - stash_msg="$1" > - ;; > - -m*) > - stash_msg=${1#-m} > - ;; > - --message=*) > - stash_msg=${1#--message=} > - ;; > - -q|--quiet) > - quiet=t > - ;; > - *) > - break > - ;; > - esac > - shift > - done > - test $# = 1 || > - die "$(eval_gettext "\"$dashless store\" requires one <commit> argument")" > - > - w_commit="$1" > - if test -z "$stash_msg" > - then > - stash_msg="Created via \"git stash store\"." > - fi > - > - git update-ref --create-reflog -m "$stash_msg" $ref_stash $w_commit > - ret=$? > - test $ret != 0 && test -z "$quiet" && > - die "$(eval_gettext "Cannot update \$ref_stash with \$w_commit")" > - return $ret > -} > - > push_stash () { > keep_index= > patch_mode= > @@ -308,7 +269,7 @@ push_stash () { > clear_stash || die "$(gettext "Cannot initialize stash")" > > create_stash -m "$stash_msg" -u "$untracked" -- "$@" > - store_stash -m "$stash_msg" -q $w_commit || > + git stash--helper store -m "$stash_msg" -q $w_commit || > die "$(gettext "Cannot save the current status")" > say "$(eval_gettext "Saved working directory and index state \$stash_msg")" > > @@ -468,7 +429,7 @@ create) > ;; > store) > shift > - store_stash "$@" > + git stash--helper store "$@" > ;; > drop) > shift > -- > 2.19.0.rc0.22.gc26283d74e > >