diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2019-08-11 23:42:45 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-11 23:42:45 +0100 |
commit | 5774b2b13468aa3c2e7e604dd348357f6842c56a (patch) | |
tree | b545eff2095ad84acb3533db6e7dc2b3a8dd32cb | |
parent | 42bacbc603bccf717b29cf603f825c9e6f5c1cf3 (diff) | |
parent | a7d32d60c1fecef268100a85b6a0f8f8c824ea0e (diff) | |
download | libgit2-5774b2b13468aa3c2e7e604dd348357f6842c56a.tar.gz |
Merge pull request #5113 from pks-t/pks/stash-perf
stash: avoid recomputing tree when committing worktree
-rw-r--r-- | examples/common.h | 1 | ||||
-rw-r--r-- | examples/lg2.c | 1 | ||||
-rw-r--r-- | examples/stash.c | 157 | ||||
-rw-r--r-- | src/stash.c | 23 |
4 files changed, 168 insertions, 14 deletions
diff --git a/examples/common.h b/examples/common.h index bba83217b..2ad897bca 100644 --- a/examples/common.h +++ b/examples/common.h @@ -70,6 +70,7 @@ extern int lg2_remote(git_repository *repo, int argc, char **argv); extern int lg2_rev_list(git_repository *repo, int argc, char **argv); extern int lg2_rev_parse(git_repository *repo, int argc, char **argv); extern int lg2_show_index(git_repository *repo, int argc, char **argv); +extern int lg2_stash(git_repository *repo, int argc, char **argv); extern int lg2_status(git_repository *repo, int argc, char **argv); extern int lg2_tag(git_repository *repo, int argc, char **argv); diff --git a/examples/lg2.c b/examples/lg2.c index 4ee0110a6..f1a8843d2 100644 --- a/examples/lg2.c +++ b/examples/lg2.c @@ -31,6 +31,7 @@ struct { { "rev-list", lg2_rev_list, 1 }, { "rev-parse", lg2_rev_parse, 1 }, { "show-index", lg2_show_index, 0 }, + { "stash", lg2_stash, 1 }, { "status", lg2_status, 1 }, { "tag", lg2_tag, 1 }, }; diff --git a/examples/stash.c b/examples/stash.c new file mode 100644 index 000000000..8142439c7 --- /dev/null +++ b/examples/stash.c @@ -0,0 +1,157 @@ +/* + * libgit2 "stash" example - shows how to use the stash API + * + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include <stdarg.h> + +#include "common.h" + +enum subcmd { + SUBCMD_APPLY, + SUBCMD_LIST, + SUBCMD_POP, + SUBCMD_PUSH +}; + +struct opts { + enum subcmd cmd; + int argc; + char **argv; +}; + +static void usage(const char *fmt, ...) +{ + va_list ap; + + fputs("usage: git stash list\n", stderr); + fputs(" or: git stash ( pop | apply )\n", stderr); + fputs(" or: git stash [push]\n", stderr); + fputs("\n", stderr); + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(1); +} + +static void parse_subcommand(struct opts *opts, int argc, char *argv[]) +{ + char *arg = (argc < 2) ? "push" : argv[1]; + enum subcmd cmd; + + if (!strcmp(arg, "apply")) { + cmd = SUBCMD_APPLY; + } else if (!strcmp(arg, "list")) { + cmd = SUBCMD_LIST; + } else if (!strcmp(arg, "pop")) { + cmd = SUBCMD_POP; + } else if (!strcmp(arg, "push")) { + cmd = SUBCMD_PUSH; + } else { + usage("invalid command %s", arg); + return; + } + + opts->cmd = cmd; + opts->argc = (argc < 2) ? argc - 1 : argc - 2; + opts->argv = argv; +} + +static int cmd_apply(git_repository *repo, struct opts *opts) +{ + if (opts->argc) + usage("apply does not accept any parameters"); + + check_lg2(git_stash_apply(repo, 0, NULL), + "Unable to apply stash", NULL); + + return 0; +} + +static int list_stash_cb(size_t index, const char *message, + const git_oid *stash_id, void *payload) +{ + UNUSED(stash_id); + UNUSED(payload); + printf("stash@{%"PRIuZ"}: %s\n", index, message); + return 0; +} + +static int cmd_list(git_repository *repo, struct opts *opts) +{ + if (opts->argc) + usage("list does not accept any parameters"); + + check_lg2(git_stash_foreach(repo, list_stash_cb, NULL), + "Unable to list stashes", NULL); + + return 0; +} + +static int cmd_push(git_repository *repo, struct opts *opts) +{ + git_signature *signature; + git_commit *stash; + git_oid stashid; + + if (opts->argc) + usage("push does not accept any parameters"); + + check_lg2(git_signature_default(&signature, repo), + "Unable to get signature", NULL); + check_lg2(git_stash_save(&stashid, repo, signature, NULL, GIT_STASH_DEFAULT), + "Unable to save stash", NULL); + check_lg2(git_commit_lookup(&stash, repo, &stashid), + "Unable to lookup stash commit", NULL); + + printf("Saved working directory %s\n", git_commit_summary(stash)); + + git_signature_free(signature); + git_commit_free(stash); + + return 0; +} + +static int cmd_pop(git_repository *repo, struct opts *opts) +{ + if (opts->argc) + usage("pop does not accept any parameters"); + + check_lg2(git_stash_pop(repo, 0, NULL), + "Unable to pop stash", NULL); + + printf("Dropped refs/stash@{0}\n"); + + return 0; +} + +int lg2_stash(git_repository *repo, int argc, char *argv[]) +{ + struct opts opts = { 0 }; + + parse_subcommand(&opts, argc, argv); + + switch (opts.cmd) { + case SUBCMD_APPLY: + return cmd_apply(repo, &opts); + case SUBCMD_LIST: + return cmd_list(repo, &opts); + case SUBCMD_PUSH: + return cmd_push(repo, &opts); + case SUBCMD_POP: + return cmd_pop(repo, &opts); + } + + return -1; +} diff --git a/src/stash.c b/src/stash.c index 2d61e6828..aa3cecf6e 100644 --- a/src/stash.c +++ b/src/stash.c @@ -398,28 +398,23 @@ static int commit_worktree( git_commit *b_commit, git_commit *u_commit) { - int error = 0; - git_tree *w_tree = NULL, *i_tree = NULL; - git_index *i_index = NULL; - const git_commit *parents[] = { NULL, NULL, NULL }; - int ignorecase; + const git_commit *parents[] = { NULL, NULL, NULL }; + git_index *i_index = NULL, *r_index = NULL; + git_tree *w_tree = NULL; + int error = 0, ignorecase; parents[0] = b_commit; parents[1] = i_commit; parents[2] = u_commit; - if ((error = git_commit_tree(&i_tree, i_commit)) < 0) - goto cleanup; - - if ((error = git_index_new(&i_index)) < 0 || - (error = git_repository__configmap_lookup(&ignorecase, repo, GIT_CONFIGMAP_IGNORECASE)) < 0) + if ((error = git_repository_index(&r_index, repo) < 0) || + (error = git_index_new(&i_index)) < 0 || + (error = git_index__fill(i_index, &r_index->entries) < 0) || + (error = git_repository__configmap_lookup(&ignorecase, repo, GIT_CONFIGMAP_IGNORECASE)) < 0) goto cleanup; git_index__set_ignore_case(i_index, ignorecase); - if ((error = git_index_read_tree(i_index, i_tree)) < 0) - goto cleanup; - if ((error = build_workdir_tree(&w_tree, repo, i_index, b_commit)) < 0) goto cleanup; @@ -436,9 +431,9 @@ static int commit_worktree( parents); cleanup: - git_tree_free(i_tree); git_tree_free(w_tree); git_index_free(i_index); + git_index_free(r_index); return error; } |