Skip to content

Commit

Permalink
feat(toml): Allow adding/removing from cargo scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Nov 25, 2024
1 parent b4a8940 commit 6fa341d
Show file tree
Hide file tree
Showing 17 changed files with 130 additions and 119 deletions.
2 changes: 2 additions & 0 deletions src/cargo/util/toml_mut/dependency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,8 @@ mod tests {
let mut local = LocalManifest {
path: crate_root.clone(),
manifest,
embedded: None,
raw: toml.to_owned(),
};
assert_eq!(local.manifest.to_string(), toml);
let gctx = GlobalContext::default().unwrap();
Expand Down
85 changes: 82 additions & 3 deletions src/cargo/util/toml_mut/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::core::dependency::DepKind;
use crate::core::{FeatureValue, Features, Workspace};
use crate::util::closest;
use crate::util::interning::InternedString;
use crate::util::toml::{is_embedded, ScriptSource};
use crate::{CargoResult, GlobalContext};

/// Dependency table to add deps to.
Expand Down Expand Up @@ -245,6 +246,8 @@ pub struct LocalManifest {
pub path: PathBuf,
/// Manifest contents.
pub manifest: Manifest,
pub raw: String,
pub embedded: Option<Embedded>,
}

impl Deref for LocalManifest {
Expand All @@ -267,18 +270,56 @@ impl LocalManifest {
if !path.is_absolute() {
anyhow::bail!("can only edit absolute paths, got {}", path.display());
}
let data = cargo_util::paths::read(&path)?;
let raw = cargo_util::paths::read(&path)?;
let mut data = raw.clone();
let mut embedded = None;
if is_embedded(path) {
let source = ScriptSource::parse(&data)?;
if let Some(frontmatter) = source.frontmatter() {
embedded = Some(Embedded::exists(&data, frontmatter));
data = frontmatter.to_owned();
} else if let Some(shebang) = source.shebang() {
embedded = Some(Embedded::after(&data, shebang));
data = String::new();
} else {
embedded = Some(Embedded::start());
data = String::new();
}
}
let manifest = data.parse().context("Unable to parse Cargo.toml")?;
Ok(LocalManifest {
manifest,
path: path.to_owned(),
raw,
embedded,
})
}

/// Write changes back to the file.
pub fn write(&self) -> CargoResult<()> {
let s = self.manifest.data.to_string();
let new_contents_bytes = s.as_bytes();
let mut manifest = self.manifest.data.to_string();
let raw = match self.embedded.as_ref() {
Some(Embedded::Implicit(start)) => {
if !manifest.ends_with("\n") {
manifest.push_str("\n");
}
let fence = "---\n";
let prefix = &self.raw[0..*start];
let suffix = &self.raw[*start..];
let empty_line = if prefix.is_empty() { "\n" } else { "" };
format!("{prefix}{fence}{manifest}{fence}{empty_line}{suffix}")
}
Some(Embedded::Explicit(span)) => {
if !manifest.ends_with("\n") {
manifest.push_str("\n");
}
let prefix = &self.raw[0..span.start];
let suffix = &self.raw[span.end..];
format!("{prefix}{manifest}{suffix}")
}
None => manifest,
};
let new_contents_bytes = raw.as_bytes();

cargo_util::paths::write_atomic(&self.path, new_contents_bytes)
}
Expand Down Expand Up @@ -531,6 +572,44 @@ impl std::fmt::Display for LocalManifest {
}
}

#[derive(Clone, Debug)]
pub enum Embedded {
Implicit(usize),
Explicit(std::ops::Range<usize>),
}

impl Embedded {
fn start() -> Self {
Self::Implicit(0)
}

fn after(input: &str, after: &str) -> Self {
let span = substr_span(input, after);
let end = span.end;
Self::Implicit(end)
}

fn exists(input: &str, exists: &str) -> Self {
let span = substr_span(input, exists);
Self::Explicit(span)
}
}

fn substr_span(haystack: &str, needle: &str) -> std::ops::Range<usize> {
let haystack_start_ptr = haystack.as_ptr();
let haystack_end_ptr = haystack[haystack.len()..haystack.len()].as_ptr();

let needle_start_ptr = needle.as_ptr();
let needle_end_ptr = needle[needle.len()..needle.len()].as_ptr();

assert!(needle_end_ptr < haystack_end_ptr);
assert!(haystack_start_ptr <= needle_start_ptr);
let start = needle_start_ptr as usize - haystack_start_ptr as usize;
let end = start + needle.len();

start..end
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
enum DependencyStatus {
None,
Expand Down
2 changes: 1 addition & 1 deletion tests/testsuite/cargo_add/script_bare/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn case() {
.arg_line("--manifest-path cargo-test-fixture.rs my-package")
.current_dir(cwd)
.assert()
.failure()
.success()
.stdout_eq(str![""])
.stderr_eq(file!["stderr.term.svg"]);

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
---
[dependencies]
my-package = "99999.0.0"
---

fn main() {}
26 changes: 6 additions & 20 deletions tests/testsuite/cargo_add/script_bare/stderr.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tests/testsuite/cargo_add/script_frontmatter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn case() {
.arg_line("--manifest-path cargo-test-fixture.rs my-package")
.current_dir(cwd)
.assert()
.failure()
.success()
.stdout_eq(str![""])
.stderr_eq(file!["stderr.term.svg"]);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
---
[package]
edition = "2015"

[dependencies]
my-package = "99999.0.0"
---

fn main() {
Expand Down
28 changes: 6 additions & 22 deletions tests/testsuite/cargo_add/script_frontmatter/stderr.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tests/testsuite/cargo_add/script_shebang/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn case() {
.arg_line("--manifest-path cargo-test-fixture.rs my-package")
.current_dir(cwd)
.assert()
.failure()
.success()
.stdout_eq(str![""])
.stderr_eq(file!["stderr.term.svg"]);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#!/usr/bin/env cargo
---
[dependencies]
my-package = "99999.0.0"
---

fn main() {}
26 changes: 6 additions & 20 deletions tests/testsuite/cargo_add/script_shebang/stderr.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tests/testsuite/cargo_remove/script/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn case() {
.arg_line("--manifest-path cargo-remove-test-fixture.rs docopt")
.current_dir(cwd)
.assert()
.failure()
.success()
.stdout_eq(str![""])
.stderr_eq(file!["stderr.term.svg"]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ edition = "2015"
semver = "0.1.0"

[dependencies]
docopt = "0.6"
rustc-serialize = "0.4"
semver = "0.1"
toml = "0.1"
Expand Down
28 changes: 5 additions & 23 deletions tests/testsuite/cargo_remove/script/stderr.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tests/testsuite/cargo_remove/script_last/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn case() {
.arg_line("--manifest-path cargo-remove-test-fixture.rs docopt")
.current_dir(cwd)
.assert()
.failure()
.success()
.stdout_eq(str![""])
.stderr_eq(file!["stderr.term.svg"]);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
[dependencies]
docopt = "0.6"

---

fn main() {
Expand Down
Loading

0 comments on commit 6fa341d

Please sign in to comment.