Skip to content

Commit 6558def

Browse files
committed
refactor: couple more of the parsing logic with the config struct
1 parent 642d909 commit 6558def

File tree

11 files changed

+212
-147
lines changed

11 files changed

+212
-147
lines changed

Cargo.lock

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ tap = "1.0.1"
5353
dialoguer = "0.11.0"
5454
clap_complete_command = { version="0.6.1", features = ["nushell", "fig", "carapace"] }
5555
clap-verbosity-flag = "3.0.3"
56+
itertools = "0.14.0"
5657

5758
[dev-dependencies]
5859
pretty_assertions = "1.4"

src/cli.rs

Lines changed: 9 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
//! Parse the command-line arguments
22
3-
use std::{path::PathBuf, str::FromStr};
3+
use std::path::PathBuf;
44

55
use clap::{
66
CommandFactory as _, Parser, Subcommand,
77
builder::styling::{AnsiColor, Effects},
88
};
9-
use tap::Pipe as _;
109

11-
use crate::{commands, commit::Commit};
10+
use crate::{commands, config::Commit, config::Remote};
1211

1312
/// A tool which makes it easy to declaratively manage personal forks by automatically merging pull requests
1413
#[derive(Parser, Debug)]
@@ -134,41 +133,6 @@ pub struct Branch {
134133
pub commit: Option<Commit>,
135134
}
136135

137-
/// Example: `helix-editor/helix/master`
138-
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Default)]
139-
pub struct Remote {
140-
/// Example: `helix-editor`
141-
pub owner: String,
142-
/// Example: `helix`
143-
pub repo: String,
144-
/// Example: `master`
145-
pub branch: String,
146-
}
147-
148-
impl Remote {
149-
/// Default branch for a remote
150-
const DEFAULT_BRANCH: &str = "main";
151-
}
152-
153-
impl FromStr for Remote {
154-
type Err = String;
155-
156-
fn from_str(s: &str) -> Result<Self, Self::Err> {
157-
s.split_once('/')
158-
.ok_or_else(|| "Expected format: `owner/repo`".to_string())?
159-
.pipe(|(owner, rest)| {
160-
rest.split_once('/')
161-
.unwrap_or((rest, Self::DEFAULT_BRANCH))
162-
.pipe(|(repo, branch)| Self {
163-
owner: owner.to_string(),
164-
repo: repo.to_string(),
165-
branch: branch.to_string(),
166-
})
167-
})
168-
.pipe(Ok)
169-
}
170-
}
171-
172136
#[cfg(test)]
173137
mod test {
174138
use super::*;
@@ -180,15 +144,19 @@ mod test {
180144
Remote {
181145
owner: "helix-editor".to_string(),
182146
repo: "helix".to_string(),
183-
branch: "main".to_string()
147+
branch: "main".to_string(),
148+
commit: None
184149
}
185150
);
186151
assert_eq!(
187-
"helix-editor/helix/master".parse::<Remote>().unwrap(),
152+
"helix-editor/helix/master @ 1a2b3c"
153+
.parse::<Remote>()
154+
.unwrap(),
188155
Remote {
189156
owner: "helix-editor".to_string(),
190157
repo: "helix".to_string(),
191-
branch: "master".to_string()
158+
branch: "master".to_string(),
159+
commit: Some(Commit::try_new("1a2b3c").unwrap())
192160
}
193161
);
194162
"helix-editor".parse::<Remote>().unwrap_err();

src/commands/branch_fetch.rs

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

5-
use crate::cli::Remote;
6-
use crate::commit::Commit;
5+
use crate::config::{Commit, Remote};
76
use crate::git::{fetch_branch, git};
87
use anyhow::anyhow;
98

@@ -13,7 +12,7 @@ pub async fn branch_fetch(
1312
commit: Option<Commit>,
1413
checkout: bool,
1514
) -> anyhow::Result<()> {
16-
let (_, info) = fetch_branch(&remote, commit.as_ref()).await?;
15+
let (_, info) = fetch_branch(&remote).await?;
1716

1817
log::info!(
1918
"Fetched branch {}/{}/{} available at branch {}{}",

src/commands/gen_patch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::path::PathBuf;
66
use anyhow::bail;
77

88
use crate::CONFIG_PATH;
9-
use crate::commit::Commit;
9+
use crate::config::Commit;
1010
use crate::git::git;
1111
use crate::utils::normalize_commit_msg;
1212

src/commands/pr_fetch.rs

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

6-
use crate::cli::Remote;
7-
use crate::commit::Commit;
6+
use crate::config::{Commit, Remote};
87
use crate::git::{fetch_pull_request, git};
98

109
/// Fetch the given `pr` of `remote` at `commit` and store it in local `branch`
@@ -37,6 +36,7 @@ pub async fn pr_fetch(
3736
owner: owner.to_string(),
3837
repo: repo.to_string(),
3938
branch: "main".to_string(),
39+
commit: None,
4040
})
4141
} else {
4242
Err(err())

src/commands/run.rs

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use colored::Colorize as _;
1212
use crate::git::{self, GIT_ROOT, git};
1313
use crate::github_api::{Branch, Remote, RemoteBranch};
1414
use crate::utils::{display_link, with_uuid};
15-
use crate::{CONFIG_PATH, CONFIG_ROOT, confirm_prompt};
15+
use crate::{CONFIG_FILE, CONFIG_FILE_PATH, CONFIG_PATH, CONFIG_ROOT, commands, confirm_prompt};
1616

1717
/// Backup for a file
1818
struct FileBackup {
@@ -24,11 +24,33 @@ struct FileBackup {
2424

2525
/// Run patchy, if `yes` then there will be no prompt
2626
pub async fn run(yes: bool) -> anyhow::Result<()> {
27-
let Some(config) = Config::read(yes)? else {
28-
// if it's Ok(None), we have wrote the default config
27+
let root = CONFIG_ROOT.as_str();
28+
29+
let Ok(config_string) = fs::read_to_string(&*CONFIG_FILE_PATH) else {
30+
log::error!("Could not find configuration file at {root}/{CONFIG_FILE}");
31+
32+
// We don't want to have *any* sort of prompt when using the -y flag since that
33+
// would be problematic in scripts
34+
if !yes && confirm_prompt!("Would you like us to run `patchy init` to initialize it?",) {
35+
commands::init()?;
36+
} else if yes {
37+
log::info!("You can create it with `patchy init`",);
38+
} else {
39+
// user said "no" in the prompt, so we don't do any initializing
40+
}
41+
42+
// We don't want to read the default configuration file as config_string. Since
43+
// it's empty there's no reason why the user would want to run it.
44+
2945
return Ok(());
3046
};
3147

48+
log::trace!("Using configuration file {}", CONFIG_FILE_PATH.display());
49+
50+
let config = toml::from_str::<Config>(&config_string).map_err(|err| {
51+
anyhow!("Could not parse `{root}/{CONFIG_FILE}` configuration file:\n{err}",)
52+
})?;
53+
3254
let Ref {
3355
item: remote_branch,
3456
commit,
@@ -145,34 +167,14 @@ pub async fn run(yes: bool) -> anyhow::Result<()> {
145167
}
146168

147169
// Process branches
148-
for Ref {
149-
item: branch_path,
150-
commit: commit_hash,
151-
} in &config.branches
152-
{
153-
// Parse the branch path into owner/repo/branch format
154-
let parts: Vec<&str> = branch_path.split('/').collect();
155-
if parts.len() < 3 {
156-
log::error!("Invalid branch format: {branch_path}. Expected format: owner/repo/branch");
170+
for remote in &config.branches {
171+
let owner = &remote.owner;
172+
let repo = &remote.repo;
173+
let branch = &remote.branch;
174+
let Ok((_, info)) = git::fetch_branch(remote).await.inspect_err(|err| {
175+
log::error!("failed to fetch branch {owner}/{repo}/{branch}: {err}");
176+
}) else {
157177
continue;
158-
}
159-
160-
let owner = parts[0];
161-
let repo = parts[1];
162-
let branch_name = parts[2..].join("/");
163-
164-
let remote = crate::cli::Remote {
165-
owner: owner.to_string(),
166-
repo: repo.to_string(),
167-
branch: branch_name.clone(),
168-
};
169-
170-
let info = match git::fetch_branch(&remote, commit_hash.as_ref()).await {
171-
Ok((_, info)) => info,
172-
Err(err) => {
173-
log::error!("Could not fetch branch {owner}/{repo}/{branch_name}: {err}");
174-
continue;
175-
}
176178
};
177179

178180
if let Err(err) = git::merge_into_main(
@@ -186,8 +188,9 @@ pub async fn run(yes: bool) -> anyhow::Result<()> {
186188
"Merged branch {}/{}/{} {}",
187189
owner.bright_blue(),
188190
repo.bright_blue(),
189-
branch_name.bright_blue(),
190-
commit_hash
191+
branch.bright_blue(),
192+
remote
193+
.commit
191194
.as_ref()
192195
.map(|hash| format!("at commit {}", hash.as_ref().bright_yellow()))
193196
.unwrap_or_default()

src/commit.rs

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)