From: Christian Couder <christian.couder@gmail.com>
To: Joel Teichroeb <joel@teichroeb.net>
Cc: git <git@vger.kernel.org>, Thomas Gummerer <t.gummerer@gmail.com>,
Jeff King <peff@peff.net>,
Johannes Schindelin <Johannes.Schindelin@gmx.de>
Subject: Re: [PATCH v3 4/4] stash: implement builtin stash
Date: Sun, 28 May 2017 19:56:28 +0200 [thread overview]
Message-ID: <CAP8UFD26oR2Y4hTYmZLBeKA8MTVe8ZTG3pJxfS9Xv8JUExbcKA@mail.gmail.com> (raw)
In-Reply-To: <20170528165642.14699-5-joel@teichroeb.net>
On Sun, May 28, 2017 at 6:56 PM, Joel Teichroeb <joel@teichroeb.net> wrote:
[...]
> +int untracked_files(struct strbuf *out, int include_untracked,
> + const char **argv)
> +{
> + struct child_process cp = CHILD_PROCESS_INIT;
> + cp.git_cmd = 1;
> + argv_array_push(&cp.args, "ls-files");
> + argv_array_push(&cp.args, "-o");
> + argv_array_push(&cp.args, "-z");
You might want to use argv_array_pushl(), for example:
argv_array_pushl(&cp.args, "ls-files", "-o", "-z", NULL);
> + if (include_untracked != 2)
> + argv_array_push(&cp.args, "--exclude-standard");
> + argv_array_push(&cp.args, "--");
> + if (argv)
> + argv_array_pushv(&cp.args, argv);
> + return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
> +}
> +
> +static int check_no_changes(const char *prefix, int include_untracked,
> + const char **argv)
> +{
> + struct argv_array args1;
> + struct argv_array args2;
> + struct strbuf out = STRBUF_INIT;
> +
> + argv_array_init(&args1);
> + argv_array_push(&args1, "diff-index");
> + argv_array_push(&args1, "--quiet");
> + argv_array_push(&args1, "--cached");
> + argv_array_push(&args1, "HEAD");
> + argv_array_push(&args1, "--ignore-submodules");
> + argv_array_push(&args1, "--");
Here and in other places also you could use argv_array_pushl().
> + if (argv)
> + argv_array_pushv(&args1, argv);
> + argv_array_init(&args2);
> + argv_array_push(&args2, "diff-files");
> + argv_array_push(&args2, "--quiet");
> + argv_array_push(&args2, "--ignore-submodules");
> + argv_array_push(&args2, "--");
> + if (argv)
> + argv_array_pushv(&args2, argv);
> + if (include_untracked)
> + untracked_files(&out, include_untracked, argv);
> + return cmd_diff_index(args1.argc, args1.argv, prefix) == 0 &&
> + cmd_diff_files(args2.argc, args2.argv, prefix) == 0 &&
> + (!include_untracked || out.len == 0);
> +}
> +
> +static int get_stash_info(struct stash_info *info, const char *commit)
> +{
> + struct strbuf w_commit_rev = STRBUF_INIT;
> + struct strbuf b_commit_rev = STRBUF_INIT;
> + struct strbuf i_commit_rev = STRBUF_INIT;
> + struct strbuf u_commit_rev = STRBUF_INIT;
> + struct strbuf w_tree_rev = STRBUF_INIT;
> + struct strbuf b_tree_rev = STRBUF_INIT;
> + struct strbuf i_tree_rev = STRBUF_INIT;
> + struct strbuf u_tree_rev = STRBUF_INIT;
> + struct strbuf commit_buf = STRBUF_INIT;
> + struct strbuf symbolic = STRBUF_INIT;
> + struct strbuf out = STRBUF_INIT;
> + struct object_context unused;
> + char *str;
> + int ret;
> + const char *REV = commit;
We use lower case variable names.
> + struct child_process cp = CHILD_PROCESS_INIT;
> + info->is_stash_ref = 0;
> +
> + if (commit == NULL) {
> + strbuf_addf(&commit_buf, "%s@{0}", ref_stash);
> + REV = commit_buf.buf;
> + } else if (strlen(commit) < 3) {
> + strbuf_addf(&commit_buf, "%s@{%s}", ref_stash, commit);
> + REV = commit_buf.buf;
> + }
> + info->REV = REV;
Also the "REV" member of struct stash_info could be lower cased.
> + strbuf_addf(&w_commit_rev, "%s", REV);
> + strbuf_addf(&b_commit_rev, "%s^1", REV);
> + strbuf_addf(&i_commit_rev, "%s^2", REV);
> + strbuf_addf(&u_commit_rev, "%s^3", REV);
> + strbuf_addf(&w_tree_rev, "%s:", REV);
> + strbuf_addf(&b_tree_rev, "%s^1:", REV);
> + strbuf_addf(&i_tree_rev, "%s^2:", REV);
> + strbuf_addf(&u_tree_rev, "%s^3:", REV);
> +
> +
Spurious new line above.
> + ret = (
> + get_sha1_with_context(w_commit_rev.buf, 0, info->w_commit.hash, &unused) == 0 &&
> + get_sha1_with_context(b_commit_rev.buf, 0, info->b_commit.hash, &unused) == 0 &&
> + get_sha1_with_context(i_commit_rev.buf, 0, info->i_commit.hash, &unused) == 0 &&
> + get_sha1_with_context(w_tree_rev.buf, 0, info->w_tree.hash, &unused) == 0 &&
> + get_sha1_with_context(b_tree_rev.buf, 0, info->b_tree.hash, &unused) == 0 &&
> + get_sha1_with_context(i_tree_rev.buf, 0, info->i_tree.hash, &unused) == 0);
> +
> + if (!ret) {
> + fprintf_ln(stderr, _("%s is not a valid reference"), REV);
> + return 1;
Maybe use "return error(_("%s is not a valid reference"), REV);"
> + }
> +
> +
Spurious new lines above.
> +
> +static void stash_create_callback(struct diff_queue_struct *q,
> + struct diff_options *opt, void *cbdata)
> +{
> + int i;
> +
> + for (i = 0; i < q->nr; i++) {
> + struct diff_filepair *p = q->queue[i];
> + const char *path = p->one->path;
> + struct stat st;
> + remove_file_from_index(&the_index, path);
> + if (!lstat(path, &st))
> + add_to_index(&the_index, path, &st, 0);
> +
Spurious new line above.
> + }
> +}
> +
> +/* Untracked files are stored by themselves in a parentless commit, for
> + * ease of unpacking later.
> + */
This comment should rather be like:
/*
* Untracked files are stored by themselves in a parentless commit, for
* ease of unpacking later.
*/
> +static int save_untracked(struct stash_info *info, struct strbuf *out,
> + int include_untracked, const char **argv)
> +{
> + struct child_process cp2 = CHILD_PROCESS_INIT;
> + struct strbuf out3 = STRBUF_INIT;
> + struct strbuf out4 = STRBUF_INIT;
Please try to find more meaningful names for such variables.
> + struct object_id orig_tree;
> +
> + set_alternate_index_output(stash_index_path);
> + untracked_files(&out4, include_untracked, argv);
> +
> + cp2.git_cmd = 1;
> + argv_array_push(&cp2.args, "update-index");
> + argv_array_push(&cp2.args, "-z");
> + argv_array_push(&cp2.args, "--add");
> + argv_array_push(&cp2.args, "--remove");
> + argv_array_push(&cp2.args, "--stdin");
> + argv_array_pushf(&cp2.env_array, "GIT_INDEX_FILE=%s", stash_index_path);
> +
> + if (pipe_command(&cp2, out4.buf, out4.len, NULL, 0, NULL, 0))
> + return 1;
> +
> + discard_cache();
> + read_cache_from(stash_index_path);
> +
> + write_index_as_tree(orig_tree.hash, &the_index, stash_index_path, 0, NULL);
> + discard_cache();
> +
> + read_cache_from(stash_index_path);
> +
> + write_cache_as_tree(info->u_tree.hash, 0, NULL);
> + strbuf_addf(&out3, "untracked files on %s", out->buf);
> +
> + if (commit_tree(out3.buf, out3.len, info->u_tree.hash, NULL, info->u_commit.hash, NULL, NULL))
> + return 1;
> +
> + set_alternate_index_output(".git/index");
Isn't there a variable, a function or a constant that could be used
instead of the hard coded ".git/index"?
> + discard_cache();
> + read_cache();
> +
> + return 0;
> +}
> +
> +static int save_working_tree(struct stash_info *info, const char *prefix,
> + const char **argv)
> +{
> + struct object_id orig_tree;
> + struct rev_info rev;
> + int nr_trees = 1;
> + struct tree_desc t[MAX_UNPACK_TREES];
> + struct tree *tree;
> + struct unpack_trees_options opts;
> + struct object *obj;
> +
> + discard_cache();
> + tree = parse_tree_indirect(info->i_tree.hash);
> + prime_cache_tree(&the_index, tree);
> + write_index_as_tree(orig_tree.hash, &the_index, stash_index_path, 0, NULL);
> + discard_cache();
> +
> + read_cache_from(stash_index_path);
> +
> + memset(&opts, 0, sizeof(opts));
> +
> + parse_tree(tree);
> +
> + opts.head_idx = 1;
> + opts.src_index = &the_index;
> + opts.dst_index = &the_index;
> + opts.merge = 1;
> + opts.fn = oneway_merge;
> +
> + init_tree_desc(t, tree->buffer, tree->size);
> +
> + if (unpack_trees(nr_trees, t, &opts))
> + return 1;
In general I think we tend to return -1 instead of 1 in case of errors in C.
[...]
> +static int do_create_stash(struct stash_info *info, const char *prefix,
> + const char *message, int include_untracked, int patch, const char **argv)
> +{
> + struct object_id curr_head;
> + char *branch_path = NULL;
> + const char *branch_name = NULL;
> + struct commit_list *parents = NULL;
> + struct strbuf out = STRBUF_INIT;
> + struct strbuf out3 = STRBUF_INIT;
> + struct pretty_print_context ctx = {0};
> +
> + struct commit *c = NULL;
> + const char *hash;
> + struct strbuf out2 = STRBUF_INIT;
> +
> + read_cache_preload(NULL);
> + refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
> + if (check_no_changes(prefix, include_untracked, argv))
> + return 1;
> +
> + if (get_sha1_tree("HEAD", info->b_commit.hash))
> + die(_("You do not have the initial commit yet"));
> +
> + branch_path = resolve_refdup("HEAD", 0, curr_head.hash, NULL);
> +
> + if (branch_path == NULL || strcmp(branch_path, "HEAD") == 0)
> + branch_name = "(no branch)";
> + else
> + skip_prefix(branch_path, "refs/heads/", &branch_name);
> +
> + c = lookup_commit(info->b_commit.hash);
> +
> + ctx.output_encoding = get_log_output_encoding();
> + ctx.abbrev = 1;
> + ctx.fmt = CMIT_FMT_ONELINE;
> + hash = find_unique_abbrev(c->object.oid.hash, DEFAULT_ABBREV);
> +
> + strbuf_addf(&out, "%s: %s ", branch_name, hash);
> +
> + pretty_print_commit(&ctx, c, &out);
> +
> + strbuf_addf(&out3, "index on %s\n", out.buf);
> +
> + commit_list_insert(lookup_commit(info->b_commit.hash), &parents);
> +
> + if (write_cache_as_tree(info->i_tree.hash, 0, NULL))
> + die(_("git write-tree failed to write a tree"));
> +
> + if (commit_tree(out3.buf, out3.len, info->i_tree.hash, parents, info->i_commit.hash, NULL, NULL))
> + die(_("Cannot save the current index state"));
> +
> +
> + if (include_untracked) {
> + if (save_untracked(info, &out, include_untracked, argv))
> + die(_("Cannot save the untracked files"));
> + }
> +
> +
Spurious new line above.
> + if (patch) {
> + if (patch_working_tree(info, prefix, argv))
> + die(_("Cannot save the current worktree state"));
> + } else {
> + if (save_working_tree(info, prefix, argv))
> + die(_("Cannot save the current worktree state"));
> + }
> + parents = NULL;
> +
> + if (include_untracked) {
> + commit_list_insert(lookup_commit(info->u_commit.hash), &parents);
> + }
Braces can be removed above.
> + commit_list_insert(lookup_commit(info->i_commit.hash), &parents);
> + commit_list_insert(lookup_commit(info->b_commit.hash), &parents);
> +
> + if (message != NULL && strlen(message) != 0)
> + strbuf_addf(&out2, "On %s: %s\n", branch_name, message);
> + else
> + strbuf_addf(&out2, "WIP on %s\n", out.buf);
> +
> + if (commit_tree(out2.buf, out2.len, info->w_tree.hash, parents, info->w_commit.hash, NULL, NULL))
> + die(_("Cannot record working tree state"));
> +
> + info->message = out2.buf;
> +
> + free(branch_path);
> +
> + return 0;
> +}
> +
> +static int create_stash(int argc, const char **argv, const char *prefix)
> +{
> + int include_untracked = 0;
> + const char *message = NULL;
> + struct stash_info info;
> + struct option options[] = {
> + OPT_BOOL('u', "include-untracked", &include_untracked,
> + N_("stash untracked filed")),
> + OPT_STRING('m', "message", &message, N_("message"),
> + N_("stash commit message")),
> + OPT_END()
> + };
> +
> + argc = parse_options(argc, argv, prefix, options,
> + git_stash_create_usage, 0);
> +
> + if (argc != 0) {
> + struct strbuf out = STRBUF_INIT;
> + int i;
> + for (i = 0; i < argc; ++i) {
> + if (i != 0) {
> + strbuf_addf(&out, " ");
> + }
Braces can be removed.
[...]
> +static int store_stash(int argc, const char **argv, const char *prefix)
> +{
> + const char *message = NULL;
> + const char *commit = NULL;
> + struct object_id obj;
> + struct option options[] = {
> + OPT_STRING('m', "message", &message, N_("message"),
> + N_("stash commit message")),
> + OPT__QUIET(&quiet, N_("be quiet, only report errors")),
> + OPT_END()
> + };
> + argc = parse_options(argc, argv, prefix, options,
> + git_stash_store_usage, 0);
> +
> + if (message == NULL)
> + message = "Create via \"git stash store\".";
Maybe you could have initialized "message" when you declared the variable above.
> + if (argc != 1)
> + die(_("\"git stash store\" requires one <commit> argument"));
> +
> + commit = argv[0];
> +
> + if (get_sha1(commit, obj.hash)) {
> + fprintf_ln(stderr, _("fatal: %s: not a valid SHA1"), commit);
> + fprintf_ln(stderr, _("cannot update %s with %s"), ref_stash, commit);
> + return 1;
Maybe use error() or warning().
> + }
[...]
> +static int do_push_stash(const char *prefix, const char *message,
> + int keep_index, int include_untracked, int patch, const char **argv)
> +{
> + int result;
> + struct stash_info info;
> +
> + if (patch && include_untracked) {
> + fprintf_ln(stderr, _("can't use --patch and --include-untracked or --all at the same time"));
> + return 1;
error()?
> + }
> +
> + if (!include_untracked) {
> + struct child_process cp = CHILD_PROCESS_INIT;
> + struct strbuf out = STRBUF_INIT;
> +
> + cp.git_cmd = 1;
> + argv_array_push(&cp.args, "ls-files");
> + argv_array_push(&cp.args, "--error-unmatch");
> + argv_array_push(&cp.args, "--");
> + if (argv)
> + argv_array_pushv(&cp.args, argv);
> + result = pipe_command(&cp, NULL, 0, &out, 0, NULL, 0);
> + if (result)
> + return 1;
> + }
> +
> + read_cache_preload(NULL);
> + refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
> + if (check_no_changes(prefix, include_untracked, argv)) {
> + printf(_("No local changes to save\n"));
> + return 0;
> + }
> +
> + if (!reflog_exists(ref_stash)) {
> + if (do_clear_stash())
> + die(_("Cannot initialize stash"));
> + }
> +
> +
Spurious new line.
> + do_create_stash(&info, prefix, message, include_untracked, patch, argv);
> + result = do_store_stash(prefix, 1, info.message, info.w_commit);
> +
> + if (result == 0 && !quiet) {
> + printf(_("Saved working directory and index state %s"), info.message);
> + }
Braces can be removed.
I stopped skimming here.
Thanks,
Christian.
next prev parent reply other threads:[~2017-05-28 17:56 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-28 16:56 [PATCH v3 0/4] Implement git stash as a builtin command Joel Teichroeb
2017-05-28 16:56 ` [PATCH v3 1/4] stash: add test for stash create with no files Joel Teichroeb
2017-05-28 17:45 ` Ævar Arnfjörð Bjarmason
2017-05-29 6:35 ` Junio C Hamano
2017-05-28 16:56 ` [PATCH v3 2/4] stash: add test for stashing in a detached state Joel Teichroeb
2017-05-28 17:57 ` Ævar Arnfjörð Bjarmason
2017-05-29 6:41 ` Junio C Hamano
2017-05-28 16:56 ` [PATCH v3 3/4] close the index lock when not writing the new index Joel Teichroeb
2017-05-28 17:46 ` Ævar Arnfjörð Bjarmason
2017-05-29 6:46 ` Junio C Hamano
2017-05-28 16:56 ` [PATCH v3 4/4] stash: implement builtin stash Joel Teichroeb
2017-05-28 17:56 ` Christian Couder [this message]
2017-05-28 18:26 ` Ævar Arnfjörð Bjarmason
2017-05-28 18:31 ` Joel Teichroeb
2017-05-28 19:26 ` Jeff King
2017-05-28 18:51 ` Ævar Arnfjörð Bjarmason
2017-05-28 19:21 ` Jeff King
2017-05-29 18:18 ` Joel Teichroeb
2017-05-29 18:26 ` Ævar Arnfjörð Bjarmason
2017-06-01 3:29 ` Joel Teichroeb
2017-06-01 4:07 ` Jeff King
2017-05-29 7:16 ` Junio C Hamano
2017-05-28 19:08 ` [PATCH v3 0/4] Implement git stash as a builtin command Ævar Arnfjörð Bjarmason
2017-10-23 11:09 ` Johannes Schindelin
2017-10-23 18:35 ` Joel Teichroeb
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAP8UFD26oR2Y4hTYmZLBeKA8MTVe8ZTG3pJxfS9Xv8JUExbcKA@mail.gmail.com \
--to=christian.couder@gmail.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=joel@teichroeb.net \
--cc=peff@peff.net \
--cc=t.gummerer@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).