Skip to content

Commit

Permalink
refactor(nervous-system-runscript): move utilities to utils.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
anchpop committed Feb 6, 2025
1 parent a49a6dd commit 96e2be9
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 89 deletions.
1 change: 1 addition & 0 deletions rs/nervous_system/tools/release-runscript/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ rust_binary(
name = "release-runscript",
srcs = [
"src/main.rs",
"src/utils.rs",
],
deps = DEPENDENCIES,
)
118 changes: 118 additions & 0 deletions rs/nervous_system/tools/release-runscript/src/commit_switcher.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use std::process::{Command, Stdio};
use anyhow::Result;
use colored::*;

/// Helper struct to switch branches, then switch back when dropped.
pub(crate) struct CommitSwitcher {
from_commit: String,
stashed: bool,
}

impl CommitSwitcher {
pub(crate) fn switch(to_commit: String) -> Result<Self> {
let ic = ic_dir();

// record original commit
let from_commit = Command::new("git")
.current_dir(&ic)
.arg("rev-parse")
.arg("HEAD")
.output()?;
let from_commit = String::from_utf8(from_commit.stdout)?.trim().to_string();

// Check for local changes
let status = Command::new("git")
.current_dir(&ic)
.args(["status", "--porcelain"])
.output()?;
let has_changes = !status.stdout.is_empty();

// stash if we have changes
if has_changes {
println!("{}", format!("Stashing changes...").bright_blue());
let stash = Command::new("git").current_dir(&ic).arg("stash").output()?;
if !stash.status.success() {
return Err(
anyhow::anyhow!("{}", String::from_utf8_lossy(&stash.stderr))
.context("Failed to stash changes."),
);
}

std::thread::sleep(std::time::Duration::from_secs(1));
}

// switch to the new commit
println!(
"{}",
format!("Switching to commit: {}", to_commit).bright_blue()
);
let output = Command::new("git")
.current_dir(&ic)
.arg("switch")
.arg("-d")
.arg(&to_commit)
.output()?;
if !output.status.success() {
return Err(
anyhow::anyhow!("{}", String::from_utf8_lossy(&output.stderr))
.context("Failed to checkout commit."),
);
}

Ok(Self {
from_commit,
stashed: has_changes,
})
}
}

impl Drop for CommitSwitcher {
fn drop(&mut self) {
let ic = ic_dir();

// reset ic/Cargo.lock, in case people's rust-analyzers have messed it up
let _ = Command::new("git")
.current_dir(&ic)
.arg("reset")
.arg("Cargo.lock")
.output();

// switch
println!(
"{}",
format!("Switching back to commit: {}", self.from_commit).bright_blue()
);
let switch = Command::new("git")
.current_dir(&ic)
.arg("switch")
.arg("-d")
.arg(&self.from_commit)
.output()
.unwrap();

std::thread::sleep(std::time::Duration::from_secs(1));

if !switch.status.success() {
println!(
"{}",
format!(
"Failed to switch back to commit. Try running `git switch -d {}`",
self.from_commit
)
.bright_red()
);
println!("error: {}", String::from_utf8_lossy(&switch.stderr));
return;
}

if self.stashed {
// apply stash
Command::new("git")
.current_dir(&ic)
.arg("stash")
.arg("pop")
.output()
.unwrap();
}
}
}
91 changes: 2 additions & 89 deletions rs/nervous_system/tools/release-runscript/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
mod utils;
use anyhow::{bail, Result};
use clap::{Parser, Subcommand};
use colored::*;
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{Command, Stdio};
use url::Url;
use utils::*;

#[derive(Debug, Parser)]
struct DetermineTargets {
Expand Down Expand Up @@ -93,12 +94,6 @@ struct ReleaseRunscript {
step: Option<Step>,
}

fn ic_dir() -> PathBuf {
let workspace_dir =
std::env::var("BUILD_WORKSPACE_DIRECTORY").expect("BUILD_WORKSPACE_DIRECTORY not set");
PathBuf::from(&workspace_dir)
}

fn main() -> Result<()> {
let args = match ReleaseRunscript::try_parse_from(std::env::args()) {
Ok(args) => args,
Expand Down Expand Up @@ -700,85 +695,3 @@ fn run_update_changelog(_: UpdateChangelog) -> Result<()> {

Ok(())
}

fn print_header() {
println!("{}", "\nNNS Release Runscript".bright_green().bold());
println!("{}", "===================".bright_green());
println!("This script will guide you through the NNS release process.\n");
}

fn print_step(number: usize, title: &str, description: &str) -> Result<()> {
println!(
"{} {}",
format!("Step {}:", number).bright_blue().bold(),
title.white().bold()
);
println!("{}", "---".bright_blue());
println!("{}\n", description);
press_enter_to_continue()?;
print!("\x1B[2J\x1B[1;1H");
Ok(())
}

fn input(text: &str) -> Result<String> {
print!("{}: ", text);
std::io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
Ok(input.trim().to_string())
}

fn input_with_default(text: &str, default: &str) -> Result<String> {
let input = input(&format!("{} (default: {})", text, default))?;
if input.is_empty() {
Ok(default.to_string())
} else {
Ok(input)
}
}

fn open_webpage(url: &Url) -> Result<()> {
println!("Opening webpage: {}", url);

let command = "open";
Command::new(command).arg(url.to_string()).spawn()?.wait()?;

Ok(())
}

fn copy(text: &[u8]) -> Result<()> {
let mut copy = Command::new("pbcopy").stdin(Stdio::piped()).spawn()?;
copy.stdin
.take()
.ok_or(anyhow::anyhow!("Failed to take stdin"))?
.write_all(text)?;
copy.wait()?;

Ok(())
}

fn input_yes_or_no(text: &str, default: bool) -> Result<bool> {
loop {
let input = input(&format!(
"{} {}",
text,
if default {
"Y/n (default: yes)"
} else {
"y/N (default: no)"
}
))?;
if input.is_empty() {
return Ok(default);
} else if input.to_lowercase() == "y" {
return Ok(true);
} else if input.to_lowercase() == "n" {
return Ok(false);
}
}
}

fn press_enter_to_continue() -> Result<()> {
input(&format!("\n{}", "Press Enter to continue...".bright_blue()))?;
Ok(())
}
94 changes: 94 additions & 0 deletions rs/nervous_system/tools/release-runscript/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use anyhow::Result;
use colored::*;
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{Command, Stdio};
use url::Url;

pub(crate) fn ic_dir() -> PathBuf {
let workspace_dir =
std::env::var("BUILD_WORKSPACE_DIRECTORY").expect("BUILD_WORKSPACE_DIRECTORY not set");
PathBuf::from(&workspace_dir)
}

pub(crate) fn print_header() {
println!("{}", "\nNNS Release Runscript".bright_green().bold());
println!("{}", "===================".bright_green());
println!("This script will guide you through the NNS release process.\n");
}

pub(crate) fn print_step(number: usize, title: &str, description: &str) -> Result<()> {
println!(
"{} {}",
format!("Step {}:", number).bright_blue().bold(),
title.white().bold()
);
println!("{}", "---".bright_blue());
println!("{}\n", description);
press_enter_to_continue()?;
print!("\x1B[2J\x1B[1;1H");
Ok(())
}

pub(crate) fn input(text: &str) -> Result<String> {
print!("{}: ", text);
std::io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
Ok(input.trim().to_string())
}

pub(crate) fn input_with_default(text: &str, default: &str) -> Result<String> {
let input = input(&format!("{} (default: {})", text, default))?;
if input.is_empty() {
Ok(default.to_string())
} else {
Ok(input)
}
}

pub(crate) fn open_webpage(url: &Url) -> Result<()> {
println!("Opening webpage: {}", url);

let command = "open";
Command::new(command).arg(url.to_string()).spawn()?.wait()?;

Ok(())
}

pub(crate) fn copy(text: &[u8]) -> Result<()> {
let mut copy = Command::new("pbcopy").stdin(Stdio::piped()).spawn()?;
copy.stdin
.take()
.ok_or(anyhow::anyhow!("Failed to take stdin"))?
.write_all(text)?;
copy.wait()?;

Ok(())
}

pub(crate) fn input_yes_or_no(text: &str, default: bool) -> Result<bool> {
loop {
let input = input(&format!(
"{} {}",
text,
if default {
"Y/n (default: yes)"
} else {
"y/N (default: no)"
}
))?;
if input.is_empty() {
return Ok(default);
} else if input.to_lowercase() == "y" {
return Ok(true);
} else if input.to_lowercase() == "n" {
return Ok(false);
}
}
}

pub(crate) fn press_enter_to_continue() -> Result<()> {
input(&format!("\n{}", "Press Enter to continue...".bright_blue()))?;
Ok(())
}

0 comments on commit 96e2be9

Please sign in to comment.