Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions src/bin/rustc_josh_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::Context;
use clap::Parser;
use rustc_josh_sync::SyncContext;
use rustc_josh_sync::config::{JoshConfig, load_config};
use rustc_josh_sync::josh::{JoshProxy, try_install_josh};
use rustc_josh_sync::josh::{JoshProxy, try_install_josh_proxy};
use rustc_josh_sync::sync::{DEFAULT_UPSTREAM_REPO, GitSync, RustcPullError};
use rustc_josh_sync::utils::{get_current_head_sha, prompt};
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -232,12 +232,9 @@ fn get_josh_proxy(proxy_path: Option<PathBuf>, verbose: bool) -> anyhow::Result<
println!("Using josh-proxy binary from {}", path.display());
Ok(JoshProxy::from_path(path))
}
None => {
println!("Updating/installing josh-proxy binary...");
match try_install_josh(verbose) {
Some(proxy) => Ok(proxy),
None => Err(anyhow::anyhow!("Could not install josh-proxy")),
}
}
None => match try_install_josh_proxy(verbose) {
Some(proxy) => Ok(proxy),
None => Err(anyhow::anyhow!("Could not install josh-proxy")),
},
}
}
113 changes: 67 additions & 46 deletions src/josh.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::config::JoshConfig;
use crate::utils::{is_null_sha, run_command, run_command_by_path};
use crate::utils::{is_inside_ci, is_null_sha, run_command_by_path};
use anyhow::Context;
use std::net::{SocketAddr, TcpStream};
use std::path::{Path, PathBuf};
Expand All @@ -14,20 +14,11 @@ pub struct JoshProxy {
path: PathBuf,
}

pub struct JoshFilter {
path: PathBuf,
}

impl JoshProxy {
pub fn from_path(path: PathBuf) -> Self {
Self { path }
}

/// Tries to figure out if `josh-proxy` is installed.
pub fn lookup() -> Option<Self> {
which::which("josh-proxy").ok().map(|path| Self { path })
}

pub fn start(&self, config: &JoshConfig) -> anyhow::Result<RunningJoshProxy> {
// Determine cache directory.
let user_dirs =
Expand Down Expand Up @@ -70,30 +61,13 @@ impl JoshProxy {
}
}

/// Try to install (or update) josh-proxy, to make sure that we use the correct version.
pub fn try_install_josh(verbose: bool) -> Option<JoshProxy> {
run_command(
&[
"cargo",
"+stable",
"install",
"--locked",
"--git",
"https://github.com/josh-project/josh",
"--tag",
JOSH_VERSION,
"josh-proxy",
],
verbose,
)
.expect("cannot install josh-proxy");
JoshProxy::lookup()
pub struct JoshFilter {
path: PathBuf,
}

impl JoshFilter {
/// Tries to figure out if `josh-filter` is installed.
pub fn lookup() -> Option<Self> {
which::which("josh-filter").ok().map(|path| Self { path })
pub fn from_path(path: PathBuf) -> Self {
Self { path }
}

pub fn run<'a, Args: AsRef<[&'a str]>>(
Expand All @@ -113,24 +87,71 @@ impl JoshFilter {
}
}

fn josh_install_directory() -> PathBuf {
let Some(user_dirs) = directories::ProjectDirs::from("org", "rust-lang", "rustc-josh") else {
eprintln!(
"Cannot determine user directory for Josh installation, falling back to local directory"
);
return PathBuf::from(".josh-sync").join("cargo");
};
let local_dir = user_dirs.data_local_dir();
local_dir.join("josh-sync").join("cargo")
}

#[derive(Copy, Clone, Debug)]
enum JoshProgram {
Proxy,
Filter,
}

pub fn try_install_josh_proxy(verbose: bool) -> Option<JoshProxy> {
try_install_josh_program(JoshProgram::Proxy, verbose).map(JoshProxy::from_path)
}

pub fn try_install_josh_filter(verbose: bool) -> Option<JoshFilter> {
// The josh-filter binary is included in the josh-cli crate
run_command(
&[
"cargo",
"+stable",
"install",
"--locked",
"--git",
"https://github.com/josh-project/josh",
"--tag",
JOSH_VERSION,
"josh-cli",
],
try_install_josh_program(JoshProgram::Filter, verbose).map(JoshFilter::from_path)
}
Comment thread
Kobzol marked this conversation as resolved.

/// Try to install (or update) a josh CLI program in a local installation directory.
/// Ensures that we use the correct version.
fn try_install_josh_program(program: JoshProgram, verbose: bool) -> Option<PathBuf> {
let install_dir = josh_install_directory();
let (krate, binary) = match program {
JoshProgram::Proxy => ("josh-proxy", "josh-proxy"),
JoshProgram::Filter => ("josh-cli", "josh-filter"),
};
let path = install_dir.join("bin").join(binary);
println!(
"Updating/installing {binary} binary into `{}`...",
path.display()
);

let mut args = vec![
"+stable",
"install",
"--locked",
"--git",
"https://github.com/josh-project/josh",
"--tag",
JOSH_VERSION,
];

// Install binaries globally on CI to ensure better (rust-)cache usage
if !is_inside_ci() {
args.extend(["--root", install_dir.to_str()?]);
}

args.push(krate);

run_command_by_path(
&Path::new("cargo"),
&args,
&std::env::current_dir().unwrap(),
false,
verbose,
)
.expect("cannot install josh-filter");
JoshFilter::lookup()
.unwrap_or_else(|e| panic!("cannot install {binary}: {e:?}"));
if path.is_file() { Some(path) } else { None }
}

/// Create a wrapper that represents a running instance of `josh-proxy` and stops it on drop.
Expand Down
10 changes: 7 additions & 3 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::Context;
use std::path::{Path, PathBuf};
use std::path::Path;
use std::process::Command;

/// Run command and return its stdout.
Expand Down Expand Up @@ -40,7 +40,7 @@ fn run_command_inner<'a, Args: AsRef<[&'a str]>>(
}

pub fn run_command_by_path<'a, Args: AsRef<[&'a str]>>(
cmd: &PathBuf,
cmd: &Path,
args: Args,
workdir: &Path,
capture: bool,
Expand Down Expand Up @@ -110,14 +110,18 @@ pub fn get_current_head_sha(verbose: bool) -> anyhow::Result<String> {
/// Returns `default_response` on CI.
pub fn prompt(prompt: &str, default_response: bool) -> bool {
// Do not run interactive prompts on CI
if std::env::var("GITHUB_ACTIONS").as_deref() == Ok("1") {
if is_inside_ci() {
return default_response;
}

println!("{prompt} [y/n]");
read_line().to_lowercase() == "y"
}

pub fn is_inside_ci() -> bool {
std::env::var("GITHUB_ACTIONS").as_deref() == Ok("1")
}

pub fn read_line() -> String {
let mut line = String::new();
std::io::stdin()
Expand Down
Loading