28
#include "log-tree.h"
29
#include "diffcore.h"
30
#include "reflog.h"
31
+#include "reflog-walk.h"
32
#include "add-interactive.h"
33
+#include "oid-array.h"
34
+#include "commit.h"
35
36
#define INCLUDE_ALL_FILES 2
37
59
" [-u | --include-untracked] [-a | --all] [<message>]")
60
#define BUILTIN_STASH_CREATE_USAGE \
61
N_("git stash create [<message>]")
62
+#define BUILTIN_STASH_EXPORT_USAGE \
63
+ N_("git stash export (--print | --to-ref <ref>) [<stash>...]")
64
#define BUILTIN_STASH_CLEAR_USAGE \
65
"git stash clear"
66
76
BUILTIN_STASH_CLEAR_USAGE,
77
BUILTIN_STASH_CREATE_USAGE,
78
BUILTIN_STASH_STORE_USAGE,
79
+ BUILTIN_STASH_EXPORT_USAGE,
80
NULL
81
};
82
130
NULL
131
};
132
133
+static const char * const git_stash_export_usage[] = {
134
+ BUILTIN_STASH_EXPORT_USAGE,
135
+ NULL
136
+};
137
+
138
+
139
static const char ref_stash[] = "refs/stash";
140
static struct strbuf stash_index_path = STRBUF_INIT;
141
172
strbuf_release(&info->revision);
173
}
174
175
+static int check_stash_topology(struct repository *r, struct commit *stash)
176
+{
177
+ struct commit *p1, *p2, *p3 = NULL;
178
+
179
+ /* stash must have two or three parents */
180
+ if (!stash->parents || !stash->parents->next ||
181
+ (stash->parents->next->next && stash->parents->next->next->next))
182
+ return -1;
183
+ p1 = stash->parents->item;
184
+ p2 = stash->parents->next->item;
185
+ if (stash->parents->next->next)
186
+ p3 = stash->parents->next->next->item;
187
+ if (repo_parse_commit(r, p1) || repo_parse_commit(r, p2) ||
188
+ (p3 && repo_parse_commit(r, p3)))
189
+ return -1;
190
+ /* p2 must have a single parent, p3 must have no parents */
191
+ if (!p2->parents || p2->parents->next || (p3 && p3->parents))
192
+ return -1;
193
+ if (repo_parse_commit(r, p2->parents->item))
194
+ return -1;
195
+ /* p2^1 must equal p1 */
196
+ if (!oideq(&p1->object.oid, &p2->parents->item->object.oid))
197
+ return -1;
198
+
199
+ return 0;
200
+}
201
+
202
static void assert_stash_like(struct stash_info *info, const char *revision)
203
{
204
if (get_oidf(&info->b_commit, "%s^1", revision) ||
1934
return ret;
1935
}
1936
1937
+static int write_commit_with_parents(struct repository *r,
1938
+ struct object_id *out,
1939
+ const struct object_id *oid,
1940
+ struct commit_list *parents)
1941
+{
1942
+ size_t author_len, committer_len;
1943
+ struct commit *this;
1944
+ const char *orig_author, *orig_committer;
1945
+ char *author = NULL, *committer = NULL;
1946
+ const char *buffer;
1947
+ unsigned long bufsize;
1948
+ const char *p;
1949
+ struct strbuf msg = STRBUF_INIT;
1950
+ int ret = 0;
1951
+ struct ident_split id;
1952
+
1953
+ this = lookup_commit_reference(r, oid);
1954
+ buffer = repo_get_commit_buffer(r, this, &bufsize);
1955
+ orig_author = find_commit_header(buffer, "author", &author_len);
1956
+ orig_committer = find_commit_header(buffer, "committer", &committer_len);
1957
+
1958
+ if (!orig_author || !orig_committer) {
1959
+ ret = error(_("cannot parse commit %s"), oid_to_hex(oid));
1960
+ goto out;
1961
+ }
1962
+
1963
+ if (split_ident_line(&id, orig_author, author_len) < 0 ||
1964
+ split_ident_line(&id, orig_committer, committer_len) < 0) {
1965
+ ret = error(_("invalid author or committer for %s"), oid_to_hex(oid));
1966
+ goto out;
1967
+ }
1968
+
1969
+ p = strstr(buffer, "\n\n");
1970
+ strbuf_addstr(&msg, "git stash: ");
1971
+
1972
+ if (p)
1973
+ strbuf_add(&msg, p + 2, bufsize - (p + 2 - buffer));
1974
+ strbuf_complete_line(&msg);
1975
+
1976
+ author = xmemdupz(orig_author, author_len);
1977
+ committer = xmemdupz(orig_committer, committer_len);
1978
+
1979
+ if (commit_tree_extended(msg.buf, msg.len,
1980
+ r->hash_algo->empty_tree, parents,
1981
+ out, author, committer,
1982
+ NULL, NULL)) {
1983
+ ret = error(_("could not write commit"));
1984
+ goto out;
1985
+ }
1986
+out:
1987
+ strbuf_release(&msg);
1988
+ repo_unuse_commit_buffer(r, this, buffer);
1989
+ free(author);
1990
+ free(committer);
1991
+ return ret;
1992
+}
1993
+
1994
+struct stash_entry_data {
1995
+ struct repository *r;
1996
+ struct commit_list **items;
1997
+ size_t count;
1998
+};
1999
+
2000
+static int collect_stash_entries(struct object_id *old_oid UNUSED,
2001
+ struct object_id *new_oid,
2002
+ const char *committer UNUSED,
2003
+ timestamp_t timestamp UNUSED,
2004
+ int tz UNUSED, const char *msg UNUSED,
2005
+ void *cb_data)
2006
+{
2007
+ struct stash_entry_data *data = cb_data;
2008
+ struct commit *stash;
2009
+
2010
+ data->count++;
2011
+ stash = lookup_commit_reference(data->r, new_oid);
2012
+ if (!stash || check_stash_topology(data->r, stash)) {
2013
+ return error(_("%s does not look like a stash commit"),
2014
+ oid_to_hex(new_oid));
2015
+ }
2016
+ data->items = commit_list_append(stash, data->items);
2017
+ return 0;
2018
+}
2019
+
2020
+static int do_export_stash(struct repository *r,
2021
+ const char *ref,
2022
+ int argc,
2023
+ const char **argv)
2024
+{
2025
+ struct object_id base;
2026
+ struct object_context unused;
2027
+ struct commit *prev;
2028
+ struct commit_list *items = NULL, **iter = &items, *cur;
2029
+ int res = 0;
2030
+ int i;
2031
+ struct strbuf revision = STRBUF_INIT;
2032
+ const char *author, *committer;
2033
+
2034
+ /*
2035
+ * This is an arbitrary, fixed date, specifically the one used by git
2036
+ * format-patch. The goal is merely to produce reproducible output.
2037
+ */
2038
+ prepare_fallback_ident("git stash", "git@stash");
2039
+ author = fmt_ident("git stash", "git@stash", WANT_BLANK_IDENT,
2040
+ "2001-09-17T00:00:00Z", 0);
2041
+ committer = fmt_ident("git stash", "git@stash", WANT_BLANK_IDENT,
2042
+ "2001-09-17T00:00:00Z", 0);
2043
+
2044
+ /* First, we create a single empty commit. */
2045
+ if (commit_tree_extended("", 0, r->hash_algo->empty_tree, NULL,
2046
+ &base, author, committer, NULL, NULL))
2047
+ return error(_("unable to write base commit"));
2048
+
2049
+ prev = lookup_commit_reference(r, &base);
2050
+
2051
+ if (argc) {
2052
+ /*
2053
+ * Find each specified stash, and load data into the array.
2054
+ */
2055
+ for (i = 0; i < argc; i++) {
2056
+ struct object_id oid;
2057
+ struct commit *stash;
2058
+
2059
+ if (parse_stash_revision(&revision, argv[i], 1) ||
2060
+ get_oid_with_context(r, revision.buf,
2061
+ GET_OID_QUIETLY | GET_OID_GENTLY,
2062
+ &oid, &unused)) {
2063
+ res = error(_("unable to find stash entry %s"), argv[i]);
2064
+ goto out;
2065
+ }
2066
+
2067
+ stash = lookup_commit_reference(r, &oid);
2068
+ if (!stash || check_stash_topology(r, stash)) {
2069
+ res = error(_("%s does not look like a stash commit"),
2070
+ revision.buf);
2071
+ goto out;
2072
+ }
2073
+ iter = commit_list_append(stash, iter);
2074
+ }
2075
+ } else {
2076
+ /*
2077
+ * Walk the reflog, finding each stash entry, and load data into the
2078
+ * array.
2079
+ */
2080
+ struct stash_entry_data cb_data = {
2081
+ .r = r, .items = iter,
2082
+ };
2083
+ if (refs_for_each_reflog_ent_reverse(get_main_ref_store(r),
2084
+ "refs/stash",
2085
+ collect_stash_entries,
2086
+ &cb_data) && cb_data.count)
2087
+ goto out;
2088
+ }
2089
+
2090
+ /*
2091
+ * Now, create a set of commits identical to the regular stash commits,
2092
+ * but where their first parents form a chain to our original empty
2093
+ * base commit.
2094
+ */
2095
+ items = reverse_commit_list(items);
2096
+ for (cur = items; cur; cur = cur->next) {
2097
+ struct commit_list *parents = NULL;
2098
+ struct commit_list **next = &parents;
2099
+ struct object_id out;
2100
+ struct commit *stash = cur->item;
2101
+
2102
+ next = commit_list_append(prev, next);
2103
+ next = commit_list_append(stash, next);
2104
+ res = write_commit_with_parents(r, &out, &stash->object.oid, parents);
2105
+ free_commit_list(parents);
2106
+ if (res)
2107
+ goto out;
2108
+ prev = lookup_commit_reference(r, &out);
2109
+ }
2110
+ if (ref)
2111
+ refs_update_ref(get_main_ref_store(r), NULL, ref,
2112
+ &prev->object.oid, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
2113
+ else
2114
+ puts(oid_to_hex(&prev->object.oid));
2115
+out:
2116
+ strbuf_release(&revision);
2117
+ free_commit_list(items);
2118
+
2119
+ return res;
2120
+}
2121
+
2122
+enum export_action {
2123
+ ACTION_NONE,
2124
+ ACTION_PRINT,
2125
+ ACTION_TO_REF,
2126
+};
2127
+
2128
+static int export_stash(int argc,
2129
+ const char **argv,
2130
+ const char *prefix,
2131
+ struct repository *repo)
2132
+{
2133
+ const char *ref = NULL;
2134
+ enum export_action action = ACTION_NONE;
2135
+ struct option options[] = {
2136
+ OPT_CMDMODE(0, "print", &action,
2137
+ N_("print the object ID instead of writing it to a ref"),
2138
+ ACTION_PRINT),
2139
+ OPT_STRING(0, "to-ref", &ref, "ref",
2140
+ N_("save the data to the given ref")),
2141
+ OPT_END()
2142
+ };
2143
+
2144
+ argc = parse_options(argc, argv, prefix, options,
2145
+ git_stash_export_usage,
2146
+ PARSE_OPT_KEEP_DASHDASH);
2147
+
2148
+ if (ref && action == ACTION_NONE)
2149
+ action = ACTION_TO_REF;
2150
+
2151
+ if (action == ACTION_NONE || (ref && action == ACTION_PRINT))
2152
+ return error(_("exactly one of --print and --to-ref is required"));
2153
+
2154
+ return do_export_stash(repo, ref, argc, argv);
2155
+}
2156
+
2157
int cmd_stash(int argc,
2158
const char **argv,
2159
const char *prefix,
2174
OPT_SUBCOMMAND("store", &fn, store_stash),
2175
OPT_SUBCOMMAND("create", &fn, create_stash),
2176
OPT_SUBCOMMAND("push", &fn, push_stash_unassumed),
2177
+ OPT_SUBCOMMAND("export", &fn, export_stash),
2178
OPT_SUBCOMMAND_F("save", &fn, save_stash, PARSE_OPT_NOCOMPLETE),
2179
OPT_END()
2180
};