Skip to content

Commit 501013d

Browse files
committed
Add support for creating pull PRs using gh
1 parent 8bc3929 commit 501013d

File tree

5 files changed

+69
-18
lines changed

5 files changed

+69
-18
lines changed

src/bin/josh_sync.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use clap::Parser;
33
use josh_sync::config::{JoshConfig, load_config};
44
use josh_sync::josh::{JoshProxy, try_install_josh};
55
use josh_sync::sync::{GitSync, RustcPullError};
6+
use josh_sync::utils::prompt;
67
use std::path::{Path, PathBuf};
78

89
const DEFAULT_CONFIG_PATH: &str = "josh-sync.toml";
@@ -44,17 +45,18 @@ fn main() -> anyhow::Result<()> {
4445
let config = load_config(&config)
4546
.context("cannot load config. Run the `init` command to initialize it.")?;
4647
let josh = get_josh_proxy()?;
47-
let sync = GitSync::new(config, josh);
48-
if let Err(error) = sync.rustc_pull() {
49-
match error {
50-
RustcPullError::NothingToPull => {
51-
eprintln!("Nothing to pull");
52-
std::process::exit(2);
53-
}
54-
RustcPullError::PullFailed(error) => {
55-
eprintln!("Pull failure: {error:?}");
56-
std::process::exit(1);
57-
}
48+
let sync = GitSync::new(config.clone(), josh);
49+
match sync.rustc_pull() {
50+
Ok(result) => {
51+
maybe_create_gh_pr(&config.config, &result.merge_commit_message)?;
52+
}
53+
Err(RustcPullError::NothingToPull) => {
54+
eprintln!("Nothing to pull");
55+
std::process::exit(2);
56+
}
57+
Err(RustcPullError::PullFailed(error)) => {
58+
eprintln!("Pull failure: {error:?}");
59+
std::process::exit(1);
5860
}
5961
}
6062
}
@@ -63,14 +65,37 @@ fn main() -> anyhow::Result<()> {
6365
Ok(())
6466
}
6567

68+
fn maybe_create_gh_pr(config: &JoshConfig, pr_description: &str) -> anyhow::Result<()> {
69+
let gh_available = which::which("gh").is_ok();
70+
if !gh_available {
71+
println!(
72+
"Note: if you install the `gh` CLI tool, josh-sync will be able to create the sync PR for you."
73+
);
74+
} else if prompt("Do you want to create a rustc pull PR using the `gh` tool?") {
75+
let repo = config.full_repo_name();
76+
std::process::Command::new("gh")
77+
.args(&[
78+
"pr",
79+
"create",
80+
"--title",
81+
"Rustc pull update",
82+
"--body",
83+
pr_description,
84+
"--repo",
85+
&repo,
86+
])
87+
.spawn()?
88+
.wait()?;
89+
}
90+
91+
Ok(())
92+
}
93+
6694
fn get_josh_proxy() -> anyhow::Result<JoshProxy> {
6795
match JoshProxy::lookup() {
6896
Some(proxy) => Ok(proxy),
6997
None => {
70-
println!("josh-proxy not found. Do you want to install it? [y/n]");
71-
let mut line = String::new();
72-
std::io::stdin().read_line(&mut line)?;
73-
if line.trim().to_lowercase() == "y" {
98+
if prompt("josh-proxy not found. Do you want to install it?") {
7499
match try_install_josh() {
75100
Some(proxy) => Ok(proxy),
76101
None => Err(anyhow::anyhow!("Could not install josh-proxy")),

src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ impl JoshConfig {
2626
}
2727
}
2828

29+
#[derive(Clone)]
2930
pub struct JoshConfigWithPath {
3031
pub config: JoshConfig,
3132
pub path: PathBuf,

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
pub mod config;
22
pub mod josh;
33
pub mod sync;
4-
mod utils;
4+
pub mod utils;

src/sync.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ fn construct_filter(path: &str) -> String {
2323
format!(":/{path}")
2424
}
2525

26+
pub struct PullResult {
27+
pub merge_commit_message: String,
28+
}
29+
2630
pub struct GitSync {
2731
config: JoshConfigWithPath,
2832
proxy: JoshProxy,
@@ -33,7 +37,7 @@ impl GitSync {
3337
Self { config, proxy }
3438
}
3539

36-
pub fn rustc_pull(&self) -> Result<(), RustcPullError> {
40+
pub fn rustc_pull(&self) -> Result<PullResult, RustcPullError> {
3741
// The upstream commit that we want to pull
3842
let upstream_sha = {
3943
let out = check_output([
@@ -170,7 +174,9 @@ Filtered ref: {incoming_ref}
170174
}
171175

172176
println!("Pull finished! Current HEAD is {current_sha}");
173-
Ok(())
177+
Ok(PullResult {
178+
merge_commit_message: merge_message,
179+
})
174180
}
175181
}
176182

src/utils.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,22 @@ pub fn ensure_clean_git_state() {
2525
.expect("cannot figure out if git state is clean");
2626
assert!(read.is_empty(), "working directory must be clean");
2727
}
28+
29+
/// Ask a prompt to user and return true if they responded with `y`.
30+
pub fn prompt(prompt: &str) -> bool {
31+
// Do not run interactive prompts on CI
32+
if std::env::var("GITHUB_ACTIONS").as_deref() == Ok("1") {
33+
return false;
34+
}
35+
36+
println!("{prompt} [y/n]");
37+
read_line().to_lowercase() == "y"
38+
}
39+
40+
pub fn read_line() -> String {
41+
let mut line = String::new();
42+
std::io::stdin()
43+
.read_line(&mut line)
44+
.expect("cannot read line from stdin");
45+
line.trim().to_string()
46+
}

0 commit comments

Comments
 (0)