feat: add alias validation

Ensures aliases don't contain characters which could
cause issues. They are now also forbidden from being
the same as an engine name to avoid issues.
This commit is contained in:
daimond113 2025-01-15 22:21:36 +01:00
parent a33302aff9
commit 5ace844035
No known key found for this signature in database
GPG key ID: 3A8ECE51328B513C
19 changed files with 182 additions and 100 deletions

View file

@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
use pesde::{
manifest::{
target::{Target, TargetKind},
DependencyType,
Alias, DependencyType,
},
names::PackageName,
source::{
@ -125,7 +125,7 @@ pub struct PackageResponseInner {
#[serde(skip_serializing_if = "BTreeSet::is_empty")]
docs: BTreeSet<RegistryDocEntry>,
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
dependencies: BTreeMap<String, (DependencySpecifiers, DependencyType)>,
dependencies: BTreeMap<Alias, (DependencySpecifiers, DependencyType)>,
}
impl PackageResponseInner {

View file

@ -7,7 +7,7 @@ use semver::VersionReq;
use crate::cli::{config::read_config, AnyPackageIdentifier, VersionedPackageName};
use pesde::{
manifest::target::TargetKind,
manifest::{target::TargetKind, Alias},
names::PackageNames,
source::{
git::{specifier::GitDependencySpecifier, GitPackageSource},
@ -37,7 +37,7 @@ pub struct AddCommand {
/// The alias to use for the package
#[arg(short, long)]
alias: Option<String>,
alias: Option<Alias>,
/// Whether to add the package as a peer dependency
#[arg(short, long)]
@ -180,24 +180,29 @@ impl AddCommand {
"dependencies"
};
let alias = self.alias.unwrap_or_else(|| match &self.name {
AnyPackageIdentifier::PackageName(versioned) => versioned.0.name().to_string(),
AnyPackageIdentifier::Url((url, _)) => url
.path
.to_string()
.split('/')
.next_back()
.map(|s| s.to_string())
.unwrap_or(url.path.to_string()),
AnyPackageIdentifier::Workspace(versioned) => versioned.0.name().to_string(),
AnyPackageIdentifier::Path(path) => path
.file_name()
.map(|s| s.to_string_lossy().to_string())
.expect("path has no file name"),
});
let alias = match self.alias {
Some(alias) => alias,
None => match &self.name {
AnyPackageIdentifier::PackageName(versioned) => versioned.0.name().to_string(),
AnyPackageIdentifier::Url((url, _)) => url
.path
.to_string()
.split('/')
.next_back()
.map(|s| s.to_string())
.unwrap_or(url.path.to_string()),
AnyPackageIdentifier::Workspace(versioned) => versioned.0.name().to_string(),
AnyPackageIdentifier::Path(path) => path
.file_name()
.map(|s| s.to_string_lossy().to_string())
.expect("path has no file name"),
}
.parse()
.context("auto-generated alias is invalid. use --alias to specify one")?,
};
let field = &mut manifest[dependency_key]
.or_insert(toml_edit::Item::Table(toml_edit::Table::new()))[&alias];
.or_insert(toml_edit::Item::Table(toml_edit::Table::new()))[alias.as_str()];
match specifier {
DependencySpecifiers::Pesde(spec) => {

View file

@ -259,7 +259,7 @@ impl InitCommand {
continue;
};
let field = &mut dev_deps[alias];
let field = &mut dev_deps[alias.as_str()];
field["name"] = toml_edit::value(spec.name.to_string());
field["version"] = toml_edit::value(spec.version.to_string());
field["target"] = toml_edit::value(

View file

@ -12,7 +12,7 @@ use pesde::{
engine::EngineKind,
graph::{DependencyGraph, DependencyGraphWithTarget},
lockfile::Lockfile,
manifest::{target::TargetKind, DependencyType, Manifest},
manifest::{target::TargetKind, Alias, DependencyType, Manifest},
names::PackageNames,
source::{pesde::PesdePackageSource, refs::PackageRefs},
version_matches, Project, RefreshedSources, LOCKFILE_FILE_NAME, MANIFEST_FILE_NAME,
@ -25,7 +25,7 @@ use std::{
};
use tokio::task::JoinSet;
fn bin_link_file(alias: &str) -> String {
fn bin_link_file(alias: &Alias) -> String {
let mut all_combinations = BTreeSet::new();
for a in TargetKind::VARIANTS {
@ -70,23 +70,13 @@ impl DownloadAndLinkHooks for InstallHooks {
.values()
.filter(|node| node.target.bin_path().is_some())
.filter_map(|node| node.node.direct.as_ref())
.map(|(alias, _, _)| alias)
.filter(|alias| {
if *alias == env!("CARGO_BIN_NAME") {
tracing::warn!(
"package {alias} has the same name as the CLI, skipping bin link"
);
return false;
}
true
})
.map(|alias| {
.map(|(alias, _, _)| {
let bin_folder = self.bin_folder.clone();
let alias = alias.clone();
async move {
let bin_exec_file = bin_folder
.join(&alias)
.join(alias.as_str())
.with_extension(std::env::consts::EXE_EXTENSION);
let impl_folder = bin_folder.join(".impl");
@ -94,7 +84,7 @@ impl DownloadAndLinkHooks for InstallHooks {
.await
.context("failed to create bin link folder")?;
let bin_file = impl_folder.join(&alias).with_extension("luau");
let bin_file = impl_folder.join(alias.as_str()).with_extension("luau");
fs::write(&bin_file, bin_link_file(&alias))
.await
.context("failed to write bin link file")?;

View file

@ -1,7 +1,7 @@
use crate::{
manifest::{
target::{Target, TargetKind},
DependencyType,
Alias, DependencyType,
},
source::{
ids::{PackageId, VersionId},
@ -22,10 +22,10 @@ pub type Graph<Node> = BTreeMap<PackageId, Node>;
pub struct DependencyGraphNode {
/// The alias, specifier, and original (as in the manifest) type for the dependency, if it is a direct dependency (i.e. used by the current project)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub direct: Option<(String, DependencySpecifiers, DependencyType)>,
pub direct: Option<(Alias, DependencySpecifiers, DependencyType)>,
/// The dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dependencies: BTreeMap<PackageId, String>,
pub dependencies: BTreeMap<PackageId, Alias>,
/// The resolved (transformed, for example Peer -> Standard) type of the dependency
pub resolved_ty: DependencyType,
/// Whether the resolved type should be Peer if this isn't depended on

View file

@ -1,7 +1,7 @@
use crate::{
graph::{DependencyGraphNodeWithTarget, DependencyGraphWithTarget},
linking::generator::get_file_types,
manifest::Manifest,
manifest::{Alias, Manifest},
scripts::{execute_script, ExecuteScriptHooks, ScriptName},
source::{
fs::{cas_path, store_in_cas},
@ -169,7 +169,7 @@ impl Project {
relative_container_folder: &Path,
node: &DependencyGraphNodeWithTarget,
package_id: &PackageId,
alias: &str,
alias: &Alias,
package_types: &Arc<PackageTypes>,
manifest: &Arc<Manifest>,
remove: bool,
@ -243,7 +243,8 @@ impl Project {
.filter(|s| !s.is_empty() && node.node.direct.is_some() && is_root)
{
let scripts_container = self.package_dir().join(SCRIPTS_LINK_FOLDER);
let scripts_base = create_and_canonicalize(scripts_container.join(alias)).await?;
let scripts_base =
create_and_canonicalize(scripts_container.join(alias.as_str())).await?;
if remove {
tasks.spawn(async move {

View file

@ -41,7 +41,7 @@ pub mod old {
manifest::{
overrides::OverrideKey,
target::{Target, TargetKind},
DependencyType,
Alias, DependencyType,
},
names::{PackageName, PackageNames},
source::{
@ -60,10 +60,10 @@ pub mod old {
pub struct DependencyGraphNodeOld {
/// The alias, specifier, and original (as in the manifest) type for the dependency, if it is a direct dependency (i.e. used by the current project)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub direct: Option<(String, DependencySpecifiers, DependencyType)>,
pub direct: Option<(Alias, DependencySpecifiers, DependencyType)>,
/// The dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dependencies: BTreeMap<PackageNames, (VersionId, String)>,
pub dependencies: BTreeMap<PackageNames, (VersionId, Alias)>,
/// The resolved (transformed, for example Peer -> Standard) type of the dependency
pub resolved_ty: DependencyType,
/// Whether the resolved type should be Peer if this isn't depended on

View file

@ -10,7 +10,12 @@ use crate::{
use relative_path::RelativePathBuf;
use semver::{Version, VersionReq};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
use serde_with::{DeserializeFromStr, SerializeDisplay};
use std::{
collections::{BTreeMap, HashMap},
fmt::Display,
str::FromStr,
};
use tracing::instrument;
/// Overrides
@ -99,19 +104,75 @@ pub struct Manifest {
/// The standard dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dependencies: BTreeMap<String, DependencySpecifiers>,
pub dependencies: BTreeMap<Alias, DependencySpecifiers>,
/// The peer dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub peer_dependencies: BTreeMap<String, DependencySpecifiers>,
pub peer_dependencies: BTreeMap<Alias, DependencySpecifiers>,
/// The dev dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dev_dependencies: BTreeMap<String, DependencySpecifiers>,
pub dev_dependencies: BTreeMap<Alias, DependencySpecifiers>,
/// The user-defined fields of the package
#[cfg_attr(feature = "schema", schemars(skip))]
#[serde(flatten)]
pub user_defined_fields: HashMap<String, toml::Value>,
}
/// An alias of a dependency
#[derive(
SerializeDisplay, DeserializeFromStr, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
)]
pub struct Alias(String);
impl Display for Alias {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.pad(&self.0)
}
}
impl FromStr for Alias {
type Err = errors::AliasFromStr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.is_empty() {
return Err(errors::AliasFromStr::Empty);
}
if !s
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
{
return Err(errors::AliasFromStr::InvalidCharacters(s.to_string()));
}
if EngineKind::from_str(s).is_ok() {
return Err(errors::AliasFromStr::EngineName(s.to_string()));
}
Ok(Self(s.to_string()))
}
}
#[cfg(feature = "schema")]
impl schemars::JsonSchema for Alias {
fn schema_name() -> std::borrow::Cow<'static, str> {
"Alias".into()
}
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
schemars::json_schema!({
"type": "string",
"pattern": r#"^[a-zA-Z0-9_-]+$"#,
})
}
}
impl Alias {
/// Get the alias as a string
pub fn as_str(&self) -> &str {
&self.0
}
}
/// A dependency type
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[serde(rename_all = "snake_case")]
@ -129,10 +190,8 @@ impl Manifest {
#[instrument(skip(self), ret(level = "trace"), level = "debug")]
pub fn all_dependencies(
&self,
) -> Result<
BTreeMap<String, (DependencySpecifiers, DependencyType)>,
errors::AllDependenciesError,
> {
) -> Result<BTreeMap<Alias, (DependencySpecifiers, DependencyType)>, errors::AllDependenciesError>
{
let mut all_deps = BTreeMap::new();
for (deps, ty) in [
@ -153,14 +212,32 @@ impl Manifest {
/// Errors that can occur when interacting with manifests
pub mod errors {
use crate::manifest::Alias;
use thiserror::Error;
/// Errors that can occur when parsing an alias from a string
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum AliasFromStr {
/// The alias is empty
#[error("the alias is empty")]
Empty,
/// The alias contains characters outside a-z, A-Z, 0-9, -, and _
#[error("alias `{0}` contains characters outside a-z, A-Z, 0-9, -, and _")]
InvalidCharacters(String),
/// The alias is an engine name
#[error("alias `{0}` is an engine name")]
EngineName(String),
}
/// Errors that can occur when trying to get all dependencies from a manifest
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum AllDependenciesError {
/// Another specifier is already using the alias
#[error("another specifier is already using the alias {0}")]
AliasConflict(String),
AliasConflict(Alias),
}
}

View file

@ -1,4 +1,4 @@
use crate::source::specifiers::DependencySpecifiers;
use crate::{manifest::Alias, source::specifiers::DependencySpecifiers};
use serde::{Deserialize, Serialize};
use serde_with::{DeserializeFromStr, SerializeDisplay};
use std::{
@ -10,7 +10,7 @@ use std::{
#[derive(
Debug, DeserializeFromStr, SerializeDisplay, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
)]
pub struct OverrideKey(pub Vec<Vec<String>>);
pub struct OverrideKey(pub Vec<Vec<Alias>>);
impl FromStr for OverrideKey {
type Err = errors::OverrideKeyFromStr;
@ -18,8 +18,13 @@ impl FromStr for OverrideKey {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let overrides = s
.split(',')
.map(|overrides| overrides.split('>').map(ToString::to_string).collect())
.collect::<Vec<Vec<String>>>();
.map(|overrides| {
overrides
.split('>')
.map(Alias::from_str)
.collect::<Result<_, _>>()
})
.collect::<Result<Vec<Vec<Alias>>, _>>()?;
if overrides.is_empty() {
return Err(errors::OverrideKeyFromStr::Empty);
@ -38,7 +43,7 @@ impl schemars::JsonSchema for OverrideKey {
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
schemars::json_schema!({
"type": "string",
"pattern": r#"^([a-zA-Z]+(>[a-zA-Z]+)+)(,([a-zA-Z]+(>[a-zA-Z]+)+))*$"#,
"pattern": r#"^(?:[a-zA-Z0-9_-]+>[a-zA-Z0-9_-]+(?:>[a-zA-Z0-9_-]+)*)(?:,(?:[a-zA-Z0-9_-]+>[a-zA-Z0-9_-]+(?:>[a-zA-Z0-9_-]+)*))*$"#,
})
}
}
@ -53,7 +58,7 @@ impl Display for OverrideKey {
.map(|overrides| {
overrides
.iter()
.map(String::as_str)
.map(Alias::as_str)
.collect::<Vec<_>>()
.join(">")
})
@ -71,7 +76,7 @@ pub enum OverrideSpecifier {
/// A specifier for a dependency
Specifier(DependencySpecifiers),
/// An alias for a dependency the current project depends on
Alias(String),
Alias(Alias),
}
/// Errors that can occur when interacting with override keys
@ -85,5 +90,9 @@ pub mod errors {
/// The override key is empty
#[error("empty override key")]
Empty,
/// An alias in the override key is invalid
#[error("invalid alias in override key")]
InvalidAlias(#[from] crate::manifest::errors::AliasFromStr),
}
}

View file

@ -1,6 +1,6 @@
use crate::{
graph::{DependencyGraph, DependencyGraphNode},
manifest::{overrides::OverrideSpecifier, DependencyType},
manifest::{overrides::OverrideSpecifier, Alias, DependencyType},
source::{
ids::PackageId,
pesde::PesdePackageSource,
@ -92,12 +92,12 @@ impl Project {
let Some(alias) = all_specifiers.remove(&(specifier.clone(), *source_ty)) else {
tracing::debug!(
"dependency {package_id} (old alias {old_alias}) from old dependency graph is no longer in the manifest",
);
"dependency {package_id} (old alias {old_alias}) from old dependency graph is no longer in the manifest",
);
continue;
};
let span = tracing::info_span!("resolve from old graph", alias);
let span = tracing::info_span!("resolve from old graph", alias = alias.as_str());
let _guard = span.enter();
tracing::debug!("resolved {package_id} from old dependency graph");
@ -121,6 +121,7 @@ impl Project {
let inner_span =
tracing::info_span!("resolve dependency", path = path.join(">"));
let _inner_guard = inner_span.enter();
if let Some(dep_node) = previous_graph.get(dep_id) {
tracing::debug!("resolved sub-dependency {dep_id}");
insert_node(&mut graph, dep_id, dep_node.clone(), false);
@ -262,7 +263,7 @@ impl Project {
.get_mut(&dependant_id)
.expect("dependant package not found in graph")
.dependencies
.insert(package_id.clone(), alias.clone());
.insert(package_id.clone(), alias.clone());
}
let pkg_ref = &resolved[package_id.version_id()];
@ -339,7 +340,7 @@ impl Project {
tracing::debug!(
"overridden specifier found for {} ({dependency_spec})",
path.iter()
.map(String::as_str)
.map(Alias::as_str)
.chain(std::iter::once(dependency_alias.as_str()))
.collect::<Vec<_>>()
.join(">"),
@ -368,7 +369,7 @@ impl Project {
Ok(())
}
.instrument(tracing::info_span!("resolve new/changed", path = path.join(">")))
.instrument(tracing::info_span!("resolve new/changed", path = path.iter().map(Alias::as_str).collect::<Vec<_>>().join(">")))
.await?;
}
@ -388,6 +389,7 @@ impl Project {
/// Errors that can occur when resolving dependencies
pub mod errors {
use crate::manifest::Alias;
use thiserror::Error;
/// Errors that can occur when creating a dependency graph
@ -425,6 +427,6 @@ pub mod errors {
/// An alias for an override was not found in the manifest
#[error("alias `{0}` not found in manifest")]
AliasNotFound(String),
AliasNotFound(Alias),
}
}

View file

@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use crate::{
manifest::DependencyType,
manifest::{Alias, DependencyType},
source::{git::GitPackageSource, DependencySpecifiers, PackageRef, PackageSources},
};
@ -19,12 +19,12 @@ pub struct GitPackageRef {
pub tree_id: String,
/// The dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dependencies: BTreeMap<String, (DependencySpecifiers, DependencyType)>,
pub dependencies: BTreeMap<Alias, (DependencySpecifiers, DependencyType)>,
/// Whether this package uses the new structure
pub new_structure: bool,
}
impl PackageRef for GitPackageRef {
fn dependencies(&self) -> &BTreeMap<String, (DependencySpecifiers, DependencyType)> {
fn dependencies(&self) -> &BTreeMap<Alias, (DependencySpecifiers, DependencyType)> {
&self.dependencies
}

View file

@ -1,5 +1,5 @@
use crate::{
manifest::DependencyType,
manifest::{Alias, DependencyType},
source::{path::PathPackageSource, DependencySpecifiers, PackageRef, PackageSources},
};
use serde::{Deserialize, Serialize};
@ -12,10 +12,10 @@ pub struct PathPackageRef {
pub path: PathBuf,
/// The dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dependencies: BTreeMap<String, (DependencySpecifiers, DependencyType)>,
pub dependencies: BTreeMap<Alias, (DependencySpecifiers, DependencyType)>,
}
impl PackageRef for PathPackageRef {
fn dependencies(&self) -> &BTreeMap<String, (DependencySpecifiers, DependencyType)> {
fn dependencies(&self) -> &BTreeMap<Alias, (DependencySpecifiers, DependencyType)> {
&self.dependencies
}

View file

@ -14,7 +14,7 @@ use specifier::PesdeDependencySpecifier;
use crate::{
engine::EngineKind,
manifest::{target::Target, DependencyType},
manifest::{target::Target, Alias, DependencyType},
names::{PackageName, PackageNames},
reporters::{response_to_async_read, DownloadProgressReporter},
source::{
@ -498,7 +498,7 @@ pub struct IndexFileEntry {
/// The dependencies of this package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dependencies: BTreeMap<String, (DependencySpecifiers, DependencyType)>,
pub dependencies: BTreeMap<Alias, (DependencySpecifiers, DependencyType)>,
}
/// The package metadata in the index file

View file

@ -3,7 +3,7 @@ use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::{
manifest::DependencyType,
manifest::{Alias, DependencyType},
source::{pesde::PesdePackageSource, DependencySpecifiers, PackageRef, PackageSources},
};
@ -18,10 +18,10 @@ pub struct PesdePackageRef {
pub index_url: gix::Url,
/// The dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dependencies: BTreeMap<String, (DependencySpecifiers, DependencyType)>,
pub dependencies: BTreeMap<Alias, (DependencySpecifiers, DependencyType)>,
}
impl PackageRef for PesdePackageRef {
fn dependencies(&self) -> &BTreeMap<String, (DependencySpecifiers, DependencyType)> {
fn dependencies(&self) -> &BTreeMap<Alias, (DependencySpecifiers, DependencyType)> {
&self.dependencies
}

View file

@ -1,5 +1,5 @@
use crate::{
manifest::DependencyType,
manifest::{Alias, DependencyType},
source::{pesde, specifiers::DependencySpecifiers, traits::PackageRef, PackageSources},
};
use serde::{Deserialize, Serialize};
@ -35,7 +35,7 @@ impl PackageRefs {
}
impl PackageRef for PackageRefs {
fn dependencies(&self) -> &BTreeMap<String, (DependencySpecifiers, DependencyType)> {
fn dependencies(&self) -> &BTreeMap<Alias, (DependencySpecifiers, DependencyType)> {
match self {
PackageRefs::Pesde(pkg_ref) => pkg_ref.dependencies(),
#[cfg(feature = "wally-compat")]

View file

@ -1,7 +1,7 @@
use crate::{
manifest::{
target::{Target, TargetKind},
DependencyType,
Alias, DependencyType,
},
reporters::DownloadProgressReporter,
source::{ids::PackageId, DependencySpecifiers, PackageFs, PackageSources, ResolveResult},
@ -21,7 +21,7 @@ pub trait DependencySpecifier: Debug + Display {}
/// A reference to a package
pub trait PackageRef: Debug {
/// The dependencies of this package
fn dependencies(&self) -> &BTreeMap<String, (DependencySpecifiers, DependencyType)>;
fn dependencies(&self) -> &BTreeMap<Alias, (DependencySpecifiers, DependencyType)>;
/// Whether to use the new structure (`packages` folders inside the package's content folder) or the old structure (Wally-style, with linker files in the parent of the folder containing the package's contents)
fn use_new_structure(&self) -> bool;
/// The source of this package

View file

@ -1,7 +1,7 @@
use std::collections::BTreeMap;
use crate::{
manifest::{errors, DependencyType},
manifest::{errors, Alias, DependencyType},
names::wally::WallyPackageName,
source::{specifiers::DependencySpecifiers, wally::specifier::WallyDependencySpecifier},
};
@ -28,9 +28,9 @@ pub struct WallyPackage {
pub fn deserialize_specifiers<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<BTreeMap<String, WallyDependencySpecifier>, D::Error> {
) -> Result<BTreeMap<Alias, WallyDependencySpecifier>, D::Error> {
// specifier is in form of `name@version_req`
BTreeMap::<String, String>::deserialize(deserializer)?
BTreeMap::<Alias, String>::deserialize(deserializer)?
.into_iter()
.map(|(k, v)| {
let (name, version) = v.split_once('@').ok_or_else(|| {
@ -54,11 +54,11 @@ pub fn deserialize_specifiers<'de, D: Deserializer<'de>>(
pub struct WallyManifest {
pub package: WallyPackage,
#[serde(default, deserialize_with = "deserialize_specifiers")]
pub dependencies: BTreeMap<String, WallyDependencySpecifier>,
pub dependencies: BTreeMap<Alias, WallyDependencySpecifier>,
#[serde(default, deserialize_with = "deserialize_specifiers")]
pub server_dependencies: BTreeMap<String, WallyDependencySpecifier>,
pub server_dependencies: BTreeMap<Alias, WallyDependencySpecifier>,
#[serde(default, deserialize_with = "deserialize_specifiers")]
pub dev_dependencies: BTreeMap<String, WallyDependencySpecifier>,
pub dev_dependencies: BTreeMap<Alias, WallyDependencySpecifier>,
}
impl WallyManifest {
@ -66,10 +66,8 @@ impl WallyManifest {
#[instrument(skip(self), ret(level = "trace"), level = "debug")]
pub fn all_dependencies(
&self,
) -> Result<
BTreeMap<String, (DependencySpecifiers, DependencyType)>,
errors::AllDependenciesError,
> {
) -> Result<BTreeMap<Alias, (DependencySpecifiers, DependencyType)>, errors::AllDependenciesError>
{
let mut all_deps = BTreeMap::new();
for (deps, ty) in [

View file

@ -3,7 +3,7 @@ use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::{
manifest::DependencyType,
manifest::{Alias, DependencyType},
source::{wally::WallyPackageSource, DependencySpecifiers, PackageRef, PackageSources},
};
@ -18,10 +18,10 @@ pub struct WallyPackageRef {
pub index_url: gix::Url,
/// The dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dependencies: BTreeMap<String, (DependencySpecifiers, DependencyType)>,
pub dependencies: BTreeMap<Alias, (DependencySpecifiers, DependencyType)>,
}
impl PackageRef for WallyPackageRef {
fn dependencies(&self) -> &BTreeMap<String, (DependencySpecifiers, DependencyType)> {
fn dependencies(&self) -> &BTreeMap<Alias, (DependencySpecifiers, DependencyType)> {
&self.dependencies
}

View file

@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use crate::{
manifest::DependencyType,
manifest::{Alias, DependencyType},
source::{workspace::WorkspacePackageSource, DependencySpecifiers, PackageRef, PackageSources},
};
@ -14,10 +14,10 @@ pub struct WorkspacePackageRef {
pub path: RelativePathBuf,
/// The dependencies of the package
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub dependencies: BTreeMap<String, (DependencySpecifiers, DependencyType)>,
pub dependencies: BTreeMap<Alias, (DependencySpecifiers, DependencyType)>,
}
impl PackageRef for WorkspacePackageRef {
fn dependencies(&self) -> &BTreeMap<String, (DependencySpecifiers, DependencyType)> {
fn dependencies(&self) -> &BTreeMap<Alias, (DependencySpecifiers, DependencyType)> {
&self.dependencies
}