Skip to content

Commit

Permalink
install rustfmt from nightly (#696)
Browse files Browse the repository at this point in the history
allowing us to use any experimental features/flags in `.rustfmt.toml`. I
created one for now with all the default flags. We can review/update
them in future PRs as needed:

```sh
rustfmt  --print-config default .rustfmt.toml
```

Nightly is only used for formatting. Other cargo commands to
build/check/test/run source code are still using the default stable
toolchain.

I additionally updated the docs for `infra` scripts, running `clippy` as
part of `infra check cargo`, since running it separately duplicates some
of the work, and its lints are as important as `cargo check`. It also
decouples its fixes/suggestions from linters like `rustfmt`, so it can
format any applied changes.
  • Loading branch information
OmarTawfik authored Dec 7, 2023
1 parent 0868683 commit 9a78865
Show file tree
Hide file tree
Showing 19 changed files with 134 additions and 90 deletions.
4 changes: 4 additions & 0 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#
# rustfmt nightly configuration options:
# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md
#
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
"rust-analyzer.check.allTargets": true,
"rust-analyzer.check.command": "clippy",
"rust-analyzer.check.features": "all",
"rust-analyzer.server.path": "${workspaceFolder}/bin/rust-analyzer",
"rust-analyzer.rustfmt.extraArgs": [
"+nightly-2023-12-01" // Keep in sync with other "RUST_NIGHTLY_VERSION" references
],
"rust-analyzer.server.path": "${workspaceFolder}/scripts/bin/rust-analyzer",
"search.exclude": {
// Packages and Dependencies
"**/.hermit/": true,
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace.package]
version = "0.11.0"
rust-version = "1.72.0" # Keep this version in sync with "$RUST_VERSION" in "$REPO_ROOT/bin/hermit.hcl" and "rust-src" in "$REPO_ROOT/bin"
rust-version = "1.72.0" # Keep in sync with other "RUST_STABLE_VERSION" references
edition = "2021"
publish = false

Expand Down
1 change: 0 additions & 1 deletion bin/[email protected]

This file was deleted.

1 change: 0 additions & 1 deletion bin/.rust-src-1.72.0.pkg

This file was deleted.

3 changes: 2 additions & 1 deletion bin/hermit.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ env = {

// Rust:
"RUST_BACKTRACE": "FULL",
"RUST_VERSION": "1.72.0", // Keep this version in sync with "rust-version" in "$REPO_ROOT/Cargo.toml" and "rust-src" in "$REPO_ROOT/bin"
"RUST_STABLE_VERSION": "1.72.0", // Keep in sync with other "RUST_STABLE_VERSION" references
"RUST_NIGHTLY_VERSION": "nightly-2023-12-01", // Keep in sync with other "RUST_NIGHTLY_VERSION" references
"RUSTC_WRAPPER": "${HERMIT_ENV}/bin/sccache",
"SCCACHE_DIR": "${HERMIT_ENV}/.hermit/sccache",

Expand Down
1 change: 0 additions & 1 deletion bin/rust-analyzer

This file was deleted.

1 change: 0 additions & 1 deletion bin/rust-src

This file was deleted.

18 changes: 8 additions & 10 deletions crates/infra/cli/generated/infra.zsh-completions

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

3 changes: 2 additions & 1 deletion crates/infra/cli/src/commands/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ impl OrderedCommand for CheckCommand {
}

fn check_cargo() -> Result<()> {
CargoWorkspace::get_command("check")?
// 'cargo clippy' will run both 'cargo check', and 'clippy' lints:
CargoWorkspace::get_command("clippy")?
.flag("--all-targets")
.run()
}
Expand Down
39 changes: 16 additions & 23 deletions crates/infra/cli/src/commands/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ impl LintController {

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, ValueEnum)]
enum LintCommand {
/// Lints all Rust source files.
// Automatically applied lints may need to be formatted again, so we run this before formatting.
Clippy,
/// Format all Rust source files.
CargoFmt,
/// Check for spelling issues in Markdown files.
Cspell,
/// Format all non-Rust source files.
Expand All @@ -38,6 +33,8 @@ enum LintCommand {
MarkdownLinkCheck,
/// Check for violations in Markdown files.
MarkdownLint,
/// Format all Rust source files.
Rustfmt,
/// Check for violations in Bash files.
Shellcheck,
/// Check for type errors in TypeScript files.
Expand All @@ -51,35 +48,18 @@ impl OrderedCommand for LintCommand {
Terminal::step(format!("lint {name}", name = self.clap_name()));

match self {
LintCommand::Clippy => run_clippy(),
LintCommand::CargoFmt => run_cargo_fmt(),
LintCommand::Cspell => run_cspell(),
LintCommand::Prettier => run_prettier(),
LintCommand::MarkdownLinkCheck => run_markdown_link_check(),
LintCommand::MarkdownLint => run_markdown_lint(),
LintCommand::Rustfmt => run_rustfmt(),
LintCommand::Shellcheck => run_shellcheck(),
LintCommand::Tsc => run_tsc(),
LintCommand::Yamllint => run_yamllint(),
}
}
}

fn run_clippy() -> Result<()> {
CargoWorkspace::get_command("clippy")?
.flag("--all-targets")
.run()
}

fn run_cargo_fmt() -> Result<()> {
let mut command = Command::new("cargo-fmt").flag("--all").flag("--verbose");

if GitHub::is_running_in_ci() {
command = command.flag("--check");
}

command.run()
}

fn run_cspell() -> Result<()> {
Command::new("cspell")
.arg("lint")
Expand Down Expand Up @@ -126,6 +106,19 @@ fn run_markdown_lint() -> Result<()> {
command.run_xargs(markdown_files)
}

fn run_rustfmt() -> Result<()> {
let mut command = Command::new("cargo-fmt")
.arg(format!("+{}", env!("RUST_NIGHTLY_VERSION")))
.flag("--all")
.flag("--verbose");

if GitHub::is_running_in_ci() {
command = command.flag("--check");
}

command.run()
}

fn run_shellcheck() -> Result<()> {
let bash_files = FileWalker::from_repo_root()
.find(["scripts/**"])?
Expand Down
12 changes: 10 additions & 2 deletions crates/infra/cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,26 @@ pub struct CLI {
#[derive(Debug, Subcommand)]
enum AppCommand {
/// Setup toolchains and dependencies.
///
/// Running this command without any args will setup everything.
Setup(SetupController),
/// Run codegen checks, and makes sure source files are up to date.
///
/// Running this command without any args will check everything.
Check(CheckController),
/// Run unit tests.
///
/// Running this command without any args will test everything.
Test(TestController),
/// Run linters for formatting, spelling, broken links, and other issues.
///
/// Running this command without any args will lint everything.
Lint(LintController),
/// Perform a full CI run locally, by running 'setup', 'check', 'test', and 'lint' (in that order).
Ci(CiController),
/// Run a local binary within this repository, forwarding any additional arguments along.
/// Run specific local binaries within this repository, forwarding any additional arguments along.
Run(RunController),
/// Build and serve documentation locally, watching for changes.
/// Watch for repository file changes, and run the specified workflows as needed.
Watch(WatchController),
/// Publish different artifacts from this repository.
Publish(PublishController),
Expand Down
50 changes: 50 additions & 0 deletions crates/infra/cli/src/commands/setup/cargo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,56 @@ use anyhow::Result;
use infra_utils::{commands::Command, github::GitHub};

pub fn setup_cargo() -> Result<()> {
// The bootstrap bash script defined in '$REPO_ROOT/scripts/_common.sh'
// installs the 'minimal' profile of the '$RUST_STABLE_VERSION' toolchain.
// This includes the following components:
//
// - 'cargo'
// - 'rust-std'
// - 'rustc'
//
// Which are enough to run infra scripts.
// But we need these additional optional components for local development:
rustup_add_components(env!("RUST_STABLE_VERSION"), ["clippy"])?;
if !GitHub::is_running_in_ci() {
rustup_add_components(
env!("RUST_STABLE_VERSION"),
["rust-analyzer", "rust-docs", "rust-src"],
)?;
}

// Additionally, we also need 'rustfmt nightly', as we use experimental options.
// So let's install the '$RUST_NIGHTLY_VERSION' toolchain along with the 'rustfmt' component.
rustup_install_toolchain(env!("RUST_NIGHTLY_VERSION"))?;
rustup_add_components(env!("RUST_NIGHTLY_VERSION"), ["rustfmt"])?;

// Make sure we have the latest dependencies:
run_cargo_fetch()?;

Ok(())
}

fn rustup_install_toolchain(toolchain: &str) -> Result<()> {
Command::new("rustup")
.arg("install")
.flag("--no-self-update")
.property("--profile", "minimal")
.arg(toolchain)
.run()
}

fn rustup_add_components(
toolchain: &str,
components: impl IntoIterator<Item = impl Into<String>>,
) -> Result<()> {
Command::new("rustup")
.args(["component", "add"])
.property("--toolchain", toolchain)
.args(components)
.run()
}

fn run_cargo_fetch() -> Result<()> {
let mut command = Command::new("cargo").arg("fetch");

if GitHub::is_running_in_ci() {
Expand Down
8 changes: 1 addition & 7 deletions crates/infra/cli/src/commands/setup/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
mod cargo;
mod npm;
mod pipenv;
mod workspace;

use anyhow::Result;
use clap::{Parser, ValueEnum};

use crate::{
commands::setup::{
cargo::setup_cargo, npm::setup_npm, pipenv::setup_pipenv, workspace::setup_workspace,
},
commands::setup::{cargo::setup_cargo, npm::setup_npm, pipenv::setup_pipenv},
utils::{ClapExtensions, OrderedCommand, Terminal},
};

Expand All @@ -27,8 +24,6 @@ impl SetupController {

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, ValueEnum)]
enum SetupCommand {
/// Configure binaries used by editors for local development..
Workspace,
/// Install Cargo dependencies.
Cargo,
/// Install NPM dependencies.
Expand All @@ -42,7 +37,6 @@ impl OrderedCommand for SetupCommand {
Terminal::step(format!("setup {name}", name = self.clap_name()));

match self {
SetupCommand::Workspace => setup_workspace(),
SetupCommand::Cargo => setup_cargo(),
SetupCommand::Npm => setup_npm(),
SetupCommand::Pipenv => setup_pipenv(),
Expand Down
18 changes: 0 additions & 18 deletions crates/infra/cli/src/commands/setup/workspace/mod.rs

This file was deleted.

5 changes: 2 additions & 3 deletions crates/infra/cli/src/commands/watch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ use crate::{

#[derive(Clone, Debug, Parser)]
pub struct WatchController {
#[clap(trailing_var_arg = true)]
commands: Vec<WatchCommand>,
command: WatchCommand,
}

impl WatchController {
pub fn execute(&self) -> Result<()> {
WatchCommand::execute_in_order(&self.commands)
self.command.execute()
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/infra/utils/src/codegen/common/formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ fn run_prettier(file_path: &Path, contents: &str) -> Result<String> {

fn run_rustfmt(contents: &str) -> Result<String> {
Command::new("rustfmt")
.arg(format!("+{}", env!("RUST_NIGHTLY_VERSION")))
.property("--emit", "stdout")
.evaluate_with_input(contents)
}
37 changes: 18 additions & 19 deletions scripts/_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,23 @@ set -euo pipefail
}

#
# Use the repository's Rust version:
# This installs the minimal profile of the '$RUST_STABLE_VERSION' toolchain.
# Any additional toolchains, or optional components, should be installed
# during 'infra setup cargo' step instead of here, as this is the hot path
# for every other command.
#
# See the comments here for more information:
# $REPO_ROOT/crates/infra/cli/src/commands/setup/cargo/mod.rs
#

{
# Components included in the minimal profile:
# - 'cargo'
# - 'rust-std'
# - 'rustc'
#
# Components only included in the default profile:
# - 'clippy'
# - 'rust-docs'
# - 'rustfmt'
#
# No need to install 'rust-docs' (large offline copy). Add the rest manually:
rustup install --no-self-update --profile "minimal" "${RUST_VERSION:?}"
rustup component add "clippy" "rustfmt"

# Make sure we chose the right version, if multiple toolchains are installed:
rustup default "${RUST_VERSION:?}"
}
if ! output=$(
rustup install --no-self-update --profile "minimal" "${RUST_STABLE_VERSION:?}" \
&& rustup default "${RUST_STABLE_VERSION:?}" \
2>&1
); then
# Only print the output if the command failed:
echo "Running 'rustup' failed:"
echo >&2 "${output}"

exit 1
fi
Loading

0 comments on commit 9a78865

Please sign in to comment.