Skip to content

Commit

Permalink
Use current package with add, publish when in a workspace (#206)
Browse files Browse the repository at this point in the history
* Try to use current package in the `add` command

Add test `two_projects_in_one_workspace_validate_add_from_path` which
cretes two projects in the same workspace. Run `cargo workspace add`
in each of those projects without `--package` switch to check we are
modifying the correct project/package.

* Use `find_current_package_spec` in `publish` command
  • Loading branch information
tomasol authored Jan 25, 2024
1 parent 356fcac commit 60e6880
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 27 deletions.
7 changes: 6 additions & 1 deletion src/commands/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,13 @@ impl AddCommand {
let config = Config::new(self.common.new_terminal())?;
let metadata = load_metadata(config.terminal(), self.manifest_path.as_deref(), false)?;

let spec = match &self.spec {
Some(spec) => Some(spec.clone()),
None => CargoPackageSpec::find_current_package_spec(&metadata),
};

let PackageComponentMetadata { package, metadata }: PackageComponentMetadata<'_> =
match &self.spec {
match &spec {
Some(spec) => {
let pkgs = load_component_metadata(&metadata, std::iter::once(spec), false)?;
assert!(pkgs.len() == 1, "one package should be present");
Expand Down
44 changes: 23 additions & 21 deletions src/commands/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,27 +93,29 @@ impl PublishCommand {
}

let metadata = load_metadata(config.terminal(), self.manifest_path.as_deref(), false)?;
let packages = [PackageComponentMetadata::new(
if let Some(spec) = &self.cargo_package {
metadata
.packages
.iter()
.find(|p| {
p.name == spec.name
&& match spec.version.as_ref() {
Some(v) => &p.version == v,
None => true,
}
})
.with_context(|| {
format!("package ID specification `{spec}` did not match any packages")
})?
} else {
metadata
.root_package()
.context("no root package found in manifest")?
},
)?];
let spec = match &self.cargo_package {
Some(spec) => Some(spec.clone()),
None => CargoPackageSpec::find_current_package_spec(&metadata),
};
let packages = [PackageComponentMetadata::new(if let Some(spec) = &spec {
metadata
.packages
.iter()
.find(|p| {
p.name == spec.name
&& match spec.version.as_ref() {
Some(v) => &p.version == v,
None => true,
}
})
.with_context(|| {
format!("package ID specification `{spec}` did not match any packages")
})?
} else {
metadata
.root_package()
.context("no root package found in manifest")?
})?];

let package = packages[0].package;
let component_metadata = packages[0].metadata.as_ref().with_context(|| {
Expand Down
18 changes: 18 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@

use anyhow::{anyhow, bail, Context, Result};
use cargo_component_core::terminal::{Color, Terminal};
use cargo_metadata::Metadata;
use parse_arg::{iter_short, match_arg};
use semver::Version;
use std::fmt;
use std::str::FromStr;
use std::{collections::BTreeMap, fmt::Display, path::PathBuf};
use toml_edit::Document;

/// Represents a cargo package specifier.
///
Expand Down Expand Up @@ -62,6 +64,22 @@ impl CargoPackageSpec {
},
})
}

/// Loads Cargo.toml in the current directory, attempts to find the matching package from metadata.
pub fn find_current_package_spec(metadata: &Metadata) -> Option<Self> {
let current_manifest = std::fs::read_to_string("Cargo.toml").ok()?;
let document: Document = current_manifest.parse().ok()?;
let name = document["package"]["name"].as_str()?;
let version = metadata
.packages
.iter()
.find(|found| found.name == name)
.map(|found| found.version.clone());
Some(CargoPackageSpec {
name: name.to_string(),
version,
})
}
}

impl FromStr for CargoPackageSpec {
Expand Down
38 changes: 33 additions & 5 deletions tests/add.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::support::*;
use anyhow::Result;
use anyhow::{Context, Result};
use assert_cmd::prelude::*;
use predicates::{prelude::*, str::contains};
use std::{fs, rc::Rc};
Expand Down Expand Up @@ -151,10 +151,7 @@ async fn prints_modified_manifest_for_dry_run() -> Result<()> {
Ok(())
}

#[test]
fn validate_add_from_path() -> Result<()> {
let project = Project::new("foo")?;

fn validate_add_from_path(project: &Project) -> Result<()> {
project
.cargo_component("add --path foo/baz foo:baz")
.assert()
Expand All @@ -168,6 +165,37 @@ fn validate_add_from_path() -> Result<()> {
let manifest = fs::read_to_string(project.root().join("Cargo.toml"))?;
assert!(contains(r#""foo:baz" = { path = "foo/baz" }"#).eval(&manifest));
assert!(contains(r#""foo:qux" = { path = "foo/qux" }"#).eval(&manifest));
Ok(())
}

#[test]
fn test_validate_add_from_path() -> Result<()> {
let project = Project::new("foo")?;
validate_add_from_path(&project)?;
Ok(())
}

#[test]
fn two_projects_in_one_workspace_validate_add_from_path() -> Result<()> {
let temp_dir = Rc::new(TempDir::new()?);
let cargo_workspace = temp_dir.path().join("Cargo.toml");
fs::write(
&cargo_workspace,
r#"
[workspace]
resolver = "2"
"#,
)
.with_context(|| {
format!(
"failed to write `{cargo_workspace}`",
cargo_workspace = cargo_workspace.display()
)
})?;
let p1 = Project::with_dir(temp_dir.clone(), "foo", "")?;
let p2 = Project::with_dir(temp_dir.clone(), "bar", "")?;

validate_add_from_path(&p1)?;
validate_add_from_path(&p2)?;
Ok(())
}
1 change: 1 addition & 0 deletions tests/support/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ pub async fn spawn_server(root: &Path) -> Result<(ServerInstance, warg_client::C
Ok((instance, config))
}

#[derive(Debug)]
pub struct Project {
pub dir: Rc<TempDir>,
pub root: PathBuf,
Expand Down

0 comments on commit 60e6880

Please sign in to comment.