Skip to content

Add stdarch-gen-common: shared check/bless harness for generators#2157

Open
xonx4l wants to merge 3 commits into
rust-lang:mainfrom
xonx4l:stdarch-gen-common
Open

Add stdarch-gen-common: shared check/bless harness for generators#2157
xonx4l wants to merge 3 commits into
rust-lang:mainfrom
xonx4l:stdarch-gen-common

Conversation

@xonx4l

@xonx4l xonx4l commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

This PR adds a library crate stdarch-gen-common that gives every generator three modes -:

  1. Write - Generator writes files straight into the committed location.
  2. Check - Generator write into a temporary directory . The crate diffs it against committed and fails on any mismatch without touching the working copy .
  3. Bless - Generator writes into a temp directory the crate then mirrors temp over committed. Adding, overwriting, and deleting files as needed.

Mode is picked via the STDARCH_GEN_MODE env var. The harness only touches files the generator explicitly lists as its own so hand-written files in the same directory are safe.

This PR also hooks stdarch-gen-hexagon to use it as the first example.

r? @folkertdev

@Kobzol

Kobzol commented Jun 9, 2026

Copy link
Copy Markdown
Member

For a bit more context, this is done for the stdarch GSoC project, where we try to integrate stdarch's tests in rust-lang/rust's CI. We want to move the blessing logic out of the CI YAML files and into Rust, to make it easier to reuse, and also share code amongst the various generators.

I'll take a look, but also CC @folkertdev , in case you have in mind who owns this code amongst the stdarch maintainers and who could also chime in.

@rustbot rustbot assigned folkertdev and unassigned Kobzol Jun 9, 2026

@Kobzol Kobzol left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for creating the crate! I left a few comments.

View changes since this review

use std::path::{Path, PathBuf};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mode {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does Write differ from Bless? I'd expect those two modes to be the same. Could you please add some doc comments on the mode to explain what the individual modes mean? Thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added doc comments .The two modes hit different code paths in run write skips the owned-list filter entirely.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments use a lot of terms and I'm not sure what do they mean 😆

What is target directory? How does "committed tree" differ from "owned list"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha I used those in order to differentiate better and more readable but I think rewording made them confusing . Here target directory and committed tree mean the same thing the folder the generator writes into to make it less confusing I will simplify it naming to just committed and owned list means the list of file names inside that folder that this generator is responsible for .

}

impl Mode {
pub fn from_env() -> Self {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a doc comment here that explains how to use the function, i.e. which env var it expects to read and what are the possible values.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added .

Comment thread crates/stdarch-gen-common/src/lib.rs Outdated

// owned is the list of relative paths the generator manages. Files in
// committed not listed here are left untouched by Bless and ignored by Check.
pub fn run<F, E>(committed: &Path, owned: &[&str], mode: Mode, generate: F) -> Result<()>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a doc comment that explains in more detail what the function is supposed to be doing? The signature is kinda complex.

I think that we can simplify the function by changing it to only work with a single subdirectory, it doesn't really need to handle slices and multiple paths at once.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added doc comment explaining the signature . I kept the slice instead of switching to one folder per generator because generated files are aligned next to hand-written ones in the same folder . if we owned the whole folder bless would delete those hand-written files. Thank you!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand, you can still just take the for loop that is now executed inside run, and perform it outside the function, by just passing it a since owned string, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes makes sense , the the loop can move out.

Comment thread crates/stdarch-gen-common/src/lib.rs Outdated
write!(f, "{}: committed but no longer generated", path.display())
}
MismatchKind::ContentsDiffer => write!(f, "{}: contents differ", path.display()),
MismatchKind::MissingFromGenerated => write!(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we bless, it can happen that the new blessed output has less files than before, right? 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes there's a case for it already MissingFromGenerated. Added the comment that explains . Thank you!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant was that MissingFromGenerated shouldn't happen, if something is not present in the generated output, we should delete it from the committed tree.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok will drop.

@Kobzol Kobzol left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'll have to examine how the generator behaves a bit deeper (I'll try to do that on Monday), because I'm still quite surprised from the behavior here 😅 I think that we might wanna do some targeted changes to the generator and the directory layout to make blessing simpler, if the complexity here is caused by the current directory layout.

View changes since this review

use std::path::{Path, PathBuf};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mode {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments use a lot of terms and I'm not sure what do they mean 😆

What is target directory? How does "committed tree" differ from "owned list"?

Comment thread crates/stdarch-gen-common/src/lib.rs Outdated
write!(f, "{}: committed but no longer generated", path.display())
}
MismatchKind::ContentsDiffer => write!(f, "{}: contents differ", path.display()),
MismatchKind::MissingFromGenerated => write!(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant was that MissingFromGenerated shouldn't happen, if something is not present in the generated output, we should delete it from the committed tree.

@xonx4l

xonx4l commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

I think I'll have to examine how the generator behaves a bit deeper (I'll try to do that on Monday), because I'm still quite surprised from the behavior here 😅 I think that we might wanna do some targeted changes to the generator and the directory layout to make blessing simpler, if the complexity here is caused by the current directory layout.

View changes since this review

Yes targeted changes to the generator will likely make this crate much simpler. Btw we are in a fixing loop :)

@folkertdev folkertdev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this seems fine as a design. I'd probably just do the other generators in a separate PR using this as a foundation.

View changes since this review

match std::env::var("STDARCH_GEN_MODE").as_deref() {
Ok("check") => Mode::Check,
Ok("bless") => Mode::Bless,
_ => Mode::Write,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather panic on an unknown value? Unless this is standard practice somehow?

/// - [`Mode::Bless`]: runs the generator into a temp dir and copies `owned`
/// into `committed`, or removes `committed`'s copy if the generator no
/// longer produces it.
pub fn run<F, E>(committed: &Path, owned: &str, mode: Mode, generate: F) -> Result<()>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn run<F, E>(committed: &Path, owned: &str, mode: Mode, generate: F) -> Result<()>
pub fn run_generator<F, E>(committed: &Path, owned: &str, mode: Mode, generate: F) -> Result<()>

maybe? run itself is quite vague at the use site.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants