Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into subtree-push-nigh…
Browse files Browse the repository at this point in the history
…tly-2024-12-02
  • Loading branch information
ytmimi committed Dec 2, 2024
2 parents 232528a + 9f8fcc2 commit 46c9cfc
Show file tree
Hide file tree
Showing 149 changed files with 1,313 additions and 466 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64};
```
[style guide's version sorting algorithm]: https://doc.rust-lang.org/nightly/style-guide/#sorting
- When parsing rustfmt configurations fails, rustfmt will now include the path to the toml file in the erorr message [#6302](https://github.com/rust-lang/rustfmt/issues/6302)
- When parsing rustfmt configurations fails, rustfmt will now include the path to the toml file in the error message [#6302](https://github.com/rust-lang/rustfmt/issues/6302)

### Added
- rustfmt now formats trailing where clauses in type aliases [#5887](https://github.com/rust-lang/rustfmt/pull/5887)
Expand Down Expand Up @@ -133,7 +133,7 @@
### Changed

- `hide_parse_errors` has been soft deprecated and it's been renamed to `show_parse_errors` [#5961](https://github.com/rust-lang/rustfmt/pull/5961).
- The diff output produced by `rustfmt --check` is more compatable with editors that support navigating directly to line numbers [#5971](https://github.com/rust-lang/rustfmt/pull/5971)
- The diff output produced by `rustfmt --check` is more compatible with editors that support navigating directly to line numbers [#5971](https://github.com/rust-lang/rustfmt/pull/5971)
- When using `version=Two`, the `trace!` macro from the [log crate] is now formatted similarly to `debug!`, `info!`, `warn!`, and `error!` [#5987](https://github.com/rust-lang/rustfmt/issues/5987).

[log crate]: https://crates.io/crates/log
Expand Down
6 changes: 4 additions & 2 deletions Configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3062,7 +3062,9 @@ fn main() {

## `version`

This option is deprecated and has been replaced by [`style_edition`](#style_edition)
This option is deprecated and has been replaced by [`style_edition`](#style_edition).
`version = "One"` is equivalent to `style_edition = "(2015|2018|2021)"` and
`version = "Two"` is equivalent to `style_edition = "2024"`

- **Default value**: `One`
- **Possible values**: `One`, `Two`
Expand Down Expand Up @@ -3112,7 +3114,7 @@ Break comments to fit on the line

Note that no wrapping will happen if:
1. The comment is the start of a markdown header doc comment
2. An URL was found in the comment
2. A URL was found in the comment

- **Default value**: `false`
- **Possible values**: `true`, `false`
Expand Down
1 change: 0 additions & 1 deletion check_diff/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@ edition = "2021"
clap = { version = "4.4.2", features = ["derive"] }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
[dev-dependencies]
tempfile = "3"
216 changes: 215 additions & 1 deletion check_diff/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,49 @@
use std::env;
use std::io;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::Utf8Error;
use tracing::info;

pub enum CheckDiffError {
/// Git related errors
FailedGit(GitError),
/// Error for generic commands
FailedCommand(&'static str),
/// UTF8 related errors
FailedUtf8(Utf8Error),
/// Error for building rustfmt from source
FailedSourceBuild(&'static str),
/// Error when obtaining binary version
FailedBinaryVersioning(PathBuf),
/// Error when obtaining cargo version
FailedCargoVersion(&'static str),
IO(std::io::Error),
}

impl From<io::Error> for CheckDiffError {
fn from(error: io::Error) -> Self {
CheckDiffError::IO(error)
}
}

impl From<GitError> for CheckDiffError {
fn from(error: GitError) -> Self {
CheckDiffError::FailedGit(error)
}
}

impl From<Utf8Error> for CheckDiffError {
fn from(error: Utf8Error) -> Self {
CheckDiffError::FailedUtf8(error)
}
}

pub enum GitError {
FailedClone { stdout: Vec<u8>, stderr: Vec<u8> },
FailedRemoteAdd { stdout: Vec<u8>, stderr: Vec<u8> },
FailedFetch { stdout: Vec<u8>, stderr: Vec<u8> },
FailedSwitch { stdout: Vec<u8>, stderr: Vec<u8> },
IO(std::io::Error),
}

Expand All @@ -15,6 +53,35 @@ impl From<io::Error> for GitError {
}
}

// will be used in future PRs, just added to make the compiler happy
#[allow(dead_code)]
pub struct CheckDiffRunners {
feature_runner: RustfmtRunner,
src_runner: RustfmtRunner,
}

pub struct RustfmtRunner {
ld_library_path: String,
binary_path: PathBuf,
}

impl RustfmtRunner {
fn get_binary_version(&self) -> Result<String, CheckDiffError> {
let Ok(command) = Command::new(&self.binary_path)
.env("LD_LIBRARY_PATH", &self.ld_library_path)
.args(["--version"])
.output()
else {
return Err(CheckDiffError::FailedBinaryVersioning(
self.binary_path.clone(),
));
};

let binary_version = std::str::from_utf8(&command.stdout)?.trim();
return Ok(binary_version.to_string());
}
}

/// Clone a git repository
///
/// Parameters:
Expand Down Expand Up @@ -47,6 +114,62 @@ pub fn clone_git_repo(url: &str, dest: &Path) -> Result<(), GitError> {
return Ok(());
}

pub fn git_remote_add(url: &str) -> Result<(), GitError> {
let git_cmd = Command::new("git")
.args(["remote", "add", "feature", url])
.output()?;

// if the git command does not return successfully,
// any command on the repo will fail. So fail fast.
if !git_cmd.status.success() {
let error = GitError::FailedRemoteAdd {
stdout: git_cmd.stdout,
stderr: git_cmd.stderr,
};
return Err(error);
}

info!("Successfully added remote: {url}");
return Ok(());
}

pub fn git_fetch(branch_name: &str) -> Result<(), GitError> {
let git_cmd = Command::new("git")
.args(["fetch", "feature", branch_name])
.output()?;

// if the git command does not return successfully,
// any command on the repo will fail. So fail fast.
if !git_cmd.status.success() {
let error = GitError::FailedFetch {
stdout: git_cmd.stdout,
stderr: git_cmd.stderr,
};
return Err(error);
}

info!("Successfully fetched: {branch_name}");
return Ok(());
}

pub fn git_switch(git_ref: &str, should_detach: bool) -> Result<(), GitError> {
let detach_arg = if should_detach { "--detach" } else { "" };
let args = ["switch", git_ref, detach_arg];
let output = Command::new("git")
.args(args.iter().filter(|arg| !arg.is_empty()))
.output()?;
if !output.status.success() {
tracing::error!("Git switch failed: {output:?}");
let error = GitError::FailedSwitch {
stdout: output.stdout,
stderr: output.stderr,
};
return Err(error);
}
info!("Successfully switched to {git_ref}");
return Ok(());
}

pub fn change_directory_to_path(dest: &Path) -> io::Result<()> {
let dest_path = Path::new(&dest);
env::set_current_dir(&dest_path)?;
Expand All @@ -56,3 +179,94 @@ pub fn change_directory_to_path(dest: &Path) -> io::Result<()> {
);
return Ok(());
}

pub fn get_ld_library_path() -> Result<String, CheckDiffError> {
let Ok(command) = Command::new("rustc").args(["--print", "sysroot"]).output() else {
return Err(CheckDiffError::FailedCommand("Error getting sysroot"));
};
let sysroot = std::str::from_utf8(&command.stdout)?.trim_end();
let ld_lib_path = format!("{}/lib", sysroot);
return Ok(ld_lib_path);
}

pub fn get_cargo_version() -> Result<String, CheckDiffError> {
let Ok(command) = Command::new("cargo").args(["--version"]).output() else {
return Err(CheckDiffError::FailedCargoVersion(
"Failed to obtain cargo version",
));
};

let cargo_version = std::str::from_utf8(&command.stdout)?.trim_end();
return Ok(cargo_version.to_string());
}

/// Obtains the ld_lib path and then builds rustfmt from source
/// If that operation succeeds, the source is then copied to the output path specified
pub fn build_rustfmt_from_src(binary_path: PathBuf) -> Result<RustfmtRunner, CheckDiffError> {
//Because we're building standalone binaries we need to set `LD_LIBRARY_PATH` so each
// binary can find it's runtime dependencies.
// See https://github.com/rust-lang/rustfmt/issues/5675
// This will prepend the `LD_LIBRARY_PATH` for the master rustfmt binary
let ld_lib_path = get_ld_library_path()?;

info!("Building rustfmt from source");
let Ok(_) = Command::new("cargo")
.args(["build", "-q", "--release", "--bin", "rustfmt"])
.output()
else {
return Err(CheckDiffError::FailedSourceBuild(
"Error building rustfmt from source",
));
};

std::fs::copy("target/release/rustfmt", &binary_path)?;

return Ok(RustfmtRunner {
ld_library_path: ld_lib_path,
binary_path,
});
}

// Compiles and produces two rustfmt binaries.
// One for the current master, and another for the feature branch
// Parameters:
// dest: Directory where rustfmt will be cloned
pub fn compile_rustfmt(
dest: &Path,
remote_repo_url: String,
feature_branch: String,
commit_hash: Option<String>,
) -> Result<CheckDiffRunners, CheckDiffError> {
const RUSTFMT_REPO: &str = "https://github.com/rust-lang/rustfmt.git";

clone_git_repo(RUSTFMT_REPO, dest)?;
change_directory_to_path(dest)?;
git_remote_add(remote_repo_url.as_str())?;
git_fetch(feature_branch.as_str())?;

let cargo_version = get_cargo_version()?;
info!("Compiling with {}", cargo_version);
let src_runner = build_rustfmt_from_src(dest.join("src_rustfmt"))?;
let should_detach = commit_hash.is_some();
git_switch(
commit_hash.unwrap_or(feature_branch).as_str(),
should_detach,
)?;

let feature_runner = build_rustfmt_from_src(dest.join("feature_rustfmt"))?;
info!("RUSFMT_BIN {}", src_runner.get_binary_version()?);
info!(
"Runtime dependencies for (src) rustfmt -- LD_LIBRARY_PATH: {}",
src_runner.ld_library_path
);
info!("FEATURE_BIN {}", feature_runner.get_binary_version()?);
info!(
"Runtime dependencies for (feature) rustfmt -- LD_LIBRARY_PATH: {}",
feature_runner.ld_library_path
);

return Ok(CheckDiffRunners {
src_runner,
feature_runner,
});
}
16 changes: 15 additions & 1 deletion check_diff/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use check_diff::compile_rustfmt;
use clap::Parser;
use tempfile::Builder;
use tracing::info;

/// Inputs for the check_diff script
#[derive(Parser)]
Expand All @@ -17,5 +20,16 @@ struct CliInputs {
}

fn main() {
let _args = CliInputs::parse();
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_env("CHECK_DIFF_LOG"))
.init();
let args = CliInputs::parse();
let tmp_dir = Builder::new().tempdir_in("").unwrap();
info!("Created tmp_dir {:?}", tmp_dir);
let _ = compile_rustfmt(
tmp_dir.path(),
args.remote_repo_url,
args.feature_branch,
args.commit_hash,
);
}
33 changes: 14 additions & 19 deletions src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,22 @@ fn argument_shape(
shape: Shape,
context: &RewriteContext<'_>,
) -> Option<Shape> {
match context.config.indent_style() {
let shape = match context.config.indent_style() {
IndentStyle::Block => {
if combine {
shape.offset_left(left)
shape.offset_left_opt(left)?
} else {
Some(
shape
.block_indent(context.config.tab_spaces())
.with_max_width(context.config),
)
shape
.block_indent(context.config.tab_spaces())
.with_max_width(context.config)
}
}
IndentStyle::Visual => shape
.visual_indent(0)
.shrink_left(left)
.and_then(|s| s.sub_width(right)),
}
.shrink_left_opt(left)?
.sub_width_opt(right)?,
};
Some(shape)
}

fn format_derive(
Expand Down Expand Up @@ -127,8 +126,8 @@ fn format_derive(
context,
)?;
let one_line_shape = shape
.offset_left("[derive()]".len() + prefix.len())?
.sub_width("()]".len())?;
.offset_left_opt("[derive()]".len() + prefix.len())?
.sub_width_opt("()]".len())?;
let one_line_budget = one_line_shape.width;

let tactic = definitive_tactic(
Expand Down Expand Up @@ -295,7 +294,7 @@ impl Rewrite for ast::MetaItem {
&path,
list.iter(),
// 1 = "]"
shape.sub_width(1).max_width_error(shape.width, self.span)?,
shape.sub_width(1, self.span)?,
self.span,
context.config.attr_fn_like_width(),
Some(if has_trailing_comma {
Expand All @@ -308,9 +307,7 @@ impl Rewrite for ast::MetaItem {
ast::MetaItemKind::NameValue(ref lit) => {
let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?;
// 3 = ` = `
let lit_shape = shape
.shrink_left(path.len() + 3)
.max_width_error(shape.width, self.span)?;
let lit_shape = shape.shrink_left(path.len() + 3, self.span)?;
// `rewrite_literal` returns `None` when `lit` exceeds max
// width. Since a literal is basically unformattable unless it
// is a string literal (and only if `format_strings` is set),
Expand Down Expand Up @@ -367,9 +364,7 @@ impl Rewrite for ast::Attribute {
}

// 1 = `[`
let shape = shape
.offset_left(prefix.len() + 1)
.max_width_error(shape.width, self.span)?;
let shape = shape.offset_left(prefix.len() + 1, self.span)?;
Ok(meta.rewrite_result(context, shape).map_or_else(
|_| snippet.to_owned(),
|rw| match &self.kind {
Expand Down
1 change: 1 addition & 0 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ fn style_edition_from_style_edition_str(edition_str: &str) -> Result<StyleEditio
"2018" => Ok(StyleEdition::Edition2018),
"2021" => Ok(StyleEdition::Edition2021),
"2024" => Ok(StyleEdition::Edition2024),
"2027" => Ok(StyleEdition::Edition2027),
_ => Err(format_err!("Invalid value for `--style-edition`")),
}
}
Expand Down
Loading

0 comments on commit 46c9cfc

Please sign in to comment.