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

feat: Initial support for single-file packages #12245

Merged
merged 10 commits into from Jun 12, 2023
Merged

Conversation

epage
Copy link
Contributor

@epage epage commented Jun 9, 2023

What does this PR try to resolve?

This is the first step towards #12207. In particular, this focuses on pulling in the demo roughly as-is to serve as a baseline for further PRs. I have a couple months of runtime (multiple times a week) using the version of the demo included here.

How should we test and review this PR?

Commit-by-commit. Most likely, the last (docs) commit should be done first to provide context for the others.

Naming is hard. I came up with these terms just so we can have ways to refer to them. Feedback is welcome.

  • -Zscript for this general feature (not great but didn't want to spend too long coming up with a throwaway name)
  • "single-file package": Rust code and a cargo manifest in a single file
  • "embedded manifest": the explicit manifest inside of a single-file package
  • "manifest command": when we interpret cargo <name> as referring to a single-file package, and similar to "built-in commands" and "external commands".

Keep in mind that this is a very hacky solution with many deficiencies and is mostly starting as a baseline for implementing and reviewing those improvements, including

  • Switching from regex to syn for extracting manifests for greater resilience
  • Matching cargo news logic when sanitizing the inferred package name
  • Allowing cargo <name> to also be a Cargo.toml file (for consistency in where manifests are accepted)
  • Allowing single-file packages to be used wherever a manifest is accepted

To minimize conflict pain, I would ask that we consider what feedback can be handled in a follow up (though still mention it!). It'll be much easier creating multiple, independent PRs once this baseline is merged to address concerns.

Additional information

The only affect for people on stable is that they may get a warning if they have an external subcommand that will be shadowed when this feature is implemented. This will allow us to collect feedback, without blocking people, so we can have an idea of how "safe" our precedence scheme is for interpreting cargo <name>.

As of right now, aliases with a . in them will be ignored (well, technically their suffix will be exposed as an alias). We directly inject the name into a lookup string into the config that uses . as the separator, so we drill down until we get to the leaf element. Ideally, we would be generating / parsing the lookup key using TOML key syntax so we can better report that this won't be supported after this change :)

@rustbot
Copy link
Collaborator

rustbot commented Jun 9, 2023

r? @weihanglo

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added A-cli Area: Command-line interface, option parsing, etc. A-documenting-cargo-itself Area: Cargo's documentation A-manifest Area: Cargo.toml issues A-testing-cargo-itself Area: cargo's tests A-unstable Area: nightly unstable support Command-run S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 9, 2023
@rustbot rustbot added the A-infrastructure Area: infrastructure around the cargo repo, ci, releases, etc. label Jun 9, 2023
epage added a commit to epage/cargo that referenced this pull request Jun 9, 2023
This should be more resilient to false positives like in rust-lang#12245 where a
string contains `println`.
epage added a commit to epage/cargo that referenced this pull request Jun 9, 2023
This should be more resilient to false positives like in rust-lang#12245 where a
string contains `println`.
bors added a commit that referenced this pull request Jun 9, 2023
chore: Migrate print-ban from test to clippy

This should be more resilient to false positives like in #12245 where a string contains `println`.

See also #12224
@epage epage force-pushed the script branch 2 times, most recently from 0d27d58 to 382e5db Compare June 9, 2023 15:48
epage added 2 commits June 9, 2023 13:16
I decided to start things off fairly simple.  It either looks like the user is
specifying a manifest or they aren't.  This is assuming we only need to
handle `cargo foo.rs` and `cargo ./foo.rs` and not `cargo foo`.
I think in most shebang cases, path multiple components will present which makes
that a dead giveaway and likely to not overlap with aliases and
subcommands.

For reference, dlang's dub goes a lot further
1. Checks for the subcommand name being `-`
2. Checks if subcommand name ends with `.d`
3. Checks if subcommand name is built-in
4. Checks if a file with the subcommand name exists
5. Checks if a file with the subcommand name + `.d` exists

This would allow a `run.d` to override `dub-run` which doesn't seem
good.
@epage epage force-pushed the script branch 2 times, most recently from a207282 to 199fb6f Compare June 9, 2023 18:49
@epage
Copy link
Contributor Author

epage commented Jun 9, 2023

FYI @weihanglo I've finally appeased the CI gods

Copy link
Member

@weihanglo weihanglo left a comment

Choose a reason for hiding this comment

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

Just did the first round review, yet I skipped the juicy part — toml/embedded.rs. Thanks for making this happen. I'll get back in the next few days!

@@ -13,6 +13,7 @@ exclude = [
[workspace.dependencies]
anyhow = "1.0.47"
base64 = "0.21.0"
blake3 = "1.3.3"
Copy link
Member

Choose a reason for hiding this comment

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

Could you clarify that why we need blake3? Is it only for performance?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was just looking for what a recommended hashing algorithm is. This is used for creating the temporary manifest on disk and will be going away when we get native support for embedded manifests. Similarly, we'll be dropping the regex dependency when we change up the parsing of embedded manifests.

Copy link
Member

Choose a reason for hiding this comment

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

Not really a blocker but maybe something like this at this moment would better.

diff --git a/src/cargo/util/toml/embedded.rs b/src/cargo/util/toml/embedded.rs
index 875ec6a4b..833f90ce9 100644
--- a/src/cargo/util/toml/embedded.rs
+++ b/src/cargo/util/toml/embedded.rs
@@ -68,7 +68,7 @@ impl RawScript {
         config: &Config,
         target_dir: &std::path::Path,
     ) -> CargoResult<std::path::PathBuf> {
-        let hash = self.hash().to_string();
+        let hash = self.hash();
         assert_eq!(hash.len(), 64);
         let mut workspace_root = target_dir.to_owned();
         workspace_root.push("eval");
@@ -207,8 +207,8 @@ impl RawScript {
         Ok(slug)
     }
 
-    fn hash(&self) -> blake3::Hash {
-        blake3::hash(self.body.as_bytes())
+    fn hash(&self) -> String {
+        cargo_util::Sha256::new().update(self.body.as_bytes()).finish_hex()
     }
 }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can we defer this out? Scott already has a branch where the hashing can be dropped, so dropping it should be a quick follow on. My hope with this change was to have cargo-script-mvs as a baseline and would rather not have churn related to throwaway parts of the PR

Copy link
Member

Choose a reason for hiding this comment

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

A tiny drawback of introducing new dependendies: need to add license exceptions on Rust side rust-lang/rust#112601.

This is not this PR's fault. It is the license check is out of sync between rust-lang/rust and rust-lang/cargo.

@@ -101,3 +105,16 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
}
})
}

pub fn is_manifest_command(arg: &str) -> bool {
Copy link
Member

@weihanglo weihanglo Jun 9, 2023

Choose a reason for hiding this comment

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

(not a blocker)
“Manifest commands” is already a term, though its definition is not pretty clear to me.

https://doc.rust-lang.org/nightly/cargo/commands/manifest-commands.html

crates/cargo-test-support/src/lib.rs Show resolved Hide resolved
src/bin/cargo/cli.rs Show resolved Hide resolved
src/bin/cargo/cli.rs Outdated Show resolved Hide resolved
tests/testsuite/script.rs Outdated Show resolved Hide resolved
deny.toml Show resolved Hide resolved
src/bin/cargo/cli.rs Show resolved Hide resolved
epage added 4 commits June 9, 2023 22:02
This will give us a window to collect feedback on if this affects
anyone.
This is no where near the implementation we want but I think we should
develop incrementally on top of what we already have.

See https://github.com/epage/cargo-script-mvs/tree/main
This is written to reflect the current implementation though some parts
might read a little weird because I didn't want to write throw-away
documentation for when we change this.  For example, single-file
packages are currently only supported in `cargo <command>` and not as
manifest paths but this will change.
Copy link
Member

@weihanglo weihanglo left a comment

Choose a reason for hiding this comment

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

Given this is an implementation for an eRFC, and it has only little impact on the current behavior of Cargo, I am pretty open to merge it as-is.

@epage I left some comment for potential cleanup but feel free to r=weihanglo if they don't make sense to do at this moment. I think what to should do is writing down the decisions needed to be made and move on.

cargo.before Outdated Show resolved Hide resolved
src/bin/cargo/cli.rs Show resolved Hide resolved
src/bin/cargo/cli.rs Outdated Show resolved Hide resolved
src/bin/cargo/cli.rs Outdated Show resolved Hide resolved
src/bin/cargo/cli.rs Show resolved Hide resolved
Comment on lines +12 to +15
manifest: String,
body: String,
path: std::path::PathBuf,
Copy link
Member

Choose a reason for hiding this comment

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

(not a blocker)
It's not immediately clear to me what these field are for. Could we have a little bit docs for them?

src/cargo/util/toml/embedded.rs Outdated Show resolved Hide resolved
fn extract_manifest(comment: &str) -> CargoResult<Option<String>> {
use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag};

// To match librustdoc/html/markdown.rs, opts.
Copy link
Member

@weihanglo weihanglo Jun 12, 2023

Choose a reason for hiding this comment

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

Should we link to a specific commit for traceability?

release
.entry("strip".to_owned())
.or_insert_with(|| toml::Value::Boolean(true));
Copy link
Member

Choose a reason for hiding this comment

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

(not a blocker)
We could have a discussion around the default compiler settings for -Zscript, like this strip = true.

Ok(manifest)
}

fn package_name(&self) -> CargoResult<String> {
Copy link
Member

Choose a reason for hiding this comment

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

(not a blocker)

Probably need a discussion around this escaping rule?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A follow up PR is planned to deal with escaping rules and I wouldn't be surprised if they are brought up again through the experiment

fn expand_manifest_(&self, config: &Config) -> CargoResult<toml::Table> {
let mut manifest: toml::Table = toml::from_str(&self.manifest)?;

for key in ["workspace", "lib", "bin", "example", "test", "bench"] {
Copy link
Member

Choose a reason for hiding this comment

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

(not a blocker)
Should we have an exhaustive list of what we allow instead?

@epage epage force-pushed the script branch 3 times, most recently from 8d638bd to 6b0b5a8 Compare June 12, 2023 18:30
Copy link
Member

@weihanglo weihanglo left a comment

Choose a reason for hiding this comment

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

This is generally good to merge. Let's see how big the impact will be on the Rust ecosystem 🎉🎉🎉. Thank you for making this come true!

Before I forget, let me jot down things to do/explore/clean up.

  • Dependency clean-up (blake3, regex, etc.)
  • Official name of the cargo <script>.rs. The current choice is “manifest command”.
  • Internal documentations of new items and modules for this new feature.
  • Default set of compiler flags for -Zscript.
  • Escaping rules of the package name generated.
  • Whether to use an exhaustive list for allowed manifest fields.

@weihanglo
Copy link
Member

@bors r+

@bors
Copy link
Collaborator

bors commented Jun 12, 2023

📌 Commit 6b0b5a8 has been approved by weihanglo

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 12, 2023
@bors
Copy link
Collaborator

bors commented Jun 12, 2023

⌛ Testing commit 6b0b5a8 with merge f8fef7a...

@epage
Copy link
Contributor Author

epage commented Jun 12, 2023

I've noted some of those down on #12207 since we'll likely want to review those when the experiment is ready for the next stage

@bors
Copy link
Collaborator

bors commented Jun 12, 2023

☀️ Test successful - checks-actions
Approved by: weihanglo
Pushing f8fef7a to master...

@bors bors merged commit f8fef7a into rust-lang:master Jun 12, 2023
21 checks passed
@epage epage deleted the script branch June 12, 2023 19:41
bors added a commit to rust-lang-ci/rust that referenced this pull request Jun 15, 2023
Update cargo

11 commits in 49b6d9e179a91cf7645142541c9563443f64bf2b..0c14026aa84ee2ec4c67460c0a18abc8519ca6b2
2023-06-09 17:21:19 +0000 to 2023-06-14 18:43:05 +0000
- fix(embedded): Don't append hash to bin names (rust-lang/cargo#12269)
- Fix version requirement example in Dependency Resolution, SemVer compatibility section (rust-lang/cargo#12267)
- Update triagebot links. (rust-lang/cargo#12265)
- Show a better error when container tests fail. (rust-lang/cargo#12264)
- chore: update dependencies (rust-lang/cargo#12261)
- refactor(embedded) (rust-lang/cargo#12262)
- docs: clarify the use of `default` branch instead of `main` by default (rust-lang/cargo#12251)
- docs: update changelog for 1.71 backport and 1.72 (rust-lang/cargo#12256)
- feat: Initial support for single-file packages (rust-lang/cargo#12245)
- test(z-flags): Verify `-Z` flags list is sorted (rust-lang/cargo#12224)
- refactor: registry data kinds cleanup (rust-lang/cargo#12248)

---

This commit also update LICENSE exceptions, as Cargo introduced a newer version of `dunce` and `blake3` as dependencies.

r? `@ghost`
RalfJung pushed a commit to RalfJung/miri that referenced this pull request Jun 16, 2023
Update cargo

11 commits in 49b6d9e179a91cf7645142541c9563443f64bf2b..0c14026aa84ee2ec4c67460c0a18abc8519ca6b2
2023-06-09 17:21:19 +0000 to 2023-06-14 18:43:05 +0000
- fix(embedded): Don't append hash to bin names (rust-lang/cargo#12269)
- Fix version requirement example in Dependency Resolution, SemVer compatibility section (rust-lang/cargo#12267)
- Update triagebot links. (rust-lang/cargo#12265)
- Show a better error when container tests fail. (rust-lang/cargo#12264)
- chore: update dependencies (rust-lang/cargo#12261)
- refactor(embedded) (rust-lang/cargo#12262)
- docs: clarify the use of `default` branch instead of `main` by default (rust-lang/cargo#12251)
- docs: update changelog for 1.71 backport and 1.72 (rust-lang/cargo#12256)
- feat: Initial support for single-file packages (rust-lang/cargo#12245)
- test(z-flags): Verify `-Z` flags list is sorted (rust-lang/cargo#12224)
- refactor: registry data kinds cleanup (rust-lang/cargo#12248)

---

This commit also update LICENSE exceptions, as Cargo introduced a newer version of `dunce` and `blake3` as dependencies.

r? `@ghost`
bors added a commit that referenced this pull request Jun 17, 2023
fix(embedded): Align package name sanitization with cargo-new

### What does this PR try to resolve?

This is a follow up to #12245 which is working to resolve the tracking issue #12207

This first aligns sanitization of package names with the central package name validation logic, putting the code next to each other so they can more easily stay in sync.

Oddly enough, cargo-new is stricter than our normal package-name validation.  I went ahead and sanitized along with that as well.

In working on this, I was bothered by
- the mix of `-` and `_` in file names because of sanitization, so I made it more consistent by detecting which the user is using
- -using `_` in bins, so I switched the default to `-`

### How should we test and review this PR?

One existing test covers a variety of sanitization needs

Another existing test hit one of the other cases (`test` being reserved)

### Additional information

For implementation convenience, I changed the directory we write the manifest to.  The impact of this should be minimal since
- We reuse the full file name, so if it worked for the user it should work for us
- We should be moving away from the temp manifest in future commits
bors added a commit that referenced this pull request Jun 17, 2023
refactor(embedded): Switch to `syn` for parsing doc comments

This is a follow up to #12245 which is working to resolve #12207

The hope is this will result in more resilient comment handling, being more consistent with rustdoc.

I also hoped for less code but `syn` is doing less than I had expected, requiring us to copy code over from other parts of rust.  It seems every proc macro has to do this but there is no guide to it, so they all do it differently, only covering the cases they thought to test for.

Note that this still won't support `include_str!()`.
bors added a commit that referenced this pull request Jun 17, 2023
refactor(embedded): Switch to `syn` for parsing doc comments

This is a follow up to #12245 which is working to resolve #12207

The hope is this will result in more resilient comment handling, being more consistent with rustdoc.

I also hoped for less code but `syn` is doing less than I had expected, requiring us to copy code over from other parts of rust.  It seems every proc macro has to do this but there is no guide to it, so they all do it differently, only covering the cases they thought to test for.

Note that this still won't support `include_str!()`.
@ehuss ehuss added this to the 1.72.0 milestone Jun 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-cli Area: Command-line interface, option parsing, etc. A-documenting-cargo-itself Area: Cargo's documentation A-infrastructure Area: infrastructure around the cargo repo, ci, releases, etc. A-manifest Area: Cargo.toml issues A-testing-cargo-itself Area: cargo's tests A-unstable Area: nightly unstable support Command-run S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants