Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add xtask msrv #3189

Merged
merged 19 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from 12 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
1 change: 1 addition & 0 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions src/tc/rust/Cargo.lock

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

2 changes: 2 additions & 0 deletions taskchampion/xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ edition = "2018"
anyhow.workspace = true

taskchampion-lib = { path = "../lib" }

regex = "^1.5.6"
129 changes: 122 additions & 7 deletions taskchampion/xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,29 @@
//! At the moment it is very simple, but if this grows more subcommands then
//! it will be sensible to use `clap` or another similar library.

//! const MSRV_FILE_PATHS in /xtask/main.rs is a list of relative file paths that the
//! Minimum Supported Rust Version should be commented into

use regex::Regex;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::io::{BufRead, BufReader};
use std::io::{Seek, Write};
use std::path::{Path, PathBuf};

// Increment length of array when adding more paths.
const MSRV_FILE_PATHS: [&str; 0] = [];

pub fn main() -> anyhow::Result<()> {
let arg = env::args().nth(1);
match arg.as_deref() {
Some("codegen") => codegen(),
Some(arg) => anyhow::bail!("unknown xtask {}", arg),
_ => anyhow::bail!("unknown xtask"),
let arguments: Vec<String> = env::args().collect();
if arguments.len() < 2 {
anyhow::bail!("xtask: Valid arguments are: `codegen`, `msrv <version x.y>`");
}

match arguments[1].as_str() {
"codegen" => codegen(),
"msrv" => msrv(arguments),
_ => anyhow::bail!("xtask: unknown xtask"),
}
}

Expand All @@ -29,3 +41,106 @@

Ok(())
}

/// `cargo xtask msrv (X.Y)`
///
/// This checks and updates the Minimum Supported Rust Version for all files specified in the `MSRV_FILE_PATHS` const in `xtask/src/main.rs` where the pattern `MSRV = "X.Y"` is found in the file.
/// The argument "X.Y" will replace the text any place the MSRV is found.
fn msrv(args: Vec<String>) -> anyhow::Result<()> {
if args.len() != 2 {
// check that (X.Y) argument is (mostly) valid:
if !args[2].chars().all(|c| c.is_numeric() || c == '.') {
anyhow::bail!("xtask: Invalid argument format. Xtask MSRV argument takes the form \"X.Y(y)\", where XYy are numbers. eg: `cargo run xtask MSRV 1.68`");
}

// for each file in const paths vector
for path in MSRV_FILE_PATHS {
let path: &Path = Path::new(&path);
let mut is_pattern_in_file = false;

// check if path exists, if not, skip then continue
if !path.exists() {
println!(
"xtask: Warning: xtask: Path \"{}\" not found. Skipping.",
path.display()
);
continue;
}

let mut file: File = File::options().read(true).write(true).open(path)?;
let reader = BufReader::new(&file);

// set the file_extension if it exists and is valid UTF-8
let mut file_extension = String::new();

Check warning on line 74 in taskchampion/xtask/src/main.rs

View workflow job for this annotation

GitHub Actions / Check & Clippy

value assigned to `file_extension` is never read

Check warning on line 74 in taskchampion/xtask/src/main.rs

View workflow job for this annotation

GitHub Actions / Check & Clippy

value assigned to `file_extension` is never read

Check warning on line 74 in taskchampion/xtask/src/main.rs

View workflow job for this annotation

GitHub Actions / codegen

value assigned to `file_extension` is never read
iwyatt marked this conversation as resolved.
Show resolved Hide resolved
if path.extension().is_some() && path.extension().unwrap().to_str().is_some() {
file_extension = path.extension().unwrap().to_str().unwrap().to_string();
} else {
anyhow::bail!(
"xtask: {} does not have a valid extension and cannot be processed.",
format!("{:#?}", path.as_os_str())
);
}

// set the comment glyph (#, //, --) pattern to search for based on file type
let mut comment_glyph = String::new();

Check warning on line 85 in taskchampion/xtask/src/main.rs

View workflow job for this annotation

GitHub Actions / Check & Clippy

value assigned to `comment_glyph` is never read

Check warning on line 85 in taskchampion/xtask/src/main.rs

View workflow job for this annotation

GitHub Actions / Check & Clippy

value assigned to `comment_glyph` is never read

Check warning on line 85 in taskchampion/xtask/src/main.rs

View workflow job for this annotation

GitHub Actions / codegen

value assigned to `comment_glyph` is never read
match file_extension.as_str() {
"rs" => comment_glyph = "//".to_string(),
"toml" | "yaml" | "yml" => comment_glyph = "#".to_string(),
_ => anyhow::bail!("xtask: Support for file extension {} is not yet implemented in `cargo xtask msrv` command.", file_extension)
}

// set search string and the replacement string
let re = Regex::new(r#"(#|/{2,}) *MSRV *= *"*([0-9]+\.*)+"*.*"#).unwrap();
let replacement_string = format!("{} MSRV = \"{}\"", comment_glyph, args[2]);

// for each line in file
let mut file_string = String::new();
for line in reader.lines() {
let line_ref = &line.as_ref().unwrap();
iwyatt marked this conversation as resolved.
Show resolved Hide resolved
let pattern_offset = re.find(line_ref);

// if a pre-existing MSRV pattern is found and is different, update it.
if pattern_offset.is_some() {
if pattern_offset.unwrap().as_str() != replacement_string {

Check warning on line 104 in taskchampion/xtask/src/main.rs

View workflow job for this annotation

GitHub Actions / Check & Clippy

called `unwrap` on `pattern_offset` after checking its variant with `is_some`
iwyatt marked this conversation as resolved.
Show resolved Hide resolved
file_string += format!("{}\n", &replacement_string).as_str();
is_pattern_in_file = true;
println!(
"xtask: MSRV pattern found in {:#?}; updating MSRV to {}",
path.as_os_str(),
args[2]
);
continue;
} else {
println!("xtask: MSRV pattern found in {:#?} and is same as specified version in xtask argument.", path.as_os_str());
}
}

file_string += line_ref;
file_string += "\n";
}

// if pattern was found and updated, write to disk
if is_pattern_in_file {
// Prepare to write the file to disk

// Set the file length to the file_string length
let _ = file.set_len(file_string.len() as u64);

// set the cursor to the beginning of the file and write
let _ = file.seek(std::io::SeekFrom::Start(0));
let file_write_result = file.write(file_string.as_bytes());

// if error, print error messege and exit
if file_write_result.is_err() {
anyhow::bail!("xtask: unable to write file to disk: {}", &path.display());
}
} else {
println!("xtask: No changes to file: \"{}\"", &path.display());
}
}
} else {
anyhow::bail!("xtask: Wrong number of arguments.");
}

Ok(())
}
Loading