Skip to content

Commit 51b8436

Browse files
committed
refactor: move more git commands into the git module
1 parent d774b3e commit 51b8436

File tree

7 files changed

+96
-48
lines changed

7 files changed

+96
-48
lines changed

src/commands/branch_fetch.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use colored::Colorize as _;
44

55
use crate::config::{CommitId, Remote};
6-
use crate::git_high_level::git;
6+
use crate::git;
77
use crate::github_api;
88
use anyhow::anyhow;
99

@@ -27,10 +27,10 @@ pub async fn branch_fetch(
2727
);
2828

2929
// Attempt to cleanup after ourselves
30-
let _ = git(["remote", "remove", &info.remote.local_remote_alias]);
30+
let _ = git::remove_remote(&info.remote.local_remote_alias);
3131

3232
if checkout {
33-
git(["checkout", info.branch.local_branch_name.as_ref()]).map_err(|err| {
33+
git::checkout(info.branch.local_branch_name.as_ref()).map_err(|err| {
3434
anyhow!(
3535
"failed to check out branch {}:\n{err}",
3636
info.branch.local_branch_name

src/commands/gen_patch.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ use std::path::PathBuf;
55

66
use anyhow::bail;
77

8-
use crate::CONFIG_PATH;
98
use crate::config::{CommitId, PatchName};
10-
use crate::git_high_level::git;
119
use crate::utils::normalize_commit_msg;
10+
use crate::{CONFIG_PATH, git};
1211

1312
/// Generate patch `filename` at the given `Commit`
1413
pub fn gen_patch(commit: CommitId, filename: Option<PatchName>) -> anyhow::Result<()> {
@@ -24,7 +23,7 @@ pub fn gen_patch(commit: CommitId, filename: Option<PatchName>) -> anyhow::Resul
2423
// 2. otherwise use the commit message
2524
// 3. if all fails use the commit hash
2625
let patch_filename = filename.unwrap_or_else(|| {
27-
git(["log", "--format=%B", "--max-count=1", commit.as_ref()]).map_or_else(
26+
git::get_message_of_commit(commit.as_ref()).map_or_else(
2827
|_| {
2928
PatchName::try_new(commit.clone().into_inner().into()).expect("commit is not empty")
3029
},
@@ -43,15 +42,9 @@ pub fn gen_patch(commit: CommitId, filename: Option<PatchName>) -> anyhow::Resul
4342
bail!("invalid path: {patch_file_path:?}");
4443
};
4544

46-
if let Err(err) = git([
47-
"format-patch",
48-
"-1",
49-
&commit.clone().into_inner(),
50-
"--output",
51-
patch_file_path_str,
52-
]) {
45+
if let Err(err) = git::save_commit_as_patch(&commit, patch_file_path_str) {
5346
bail!(
54-
"Could not get patch output for patch {}\n{err}",
47+
"failed to get patch output for patch {}\n{err}",
5548
commit.into_inner()
5649
);
5750
}

src/commands/pr_fetch.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use anyhow::{Context as _, anyhow};
44
use colored::Colorize as _;
55

66
use crate::config::{BranchName, CommitId, PrNumber, Remote, RepoName, RepoOwner};
7-
use crate::git_high_level::git;
7+
use crate::git;
88
use crate::github_api::fetch_pull_request;
99

1010
/// Fetch the given `pr` of `remote` at `commit` and store it in local `branch`
@@ -23,7 +23,7 @@ pub async fn pr_fetch(
2323
// The user hasn't provided a custom remote, so we're going to try `origin`
2424
let remote = remote.map_or_else(
2525
|| -> anyhow::Result<Remote> {
26-
let remote = git(["remote", "get-url", "origin"])?;
26+
let remote = git::get_remote_url("origin")?;
2727
let err = || anyhow!("git command returned invalid remote: {remote}");
2828

2929
if remote.starts_with(GITHUB_REMOTE_PREFIX) && remote.ends_with(GITHUB_REMOTE_SUFFIX) {
@@ -79,10 +79,10 @@ pub async fn pr_fetch(
7979
);
8080

8181
// Attempt to cleanup after ourselves
82-
let _ = git(["remote", "remove", &info.remote.local_remote_alias]);
82+
let _ = git::remove_remote(&info.remote.local_remote_alias);
8383

8484
if checkout {
85-
if let Err(checkout_err) = git(["checkout", info.branch.local_branch_name.as_ref()]) {
85+
if let Err(checkout_err) = git::checkout(info.branch.local_branch_name.as_ref()) {
8686
log::error!(
8787
"Could not check out branch {}:\n{checkout_err}",
8888
info.branch.local_branch_name

src/commands/run.rs

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::path::PathBuf;
99
use anyhow::{anyhow, bail};
1010
use colored::Colorize as _;
1111

12-
use crate::git_high_level::{self, git};
12+
use crate::git_high_level;
1313
use crate::github_api::{self, Branch, Remote, RemoteBranch};
1414
use crate::utils::{display_link, with_uuid};
1515
use crate::{
@@ -212,7 +212,7 @@ pub async fn run(yes: bool) -> anyhow::Result<()> {
212212
}
213213

214214
if let Err(err) = fs::create_dir_all(git::ROOT.join(CONFIG_ROOT.as_str())) {
215-
git(["checkout", &previous_branch])?;
215+
git::checkout(&previous_branch)?;
216216

217217
git::delete_remote_and_branch(
218218
&info.remote.local_remote_alias,
@@ -243,16 +243,16 @@ pub async fn run(yes: bool) -> anyhow::Result<()> {
243243
.join(format!("{patch}.patch"));
244244

245245
if !file_name.exists() {
246-
log::warn!("Could not find patch {patch}, skipping");
246+
log::error!("failed to find patch {patch}, skipping");
247247
continue;
248248
}
249249

250-
if let Err(err) = git(["am", "--keep-cr", "--signoff", &file_name.to_string_lossy()]) {
251-
git(["am", "--abort"])?;
252-
return Err(anyhow!("Could not apply patch {patch}, skipping\n{err}"));
250+
if let Err(err) = git::apply_patch(&file_name) {
251+
log::error!("failed to apply patch {patch}, skipping\n{err}");
252+
continue;
253253
}
254254

255-
let last_commit_message = git(["log", "-1", "--format=%B"])?;
255+
let last_commit_message = git::last_commit_message()?;
256256

257257
log::info!(
258258
"Applied patch {patch} {}",
@@ -265,12 +265,12 @@ pub async fn run(yes: bool) -> anyhow::Result<()> {
265265
);
266266
}
267267

268-
git(["add", CONFIG_ROOT.as_str()])?;
268+
git::add(CONFIG_ROOT.as_str())?;
269269
git::commit("restore configuration files")?;
270270

271271
let temporary_branch = with_uuid("temp-branch");
272272

273-
git(["switch", "--create", &temporary_branch])?;
273+
git::create_branch(&temporary_branch)?;
274274

275275
git::delete_remote_and_branch(
276276
&info.remote.local_remote_alias,
@@ -283,16 +283,7 @@ pub async fn run(yes: bool) -> anyhow::Result<()> {
283283
config.local_branch.as_ref().cyan()
284284
)
285285
{
286-
// forcefully renames the branch we are currently on into the branch specified
287-
// by the user. WARNING: this is a destructive action which erases the
288-
// original branch
289-
git([
290-
"branch",
291-
"--move",
292-
"--force",
293-
&temporary_branch,
294-
config.local_branch.as_ref(),
295-
])?;
286+
git::rename_branch(&temporary_branch, config.local_branch.as_ref())?;
296287
if yes {
297288
log::info!(
298289
"Automatically overwrote branch {} since you supplied the {} flag",

src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ impl Display for PatchName {
261261
/// Represents a git commit hash
262262
#[nutype(
263263
validate(not_empty, predicate = is_valid_commit_hash),
264-
derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, AsRef, TryFrom, FromStr)
264+
derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, AsRef, TryFrom, FromStr, Display)
265265
)]
266266
pub struct CommitId(String);
267267

src/git.rs

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,49 @@ use std::{
1111
use crate::config::{BranchName, CommitId};
1212

1313
/// Run `git` with the given arguments, and get its output
14-
pub fn git<const N: usize>(args: [&str; N]) -> Result<String> {
14+
fn git<const N: usize>(args: [&str; N]) -> Result<String> {
1515
log::trace!("$ git {}", args.join(" "));
1616
get_git_output(&spawn_git(&args, &ROOT)?, &args)
1717
}
1818

19+
/// Add the file
20+
pub fn add(file: &str) -> Result<String> {
21+
git(["add", file])
22+
}
23+
24+
/// Retrieve message of the last commit
25+
pub fn last_commit_message() -> Result<String> {
26+
git(["log", "--format=%B", "--max-count=1"])
27+
}
28+
29+
/// Retrieve message of specific commit
30+
pub fn get_message_of_commit(commit: &str) -> Result<String> {
31+
git(["log", "--format=%B", "--max-count=1", commit])
32+
}
33+
34+
/// Merge the branch into the current one
35+
pub fn merge(branch: &str) -> Result<String> {
36+
git(["merge", "--squash", branch])
37+
}
38+
39+
/// Remote the given remote
40+
pub fn remove_remote(remote: &str) -> Result<String> {
41+
git(["remote", "remove", remote])
42+
}
43+
44+
/// Checkout the commit
45+
pub fn checkout(object: &str) -> Result<String> {
46+
git(["checkout", object])
47+
}
48+
1949
/// Create a commit with the given message
2050
pub fn commit(message: &str) -> Result<String> {
2151
git(["commit", "--message", &format!("patchy: {message}")])
2252
}
2353

2454
/// Fetch remote `url` to local `name`
25-
pub fn try_remote_add(name: &str, url: &str) -> Result<String> {
26-
git(["remote", "add", name, url]).inspect_err(|_| {
27-
// try remove the remote just in case
28-
let _ = git(["remote", "remove", name]);
29-
})
55+
pub fn add_remote(name: &str, url: &str) -> Result<String> {
56+
git(["remote", "add", name, url])
3057
}
3158

3259
/// Fetches the `remote_branch` as the name of `local_branch` from `url`
@@ -38,6 +65,32 @@ pub fn fetch_remote_branch(
3865
git(["fetch", url, &format!("{remote_branch}:{local_branch}")])
3966
}
4067

68+
/// Formats the commit as a `patch` and saves it to the specified path
69+
pub fn save_commit_as_patch(commit: &CommitId, output_path: &str) -> Result<String> {
70+
git([
71+
"format-patch",
72+
"-1",
73+
commit.as_ref(),
74+
"--output",
75+
output_path,
76+
])
77+
}
78+
79+
/// Obtain the URL for a remote
80+
pub fn get_remote_url(remote: &str) -> Result<String> {
81+
git(["remote", "get-url", remote])
82+
}
83+
84+
/// Apply a `patch` as a commit
85+
pub fn apply_patch(filename: &Path) -> Result<()> {
86+
if let Err(err) = git(["am", "--keep-cr", "--signoff", &filename.to_string_lossy()]) {
87+
git(["am", "--abort"])?;
88+
return Err(err);
89+
}
90+
91+
Ok(())
92+
}
93+
4194
/// `true` if there are unstaged changes
4295
pub fn is_worktree_dirty() -> bool {
4396
git(["diff", "--cached", "--quiet"]).is_err()
@@ -70,6 +123,18 @@ pub fn delete_remote_and_branch(remote: &str, branch: &BranchName) -> Result<()>
70123
Ok(())
71124
}
72125

126+
/// Create a `branch` and check it out
127+
pub fn create_branch(branch: &str) -> Result<String> {
128+
git(["switch", "--create", branch])
129+
}
130+
131+
/// forcefully renames the branch we are currently on into the branch specified
132+
/// by the user. WARNING: this is a destructive action which erases the
133+
/// branch name if it conflicts
134+
pub fn rename_branch(old: &str, new: &str) -> Result<String> {
135+
git(["branch", "--move", "--force", old, new])
136+
}
137+
73138
/// Resets the `branch` to the specified `commit`
74139
pub fn reset_branch_to_commit(branch: &BranchName, commit: &CommitId) -> Result<String> {
75140
git(["branch", "--force", branch.as_ref(), commit.as_ref()])

src/git_high_level.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
//! time we want to interact with Git
77
use crate::config::{BranchName, CommitId, PrNumber};
88
use crate::git;
9-
pub use crate::git::git;
109

1110
use anyhow::{Result, anyhow, bail};
1211
use colored::Colorize as _;
@@ -17,7 +16,7 @@ use crate::utils::display_link;
1716
/// Fetches a branch of a remote into local. Optionally accepts a commit hash
1817
/// for versioning.
1918
pub fn add_remote_branch(remote_branch: &RemoteBranch, commit: Option<&CommitId>) -> Result<()> {
20-
git::try_remote_add(
19+
git::add_remote(
2120
&remote_branch.remote.local_remote_alias,
2221
&remote_branch.remote.repository_url,
2322
)
@@ -64,7 +63,7 @@ pub fn checkout_from_remote(branch: &BranchName, remote: &str) -> Result<String>
6463
}
6564
})?;
6665

67-
if let Err(err) = git(["checkout", branch.as_ref()]) {
66+
if let Err(err) = git::checkout(branch.as_ref()) {
6867
git::delete_remote_and_branch(remote, branch)?;
6968
bail!("Failed to checkout branch: {branch}, which belongs to remote {remote}\n{err}");
7069
}
@@ -79,7 +78,7 @@ pub fn merge(
7978
) -> Result<String, anyhow::Error> {
8079
log::trace!("Merging branch {current_branch}");
8180

82-
if let Err(err) = git(["merge", "--squash", current_branch.as_ref()]) {
81+
if let Err(err) = git::merge(current_branch.as_ref()) {
8382
git::nuke_worktree()?;
8483
bail!("failed to merge {other_branch}\n{err}");
8584
}

0 commit comments

Comments
 (0)