Skip to content

Commit 72b99c5

Browse files
pks-tgitster
authored andcommitted
replay: extract logic to pick commits
We're about to add a new git-history(1) command that will reuse some of the same infrastructure as git-replay(1). To prepare for this, extract the logic to pick a commit into a new "replay.c" file so that it can be shared between both commands. Rename the function to have a "replay_" prefix to clearly indicate its subsystem. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 0da3fb3 commit 72b99c5

File tree

5 files changed

+143
-107
lines changed

5 files changed

+143
-107
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,7 @@ LIB_OBJS += reftable/tree.o
12611261
LIB_OBJS += reftable/writer.o
12621262
LIB_OBJS += remote.o
12631263
LIB_OBJS += replace-object.o
1264+
LIB_OBJS += replay.o
12641265
LIB_OBJS += repo-settings.o
12651266
LIB_OBJS += repository.o
12661267
LIB_OBJS += rerere.o

builtin/replay.c

Lines changed: 3 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* "git replay" builtin command
33
*/
44

5-
#define USE_THE_REPOSITORY_VARIABLE
65
#define DISABLE_SIGN_COMPARE_WARNINGS
76

87
#include "git-compat-util.h"
@@ -16,6 +15,7 @@
1615
#include "object-name.h"
1716
#include "parse-options.h"
1817
#include "refs.h"
18+
#include "replay.h"
1919
#include "revision.h"
2020
#include "strmap.h"
2121
#include <oidset.h>
@@ -26,13 +26,6 @@ enum ref_action_mode {
2626
REF_ACTION_PRINT,
2727
};
2828

29-
static const char *short_commit_name(struct repository *repo,
30-
struct commit *commit)
31-
{
32-
return repo_find_unique_abbrev(repo, &commit->object.oid,
33-
DEFAULT_ABBREV);
34-
}
35-
3629
static struct commit *peel_committish(struct repository *repo, const char *name)
3730
{
3831
struct object *obj;
@@ -45,59 +38,6 @@ static struct commit *peel_committish(struct repository *repo, const char *name)
4538
OBJ_COMMIT);
4639
}
4740

48-
static char *get_author(const char *message)
49-
{
50-
size_t len;
51-
const char *a;
52-
53-
a = find_commit_header(message, "author", &len);
54-
if (a)
55-
return xmemdupz(a, len);
56-
57-
return NULL;
58-
}
59-
60-
static struct commit *create_commit(struct repository *repo,
61-
struct tree *tree,
62-
struct commit *based_on,
63-
struct commit *parent)
64-
{
65-
struct object_id ret;
66-
struct object *obj = NULL;
67-
struct commit_list *parents = NULL;
68-
char *author;
69-
char *sign_commit = NULL; /* FIXME: cli users might want to sign again */
70-
struct commit_extra_header *extra = NULL;
71-
struct strbuf msg = STRBUF_INIT;
72-
const char *out_enc = get_commit_output_encoding();
73-
const char *message = repo_logmsg_reencode(repo, based_on,
74-
NULL, out_enc);
75-
const char *orig_message = NULL;
76-
const char *exclude_gpgsig[] = { "gpgsig", NULL };
77-
78-
commit_list_insert(parent, &parents);
79-
extra = read_commit_extra_headers(based_on, exclude_gpgsig);
80-
find_commit_subject(message, &orig_message);
81-
strbuf_addstr(&msg, orig_message);
82-
author = get_author(message);
83-
reset_ident_date();
84-
if (commit_tree_extended(msg.buf, msg.len, &tree->object.oid, parents,
85-
&ret, author, NULL, sign_commit, extra)) {
86-
error(_("failed to write commit object"));
87-
goto out;
88-
}
89-
90-
obj = parse_object(repo, &ret);
91-
92-
out:
93-
repo_unuse_commit_buffer(the_repository, based_on, message);
94-
free_commit_extra_headers(extra);
95-
free_commit_list(parents);
96-
strbuf_release(&msg);
97-
free(author);
98-
return (struct commit *)obj;
99-
}
100-
10141
struct ref_info {
10242
struct commit *onto;
10343
struct strset positive_refs;
@@ -246,50 +186,6 @@ static void determine_replay_mode(struct repository *repo,
246186
strset_clear(&rinfo.positive_refs);
247187
}
248188

249-
static struct commit *mapped_commit(kh_oid_map_t *replayed_commits,
250-
struct commit *commit,
251-
struct commit *fallback)
252-
{
253-
khint_t pos = kh_get_oid_map(replayed_commits, commit->object.oid);
254-
if (pos == kh_end(replayed_commits))
255-
return fallback;
256-
return kh_value(replayed_commits, pos);
257-
}
258-
259-
static struct commit *pick_regular_commit(struct repository *repo,
260-
struct commit *pickme,
261-
kh_oid_map_t *replayed_commits,
262-
struct commit *onto,
263-
struct merge_options *merge_opt,
264-
struct merge_result *result)
265-
{
266-
struct commit *base, *replayed_base;
267-
struct tree *pickme_tree, *base_tree;
268-
269-
base = pickme->parents->item;
270-
replayed_base = mapped_commit(replayed_commits, base, onto);
271-
272-
result->tree = repo_get_commit_tree(repo, replayed_base);
273-
pickme_tree = repo_get_commit_tree(repo, pickme);
274-
base_tree = repo_get_commit_tree(repo, base);
275-
276-
merge_opt->branch1 = short_commit_name(repo, replayed_base);
277-
merge_opt->branch2 = short_commit_name(repo, pickme);
278-
merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2);
279-
280-
merge_incore_nonrecursive(merge_opt,
281-
base_tree,
282-
result->tree,
283-
pickme_tree,
284-
result);
285-
286-
free((char*)merge_opt->ancestor);
287-
merge_opt->ancestor = NULL;
288-
if (!result->clean)
289-
return NULL;
290-
return create_commit(repo, result->tree, pickme, replayed_base);
291-
}
292-
293189
static enum ref_action_mode parse_ref_action_mode(const char *ref_action, const char *source)
294190
{
295191
if (!ref_action || !strcmp(ref_action, "update"))
@@ -495,8 +391,8 @@ int cmd_replay(int argc,
495391
if (commit->parents->next)
496392
die(_("replaying merge commits is not supported yet!"));
497393

498-
last_commit = pick_regular_commit(repo, commit, replayed_commits,
499-
onto, &merge_opt, &result);
394+
last_commit = replay_pick_regular_commit(repo, commit, replayed_commits,
395+
onto, &merge_opt, &result);
500396
if (!last_commit)
501397
break;
502398

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ libgit_sources = [
464464
'reftable/writer.c',
465465
'remote.c',
466466
'replace-object.c',
467+
'replay.c',
467468
'repo-settings.c',
468469
'repository.c',
469470
'rerere.c',

replay.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#define USE_THE_REPOSITORY_VARIABLE
2+
3+
#include "git-compat-util.h"
4+
#include "commit.h"
5+
#include "environment.h"
6+
#include "gettext.h"
7+
#include "ident.h"
8+
#include "object.h"
9+
#include "object-name.h"
10+
#include "replay.h"
11+
#include "tree.h"
12+
13+
static const char *short_commit_name(struct repository *repo,
14+
struct commit *commit)
15+
{
16+
return repo_find_unique_abbrev(repo, &commit->object.oid,
17+
DEFAULT_ABBREV);
18+
}
19+
20+
static char *get_author(const char *message)
21+
{
22+
size_t len;
23+
const char *a;
24+
25+
a = find_commit_header(message, "author", &len);
26+
if (a)
27+
return xmemdupz(a, len);
28+
29+
return NULL;
30+
}
31+
32+
struct commit *replay_create_commit(struct repository *repo,
33+
struct tree *tree,
34+
struct commit *based_on,
35+
struct commit *parent)
36+
{
37+
struct object_id ret;
38+
struct object *obj = NULL;
39+
struct commit_list *parents = NULL;
40+
char *author;
41+
char *sign_commit = NULL; /* FIXME: cli users might want to sign again */
42+
struct commit_extra_header *extra = NULL;
43+
struct strbuf msg = STRBUF_INIT;
44+
const char *out_enc = get_commit_output_encoding();
45+
const char *message = repo_logmsg_reencode(repo, based_on,
46+
NULL, out_enc);
47+
const char *orig_message = NULL;
48+
const char *exclude_gpgsig[] = { "gpgsig", NULL };
49+
50+
commit_list_insert(parent, &parents);
51+
extra = read_commit_extra_headers(based_on, exclude_gpgsig);
52+
find_commit_subject(message, &orig_message);
53+
strbuf_addstr(&msg, orig_message);
54+
author = get_author(message);
55+
reset_ident_date();
56+
if (commit_tree_extended(msg.buf, msg.len, &tree->object.oid, parents,
57+
&ret, author, NULL, sign_commit, extra)) {
58+
error(_("failed to write commit object"));
59+
goto out;
60+
}
61+
62+
obj = parse_object(repo, &ret);
63+
64+
out:
65+
repo_unuse_commit_buffer(the_repository, based_on, message);
66+
free_commit_extra_headers(extra);
67+
free_commit_list(parents);
68+
strbuf_release(&msg);
69+
free(author);
70+
return (struct commit *)obj;
71+
}
72+
73+
static struct commit *mapped_commit(kh_oid_map_t *replayed_commits,
74+
struct commit *commit,
75+
struct commit *fallback)
76+
{
77+
khint_t pos = kh_get_oid_map(replayed_commits, commit->object.oid);
78+
if (pos == kh_end(replayed_commits))
79+
return fallback;
80+
return kh_value(replayed_commits, pos);
81+
}
82+
83+
struct commit *replay_pick_regular_commit(struct repository *repo,
84+
struct commit *pickme,
85+
kh_oid_map_t *replayed_commits,
86+
struct commit *onto,
87+
struct merge_options *merge_opt,
88+
struct merge_result *result)
89+
{
90+
struct commit *base, *replayed_base;
91+
struct tree *pickme_tree, *base_tree;
92+
93+
base = pickme->parents->item;
94+
replayed_base = mapped_commit(replayed_commits, base, onto);
95+
96+
result->tree = repo_get_commit_tree(repo, replayed_base);
97+
pickme_tree = repo_get_commit_tree(repo, pickme);
98+
base_tree = repo_get_commit_tree(repo, base);
99+
100+
merge_opt->branch1 = short_commit_name(repo, replayed_base);
101+
merge_opt->branch2 = short_commit_name(repo, pickme);
102+
merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2);
103+
104+
merge_incore_nonrecursive(merge_opt,
105+
base_tree,
106+
result->tree,
107+
pickme_tree,
108+
result);
109+
110+
free((char*)merge_opt->ancestor);
111+
merge_opt->ancestor = NULL;
112+
if (!result->clean)
113+
return NULL;
114+
return replay_create_commit(repo, result->tree, pickme, replayed_base);
115+
}

replay.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef REPLAY_H
2+
#define REPLAY_H
3+
4+
#include "khash.h"
5+
#include "merge-ort.h"
6+
#include "repository.h"
7+
8+
struct commit;
9+
struct tree;
10+
11+
struct commit *replay_create_commit(struct repository *repo,
12+
struct tree *tree,
13+
struct commit *based_on,
14+
struct commit *parent);
15+
16+
struct commit *replay_pick_regular_commit(struct repository *repo,
17+
struct commit *pickme,
18+
kh_oid_map_t *replayed_commits,
19+
struct commit *onto,
20+
struct merge_options *merge_opt,
21+
struct merge_result *result);
22+
23+
#endif

0 commit comments

Comments
 (0)