feat(toml): Allow adding/removing from cargo scripts
@ -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();
|
||||
|
@ -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.
|
||||
@ -245,6 +246,10 @@ pub struct LocalManifest {
|
||||
pub path: PathBuf,
|
||||
/// Manifest contents.
|
||||
pub manifest: Manifest,
|
||||
/// The raw, unparsed package file
|
||||
pub raw: String,
|
||||
/// Edit location for an embedded manifest, if relevant
|
||||
pub embedded: Option<Embedded>,
|
||||
}
|
||||
|
||||
impl Deref for LocalManifest {
|
||||
@ -267,18 +272,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)
|
||||
}
|
||||
@ -531,6 +574,51 @@ impl std::fmt::Display for LocalManifest {
|
||||
}
|
||||
}
|
||||
|
||||
/// Edit location for an embedded manifest
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Embedded {
|
||||
/// Manifest is implicit
|
||||
///
|
||||
/// This is the insert location for a frontmatter
|
||||
Implicit(usize),
|
||||
/// Manifest is explicit in a frontmatter
|
||||
///
|
||||
/// This is the span of the frontmatter body
|
||||
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,
|
||||
|
@ -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"]);
|
||||
|
||||
|
@ -1 +1,6 @@
|
||||
---
|
||||
[dependencies]
|
||||
my-package = "99999.0.0"
|
||||
---
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,8 @@
|
||||
<svg width="740px" height="254px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { background: #000000 }
|
||||
.fg-red { fill: #AA0000 }
|
||||
.fg-green { fill: #00AA00 }
|
||||
.fg-yellow { fill: #AA5500 }
|
||||
.container {
|
||||
padding: 0 10px;
|
||||
@ -21,29 +21,15 @@
|
||||
<text xml:space="preserve" class="container fg">
|
||||
<tspan x="10px" y="28px"><tspan class="fg-yellow bold">warning</tspan><tspan class="bold">:</tspan><tspan> `package.edition` is unspecified, defaulting to `[..]`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="46px"><tspan class="fg-red bold">error</tspan><tspan class="bold">:</tspan><tspan> Unable to parse Cargo.toml</tspan>
|
||||
<tspan x="10px" y="46px"><tspan class="fg-green bold"> Updating</tspan><tspan> `dummy-registry` index</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="64px">
|
||||
<tspan x="10px" y="64px"><tspan class="fg-green bold"> Adding</tspan><tspan> my-package v99999.0.0 to dependencies</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="82px"><tspan>Caused by:</tspan>
|
||||
<tspan x="10px" y="82px"><tspan class="fg-yellow bold">warning</tspan><tspan class="bold">:</tspan><tspan> `package.edition` is unspecified, defaulting to `[..]`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="100px"><tspan> Manifest not valid TOML</tspan>
|
||||
<tspan x="10px" y="100px"><tspan class="fg-green bold"> Locking</tspan><tspan> 1 package to latest [..]compatible version</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="118px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="136px"><tspan>Caused by:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="154px"><tspan> TOML parse error at line 1, column 4</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="172px"><tspan> |</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="190px"><tspan> 1 | fn main() {}</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="208px"><tspan> | ^</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="226px"><tspan> expected `.`, `=`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="244px">
|
||||
</tspan>
|
||||
</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
@ -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"]);
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
---
|
||||
[package]
|
||||
edition = "2015"
|
||||
|
||||
[dependencies]
|
||||
my-package = "99999.0.0"
|
||||
---
|
||||
|
||||
fn main() {
|
||||
|
@ -1,8 +1,8 @@
|
||||
<svg width="740px" height="236px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="740px" height="92px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { background: #000000 }
|
||||
.fg-red { fill: #AA0000 }
|
||||
.fg-green { fill: #00AA00 }
|
||||
.container {
|
||||
padding: 0 10px;
|
||||
line-height: 18px;
|
||||
@ -18,29 +18,13 @@
|
||||
<rect width="100%" height="100%" y="0" rx="4.5" class="bg" />
|
||||
|
||||
<text xml:space="preserve" class="container fg">
|
||||
<tspan x="10px" y="28px"><tspan class="fg-red bold">error</tspan><tspan class="bold">:</tspan><tspan> Unable to parse Cargo.toml</tspan>
|
||||
<tspan x="10px" y="28px"><tspan class="fg-green bold"> Updating</tspan><tspan> `dummy-registry` index</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="46px">
|
||||
<tspan x="10px" y="46px"><tspan class="fg-green bold"> Adding</tspan><tspan> my-package v99999.0.0 to dependencies</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="64px"><tspan>Caused by:</tspan>
|
||||
<tspan x="10px" y="64px"><tspan class="fg-green bold"> Locking</tspan><tspan> 1 package to latest [..]compatible version</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="82px"><tspan> Manifest not valid TOML</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="100px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="118px"><tspan>Caused by:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="136px"><tspan> TOML parse error at line 1, column 4</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="154px"><tspan> |</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="172px"><tspan> 1 | ---</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="190px"><tspan> | ^</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="208px"><tspan> expected `.`, `=`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="226px">
|
||||
<tspan x="10px" y="82px">
|
||||
</tspan>
|
||||
</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1016 B |
@ -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"]);
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
#!/usr/bin/env cargo
|
||||
---
|
||||
[dependencies]
|
||||
my-package = "99999.0.0"
|
||||
---
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,8 @@
|
||||
<svg width="740px" height="254px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { background: #000000 }
|
||||
.fg-red { fill: #AA0000 }
|
||||
.fg-green { fill: #00AA00 }
|
||||
.fg-yellow { fill: #AA5500 }
|
||||
.container {
|
||||
padding: 0 10px;
|
||||
@ -21,29 +21,15 @@
|
||||
<text xml:space="preserve" class="container fg">
|
||||
<tspan x="10px" y="28px"><tspan class="fg-yellow bold">warning</tspan><tspan class="bold">:</tspan><tspan> `package.edition` is unspecified, defaulting to `[..]`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="46px"><tspan class="fg-red bold">error</tspan><tspan class="bold">:</tspan><tspan> Unable to parse Cargo.toml</tspan>
|
||||
<tspan x="10px" y="46px"><tspan class="fg-green bold"> Updating</tspan><tspan> `dummy-registry` index</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="64px">
|
||||
<tspan x="10px" y="64px"><tspan class="fg-green bold"> Adding</tspan><tspan> my-package v99999.0.0 to dependencies</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="82px"><tspan>Caused by:</tspan>
|
||||
<tspan x="10px" y="82px"><tspan class="fg-yellow bold">warning</tspan><tspan class="bold">:</tspan><tspan> `package.edition` is unspecified, defaulting to `[..]`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="100px"><tspan> Manifest not valid TOML</tspan>
|
||||
<tspan x="10px" y="100px"><tspan class="fg-green bold"> Locking</tspan><tspan> 1 package to latest [..]compatible version</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="118px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="136px"><tspan>Caused by:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="154px"><tspan> TOML parse error at line 3, column 4</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="172px"><tspan> |</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="190px"><tspan> 3 | fn main() {}</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="208px"><tspan> | ^</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="226px"><tspan> expected `.`, `=`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="244px">
|
||||
</tspan>
|
||||
</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
@ -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"]);
|
||||
|
||||
|
@ -5,7 +5,6 @@ edition = "2015"
|
||||
semver = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
docopt = "0.6"
|
||||
rustc-serialize = "0.4"
|
||||
semver = "0.1"
|
||||
toml = "0.1"
|
||||
|
@ -1,8 +1,8 @@
|
||||
<svg width="740px" height="254px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="740px" height="92px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { background: #000000 }
|
||||
.fg-red { fill: #AA0000 }
|
||||
.fg-green { fill: #00AA00 }
|
||||
.fg-yellow { fill: #AA5500 }
|
||||
.container {
|
||||
padding: 0 10px;
|
||||
@ -21,29 +21,11 @@
|
||||
<text xml:space="preserve" class="container fg">
|
||||
<tspan x="10px" y="28px"><tspan class="fg-yellow bold">warning</tspan><tspan class="bold">:</tspan><tspan> `package.edition` is unspecified, defaulting to `[..]`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="46px"><tspan class="fg-red bold">error</tspan><tspan class="bold">:</tspan><tspan> Unable to parse Cargo.toml</tspan>
|
||||
<tspan x="10px" y="46px"><tspan class="fg-green bold"> Removing</tspan><tspan> docopt from dependencies</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="64px">
|
||||
<tspan x="10px" y="64px"><tspan class="fg-yellow bold">warning</tspan><tspan class="bold">:</tspan><tspan> `package.edition` is unspecified, defaulting to `[..]`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="82px"><tspan>Caused by:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="100px"><tspan> Manifest not valid TOML</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="118px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="136px"><tspan>Caused by:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="154px"><tspan> TOML parse error at line 1, column 4</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="172px"><tspan> |</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="190px"><tspan> 1 | ---</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="208px"><tspan> | ^</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="226px"><tspan> expected `.`, `=`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="244px">
|
||||
<tspan x="10px" y="82px">
|
||||
</tspan>
|
||||
</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.1 KiB |
@ -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"]);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
---
|
||||
[dependencies]
|
||||
docopt = "0.6"
|
||||
|
||||
---
|
||||
|
||||
fn main() {
|
||||
|
@ -1,8 +1,8 @@
|
||||
<svg width="740px" height="254px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="740px" height="92px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { background: #000000 }
|
||||
.fg-red { fill: #AA0000 }
|
||||
.fg-green { fill: #00AA00 }
|
||||
.fg-yellow { fill: #AA5500 }
|
||||
.container {
|
||||
padding: 0 10px;
|
||||
@ -21,29 +21,11 @@
|
||||
<text xml:space="preserve" class="container fg">
|
||||
<tspan x="10px" y="28px"><tspan class="fg-yellow bold">warning</tspan><tspan class="bold">:</tspan><tspan> `package.edition` is unspecified, defaulting to `[..]`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="46px"><tspan class="fg-red bold">error</tspan><tspan class="bold">:</tspan><tspan> Unable to parse Cargo.toml</tspan>
|
||||
<tspan x="10px" y="46px"><tspan class="fg-green bold"> Removing</tspan><tspan> docopt from dependencies</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="64px">
|
||||
<tspan x="10px" y="64px"><tspan class="fg-yellow bold">warning</tspan><tspan class="bold">:</tspan><tspan> `package.edition` is unspecified, defaulting to `[..]`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="82px"><tspan>Caused by:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="100px"><tspan> Manifest not valid TOML</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="118px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="136px"><tspan>Caused by:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="154px"><tspan> TOML parse error at line 1, column 4</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="172px"><tspan> |</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="190px"><tspan> 1 | ---</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="208px"><tspan> | ^</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="226px"><tspan> expected `.`, `=`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="244px">
|
||||
<tspan x="10px" y="82px">
|
||||
</tspan>
|
||||
</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.1 KiB |