Last active
November 18, 2019 03:40
-
-
Save qryxip/bb4eef6135b5d3961004f5ab5927422d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //! ```toml | |
| //! [package] | |
| //! edition = "2018" | |
| //! name = "cargo-touch-workspace" | |
| //! version = "0.0.0" | |
| //! authors = ["Ryo Yamashita <[email protected]>"] | |
| //! description = "Touch the source files in the workspace." | |
| //! publish = false | |
| //! license = "CC0-1.0" | |
| //! | |
| //! [dependencies] | |
| //! anyhow = "1.0.20" | |
| //! atty = "0.2.13" | |
| //! cargo_metadata = "0.9.0" | |
| //! filetime = "0.2.8" | |
| //! structopt = "0.3.4" | |
| //! tracing = "0.1.10" | |
| //! tracing-subscriber = "0.1.6" | |
| //! ``` | |
| use anyhow::Context as _; | |
| use cargo_metadata::MetadataCommand; | |
| use filetime::FileTime; | |
| use structopt::StructOpt; | |
| use tracing::{info, Level}; | |
| use tracing_subscriber::FmtSubscriber; | |
| use std::collections::HashSet; | |
| use std::path::{Path, PathBuf}; | |
| use std::time::SystemTime; | |
| #[derive(Debug, StructOpt)] | |
| #[structopt(author, about, bin_name("cargo"))] | |
| enum Cargo { | |
| #[structopt( | |
| author, | |
| about, | |
| after_help( | |
| r#"This Cargo subcommand does almost the same thing as the following Bash script. | |
| ``` | |
| cargo metadata --format-version 1 | | |
| jq -r '.workspace_members[] as $members | .packages[] | select(.id == $members) | .targets[].src_path' | | |
| xargs touch | |
| ``` | |
| "#, | |
| ) | |
| )] | |
| TouchWorkspace(CargoTouchWorkspace), | |
| } | |
| #[derive(Debug, StructOpt)] | |
| struct CargoTouchWorkspace { | |
| #[structopt(long, help("Path to Cargo.toml"))] | |
| manifest_path: Option<PathBuf>, | |
| } | |
| fn main() -> anyhow::Result<()> { | |
| let Cargo::TouchWorkspace(CargoTouchWorkspace { manifest_path }) = Cargo::from_args(); | |
| FmtSubscriber::builder() | |
| .without_time() | |
| .with_ansi(should_enable_color_for_stderr()) | |
| .with_max_level(Level::INFO) | |
| .init(); | |
| let mut cmd = MetadataCommand::new(); | |
| if let Some(manifest_path) = manifest_path { | |
| cmd.manifest_path(manifest_path); | |
| } | |
| let metadata = cmd.exec()?; | |
| let members = metadata.workspace_members.iter().collect::<HashSet<_>>(); | |
| metadata | |
| .packages | |
| .iter() | |
| .filter(|p| members.contains(&p.id)) | |
| .flat_map(|p| &p.targets) | |
| .try_for_each(|t| touch(&t.src_path)) | |
| } | |
| #[cfg(not(windows))] | |
| fn should_enable_color_for_stderr() -> bool { | |
| use std::env; | |
| atty::is(atty::Stream::Stderr) && env::var("TERM").ok().map_or(false, |v| v != "dumb") | |
| } | |
| #[cfg(windows)] | |
| fn should_enable_color_for_stderr() -> bool { | |
| use tracing::warn; | |
| warn!("TODO"); | |
| false | |
| } | |
| fn touch(path: impl AsRef<Path>) -> anyhow::Result<()> { | |
| let now = FileTime::from_system_time(SystemTime::now()); | |
| filetime::set_file_times(&path, now, now) | |
| .with_context(|| format!("Failed to touch {}", path.as_ref().display()))?; | |
| info!("Touched {}", path.as_ref().display()); | |
| Ok(()) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment