Skip to content

Commit 3200228

Browse files
committed
Add merge commit (draft)
1 parent 69b86a4 commit 3200228

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

src/subcommand/merge_subcommand.cpp

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
#include <git2/types.h>
33

44
#include "merge_subcommand.hpp"
5-
// #include "../wrapper/repository_wrapper.hpp"
5+
#include <iostream>
66

77

88
merge_subcommand::merge_subcommand(const libgit2_object&, CLI::App& app)
99
{
1010
auto *sub = app.add_subcommand("merge", "Join two or more development histories together");
1111

1212
sub->add_option("<branch>", m_branches_to_merge, "Branch(es) to merge");
13+
sub->add_flag("--no-ff", m_no_ff, "");
14+
sub->add_flag("--commit", m_commit, "Perform the merge and commit the result. This option can be used to override --no-commit.");
15+
sub->add_flag("--no-commit", m_no_commit, "With --no-commit perform the merge and stop just before creating a merge commit, to give the user a chance to inspect and further tweak the merge result before committing. \nNote that fast-forward updates do not create a merge commit and therefore there is no way to stop those merges with --no-commit. Thus, if you want to ensure your branch is not changed or updated by the merge command, use --no-ff with --no-commit.");
1316

1417
sub->callback([this]() { this->run(); });
1518
}
@@ -54,6 +57,60 @@ void perform_fastforward(repository_wrapper& repo, const git_oid target_oid, int
5457
target_ref.write_new_ref(target_oid);
5558
}
5659

60+
static void create_merge_commit(repository_wrapper repo, index_wrapper index, std::vector<std::string> m_branches_to_merge,
61+
annotated_commit_list_wrapper commits_to_merge, size_t num_commits_to_merge) // std::vector<annotated_commit_wrapper> commits_to_merge
62+
{
63+
auto head_ref = repo.head();
64+
auto merge_ref = repo.find_reference_dwim(m_branches_to_merge.front());
65+
// if (ref)
66+
// {
67+
// auto merge_ref = std::move(ref).value();
68+
// }
69+
auto merge_commit = repo.resolve_local_ref(m_branches_to_merge.front()).value();
70+
71+
std::vector<commit_wrapper> parents_list;
72+
parents_list.reserve(num_commits_to_merge + 1);
73+
parents_list.push_back(std::move(head_ref.peel<commit_wrapper>()));
74+
for (size_t i=0; i<num_commits_to_merge; ++i)
75+
{
76+
std::cout << commits_to_merge[i];
77+
parents_list.push_back(repo.find_commit(commits_to_merge[i]->oid()));
78+
}
79+
auto parents = commit_list_wrapper(std::move(parents_list));
80+
81+
auto author_committer_sign = signature_wrapper::get_default_signature_from_env(repo);
82+
std::string author_name;
83+
author_name = author_committer_sign.first.name();
84+
std::string author_email;
85+
author_email = author_committer_sign.first.email();
86+
auto author_committer_sign_now = signature_wrapper::signature_now(author_name, author_email, author_name, author_email);
87+
88+
std::string msg_target = NULL;
89+
if (merge_ref)
90+
{
91+
msg_target = merge_ref->short_name();
92+
}
93+
else
94+
{
95+
msg_target = git_oid_tostr_s(&(merge_commit.oid()));
96+
}
97+
98+
std::string msg;
99+
msg = "Merge ";
100+
if (merge_ref)
101+
{
102+
msg.append("branch ");
103+
}
104+
else
105+
{
106+
msg.append("commit ");
107+
}
108+
msg.append(msg_target);
109+
std::cout << msg << std::endl;
110+
111+
repo.create_commit(author_committer_sign_now, msg, std::optional<commit_list_wrapper>(std::move(parents)));
112+
}
113+
57114
void merge_subcommand::run()
58115
{
59116
auto directory = get_current_git_path();
@@ -97,4 +154,41 @@ void merge_subcommand::run()
97154
assert(num_commits_to_merge == 1);
98155
perform_fastforward(repo, target_oid, (analysis & GIT_MERGE_ANALYSIS_UNBORN));
99156
}
157+
else if (analysis & GIT_MERGE_ANALYSIS_NORMAL)
158+
{
159+
std::cout << "OR THERE ?" << std::endl;
160+
git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
161+
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
162+
163+
merge_opts.flags = 0;
164+
merge_opts.file_flags = GIT_MERGE_FILE_STYLE_DIFF3;
165+
166+
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE|GIT_CHECKOUT_ALLOW_CONFLICTS;
167+
168+
if (preference & GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY)
169+
{
170+
std::cout << "Fast-forward is preferred, but only a merge is possible\n" << std::endl;
171+
}
172+
173+
throw_if_error(git_merge(repo,
174+
(const git_annotated_commit**)c_commits_to_merge,
175+
num_commits_to_merge,
176+
&merge_opts,
177+
&checkout_opts));
178+
}
179+
180+
index_wrapper index = repo.make_index();
181+
182+
if (git_index_has_conflicts(index))
183+
{
184+
std::cout << "WAAAAAAAAAAAARRRRRR !!!!!!!!!" << std::endl;
185+
/* Handle conflicts */
186+
// output_conflicts(index);
187+
}
188+
else if (!m_no_commit)
189+
{
190+
std::cout << "???" << std::endl;
191+
create_merge_commit(repo, index, m_branches_to_merge, commits_to_merge, num_commits_to_merge);
192+
printf("Merge made\n");
193+
}
100194
}

src/subcommand/merge_subcommand.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,7 @@ class merge_subcommand
1717
annotated_commit_list_wrapper resolve_heads(const repository_wrapper& repo);
1818

1919
std::vector<std::string> m_branches_to_merge;
20+
bool m_no_ff = false;
21+
bool m_commit = false;
22+
bool m_no_commit = false;
2023
};

0 commit comments

Comments
 (0)