1mod amend;
4mod bug_report;
5mod hide;
6mod repair;
7mod restack;
8mod snapshot;
9mod sync;
10mod wrap;
11
12use git_branchless_invoke::CommandContext;
13use lib::core::rewrite::MergeConflictRemediation;
14
15use lib::util::ExitCode;
16use lib::{core::gc, util::EyreExitOr};
17
18use git_branchless_opts::{
19 rewrite_args, Command, Opts, ResolveRevsetOptions, SnapshotSubcommand, WrappedCommand,
20};
21use lib::git::GitRunInfo;
22
23fn command_main(ctx: CommandContext, opts: Opts) -> EyreExitOr<()> {
24 let CommandContext {
25 effects,
26 git_run_info,
27 } = ctx.clone();
28 let Opts {
29 global_args: _,
30 command,
31 } = opts;
32
33 let exit_code = match command {
34 Command::Amend {
35 move_options,
36 reparent,
37 } => amend::amend(
38 &effects,
39 &git_run_info,
40 &ResolveRevsetOptions::default(),
41 &move_options,
42 reparent,
43 )?,
44
45 Command::BugReport => bug_report::bug_report(&effects, &git_run_info)?,
46
47 Command::Difftool(opts) => {
48 let result = scm_diff_editor::run(opts);
49 match result {
50 Ok(()) | Err(scm_diff_editor::Error::Cancelled) => Ok(()),
51 Err(err) => {
52 eprintln!("Error: {err}");
53 Err(ExitCode(1))
54 }
55 }
56 }
57
58 Command::Switch { switch_options } => {
59 git_branchless_navigation::switch(&effects, &git_run_info, &switch_options)?
60 }
61
62 Command::Gc => {
63 gc::gc(&effects)?;
64 Ok(())
65 }
66
67 Command::Hook(args) => git_branchless_hook::command_main(ctx, args)?,
68
69 Command::Hide {
70 revsets,
71 resolve_revset_options,
72 no_delete_branches,
73 recursive,
74 } => hide::hide(
75 &effects,
76 &git_run_info,
77 revsets,
78 &resolve_revset_options,
79 no_delete_branches,
80 recursive,
81 )?,
82
83 Command::Init(args) => git_branchless_init::command_main(ctx, args)?,
84
85 Command::InstallManPages(args) => {
86 git_branchless_init::command_install_man_pages(ctx, args)?
87 }
88
89 Command::Move {
90 source,
91 dest,
92 base,
93 exact,
94 resolve_revset_options,
95 move_options,
96 fixup,
97 insert,
98 } => git_branchless_move::r#move(
99 &effects,
100 &git_run_info,
101 source,
102 dest,
103 base,
104 exact,
105 &resolve_revset_options,
106 &move_options,
107 fixup,
108 insert,
109 )?,
110
111 Command::Next {
112 traverse_commits_options,
113 } => git_branchless_navigation::traverse_commits(
114 &effects,
115 &git_run_info,
116 git_branchless_navigation::Command::Next,
117 &traverse_commits_options,
118 )?,
119
120 Command::Prev {
121 traverse_commits_options,
122 } => git_branchless_navigation::traverse_commits(
123 &effects,
124 &git_run_info,
125 git_branchless_navigation::Command::Prev,
126 &traverse_commits_options,
127 )?,
128
129 Command::Query(args) => git_branchless_query::command_main(ctx, args)?,
130
131 Command::Repair { dry_run } => repair::repair(&effects, dry_run)?,
132
133 Command::Restack {
134 revsets,
135 resolve_revset_options,
136 move_options,
137 } => restack::restack(
138 &effects,
139 &git_run_info,
140 revsets,
141 &resolve_revset_options,
142 &move_options,
143 MergeConflictRemediation::Retry,
144 )?,
145
146 Command::Record(args) => git_branchless_record::command_main(ctx, args)?,
147
148 Command::Reword {
149 revsets,
150 resolve_revset_options,
151 messages,
152 force_rewrite_public_commits,
153 discard,
154 commit_to_fixup,
155 } => {
156 let messages = if discard {
157 git_branchless_reword::InitialCommitMessages::Discard
158 } else if let Some(commit_to_fixup) = commit_to_fixup {
159 git_branchless_reword::InitialCommitMessages::FixUp(commit_to_fixup)
160 } else {
161 git_branchless_reword::InitialCommitMessages::Messages(messages)
162 };
163 git_branchless_reword::reword(
164 &effects,
165 revsets,
166 &resolve_revset_options,
167 messages,
168 &git_run_info,
169 force_rewrite_public_commits,
170 )?
171 }
172
173 Command::Smartlog(args) => git_branchless_smartlog::command_main(ctx, args)?,
174
175 Command::Snapshot { subcommand } => match subcommand {
176 SnapshotSubcommand::Create => snapshot::create(&effects, &git_run_info)?,
177 SnapshotSubcommand::Restore { snapshot_oid } => {
178 snapshot::restore(&effects, &git_run_info, snapshot_oid)?
179 }
180 },
181
182 Command::Submit(args) => git_branchless_submit::command_main(ctx, args)?,
183
184 Command::Sync {
185 pull,
186 move_options,
187 revsets,
188 resolve_revset_options,
189 } => sync::sync(
190 &effects,
191 &git_run_info,
192 pull,
193 &move_options,
194 revsets,
195 &resolve_revset_options,
196 )?,
197
198 Command::Test(args) => git_branchless_test::command_main(ctx, args)?,
199
200 Command::Undo { interactive, yes } => {
201 git_branchless_undo::undo(&effects, &git_run_info, interactive, yes)?
202 }
203
204 Command::Unhide {
205 revsets,
206 resolve_revset_options,
207 recursive,
208 } => hide::unhide(&effects, revsets, &resolve_revset_options, recursive)?,
209
210 Command::Wrap {
211 git_executable: explicit_git_executable,
212 command: WrappedCommand::WrappedCommand(args),
213 } => {
214 let git_run_info = match explicit_git_executable {
215 Some(path_to_git) => GitRunInfo {
216 path_to_git,
217 ..git_run_info
218 },
219 None => git_run_info,
220 };
221 wrap::wrap(&git_run_info, args.as_slice())?
222 }
223 };
224
225 Ok(exit_code)
226}
227
228pub fn main() {
230 color_eyre::install().expect("Could not install panic handler");
232 let args: Vec<_> = std::env::args_os().collect();
233 let args = rewrite_args(args);
234 let exit_code = git_branchless_invoke::do_main_and_drop_locals(command_main, args)
235 .expect("A fatal error occurred");
236 std::process::exit(exit_code);
237}