Skip to content

Commit

Permalink
Handle ctrl-c
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Nov 20, 2019
1 parent 143b164 commit 0982207
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 22 deletions.
48 changes: 45 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ A tool to work around some limitations on cargo.
[workspace]

[dependencies]
anyhow = "1.0.20"
anyhow = "1.0.22"
ctrlc = "3.1.3"
serde = "1.0.102"
# Depends directly on `serde_derive` instead of using `derive` feature of
# `serde` to reduce compile time. When pipeline compilation for proc-macro is
Expand Down
82 changes: 64 additions & 18 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@ mod manifest;
mod metadata;
mod process;

use std::{env, ffi::OsString, fs, path::Path};
use std::{
env,
ffi::OsString,
fs,
path::{Path, PathBuf},
sync::{
atomic::{AtomicBool, Ordering::SeqCst},
Arc, Mutex,
},
};

use anyhow::{bail, Context, Error};

Expand Down Expand Up @@ -121,33 +130,70 @@ fn no_dev_deps(
manifest: &Manifest,
line: &ProcessBuilder,
) -> Result<()> {
struct Bomb<'a> {
manifest: &'a Manifest,
args: &'a Args,
done: bool,
res: &'a mut Result<()>,
struct Restore {
manifest: String,
manifest_path: PathBuf,
color: Option<Coloring>,
restore: AtomicBool,
done: AtomicBool,
res: Arc<Mutex<Option<Result<()>>>>,
}

impl Drop for Bomb<'_> {
fn drop(&mut self) {
if !self.args.remove_dev_deps {
let res = fs::write(&self.manifest.path, &self.manifest.raw).with_context(|| {
format!("failed to restore manifest file: {}", self.manifest.path.display())
impl Restore {
#[allow(clippy::type_complexity)]
fn new(
args: &Args,
manifest: &Manifest,
) -> (Bomb, Arc<Self>, Arc<Mutex<Option<Result<()>>>>) {
let res = Arc::new(Mutex::new(Some(Ok(()))));

let bomb = Arc::new(Self {
manifest: manifest.raw.to_string(),
manifest_path: manifest.path.to_path_buf(),
color: args.color,
// if `--remove-dev-deps` flag is off, restore manifest file.
restore: AtomicBool::new(args.no_dev_deps && !args.remove_dev_deps),
done: AtomicBool::new(false),
res: res.clone(),
});

(Bomb(bomb.clone()), bomb, res)
}

fn restore_dev_deps(&self) {
if self.restore.load(SeqCst) {
let res = fs::write(&self.manifest_path, &self.manifest).with_context(|| {
format!("failed to restore manifest file: {}", self.manifest_path.display())
});

if self.done {
*self.res = res;
if self.done.load(SeqCst) {
*self.res.lock().unwrap() = Some(res);
} else if let Err(e) = res {
error!(self.args.color, "{:#}", e);
error!(self.color, "{:#}", e);
}

self.restore.store(false, SeqCst);
}
}
}

struct Bomb(Arc<Restore>);

impl Drop for Bomb {
fn drop(&mut self) {
self.0.restore_dev_deps();
}
}

if args.no_dev_deps || args.remove_dev_deps {
let mut res = Ok(());
let new = manifest.remove_dev_deps()?;
let mut bomb = Bomb { manifest, args, done: false, res: &mut res };
let (bomb, restore, res) = Restore::new(args, manifest);

ctrlc::set_handler(move || {
restore.restore_dev_deps();
std::process::exit(0)
})
.unwrap();

fs::write(&package.manifest_path, new).with_context(|| {
format!("failed to update manifest file: {}", package.manifest_path.display())
Expand All @@ -157,9 +203,9 @@ fn no_dev_deps(
each_feature(args, package, line)?;
}

bomb.done = true;
bomb.0.done.store(true, SeqCst);
drop(bomb);
res?;
res.lock().unwrap().take().unwrap()?;
} else if args.subcommand.is_some() {
each_feature(args, package, line)?;
}
Expand Down

0 comments on commit 0982207

Please sign in to comment.