1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use std::{collections::HashSet, path::Path};
use crate::{Language, update_type::UpdateType};
use anyhow::Result;
use async_trait::async_trait;
/// Interface for single versioned packages.
///
/// Implemented by language-specific package types for reading versions, updating files,
/// detecting changes, and publishing. All I/O operations are async.
#[async_trait]
pub trait Package: std::fmt::Debug + Send + Sync {
fn name(&self) -> Option<&str>;
fn version(&self) -> Option<&str>;
fn path(&self) -> &Path;
fn relative_path(&self) -> &Path;
/// # Errors
/// Returns error if the version update operation fails.
async fn update_version(&mut self, update_type: UpdateType) -> Result<()>;
fn is_changed(&self) -> bool;
fn language(&self) -> Language;
fn dependencies(&self) -> &HashSet<String>;
fn add_dependency(&mut self, dependency: &str);
fn set_changed(&mut self, changed: bool);
/// Set the package name (used for fallback when name is not found in manifest).
/// Implementors typically get this via `impl_basic_accessors!()`.
fn set_name(&mut self, name: String);
/// Get the default publish command for this package type
fn default_publish_command(&self) -> String;
/// Get the default dry-run publish command for this package type.
///
/// Returns `None` for ecosystems whose default publish tool does not
/// support a built-in dry-run mode (e.g. `dotnet nuget push`). Callers
/// should treat `None` as "dry-run not supported; skip with a warning"
/// rather than as a failure. Users may still provide an override via
/// `config.publish_dry_run`.
fn default_dry_run_publish_command(&self) -> Option<String>;
crate::impl_shared_project_defaults!();
/// Whether this package inherits its version from the workspace root via `version.workspace = true`
fn inherits_workspace_version(&self) -> bool {
false
}
/// Path to the workspace root Cargo.toml, if this package inherits its version from workspace
fn workspace_root_path(&self) -> Option<&Path> {
None
}
crate::impl_publish_flows!(crate::publish::PACKAGE_DIR_NOT_FOUND);
crate::impl_publish_command_resolvers!();
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_support::MockPackage;
// The eighteen tests pinning the shared trait defaults and the shared
// `UnsupportedDryRunProject` fixture are generated from one surface shared
// with `workspace.rs`; only the `Package`-only defaults below stay
// hand-written here.
crate::test_support::shared_project_default_tests!(
mock: MockPackage,
trait_name: Package,
kind: "package",
dir_not_found: "Package directory not found",
publishable_test: test_package_is_publishable_by_default,
);
#[test]
fn test_inherits_workspace_version_default() {
let package =
MockPackage::with_paths(Some("test"), "/project/package.json", "package.json");
assert!(!package.inherits_workspace_version());
}
#[test]
fn test_workspace_root_path_default() {
let package =
MockPackage::with_paths(Some("test"), "/project/package.json", "package.json");
assert!(package.workspace_root_path().is_none());
}
}