mirror of
https://github.com/pesde-pkg/pesde.git
synced 2025-01-06 08:09:09 +00:00
feat: implement multi target packages
This commit is contained in:
parent
14463b7205
commit
2898b02e1c
10 changed files with 148 additions and 117 deletions
|
@ -63,6 +63,7 @@ impl InstallCommand {
|
||||||
.write_lockfile(Lockfile {
|
.write_lockfile(Lockfile {
|
||||||
name: manifest.name,
|
name: manifest.name,
|
||||||
version: manifest.version,
|
version: manifest.version,
|
||||||
|
target: manifest.target.kind(),
|
||||||
overrides: manifest.overrides,
|
overrides: manifest.overrides,
|
||||||
|
|
||||||
graph: downloaded_graph,
|
graph: downloaded_graph,
|
||||||
|
|
|
@ -245,9 +245,16 @@ impl IsUpToDate for Project {
|
||||||
Err(e) => return Err(e.into()),
|
Err(e) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if manifest.overrides != lockfile.overrides {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if manifest.target.kind() != lockfile.target {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
if !strict {
|
if !strict {
|
||||||
// the resolver will use the old lockfile and update it itself. it can't handle overrides only
|
return Ok(true);
|
||||||
return Ok(manifest.overrides == lockfile.overrides);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if manifest.name != lockfile.name || manifest.version != lockfile.version {
|
if manifest.name != lockfile.name || manifest.version != lockfile.version {
|
||||||
|
|
|
@ -30,7 +30,7 @@ impl RunCommand {
|
||||||
|
|
||||||
let pkg_name = PackageNames::Pesde(pkg_name);
|
let pkg_name = PackageNames::Pesde(pkg_name);
|
||||||
|
|
||||||
for (version, node) in graph.get(&pkg_name).context("package not found in graph")? {
|
for (version_id, node) in graph.get(&pkg_name).context("package not found in graph")? {
|
||||||
if node.node.direct.is_none() {
|
if node.node.direct.is_none() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ impl RunCommand {
|
||||||
.join(base_folder)
|
.join(base_folder)
|
||||||
.join(PACKAGES_CONTAINER_NAME),
|
.join(PACKAGES_CONTAINER_NAME),
|
||||||
&pkg_name,
|
&pkg_name,
|
||||||
version,
|
version_id.version(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let path = bin_path.to_path(&container_folder);
|
let path = bin_path.to_path(&container_folder);
|
||||||
|
|
|
@ -21,7 +21,7 @@ impl Project {
|
||||||
let mut downloaded_graph: DownloadedGraph = BTreeMap::new();
|
let mut downloaded_graph: DownloadedGraph = BTreeMap::new();
|
||||||
|
|
||||||
for (name, versions) in graph {
|
for (name, versions) in graph {
|
||||||
for (version, node) in versions {
|
for (version_id, node) in versions {
|
||||||
let source = match &node.pkg_ref {
|
let source = match &node.pkg_ref {
|
||||||
PackageRefs::Pesde(pkg_ref) => {
|
PackageRefs::Pesde(pkg_ref) => {
|
||||||
PackageSources::Pesde(PesdePackageSource::new(pkg_ref.index_url.clone()))
|
PackageSources::Pesde(PesdePackageSource::new(pkg_ref.index_url.clone()))
|
||||||
|
@ -38,7 +38,7 @@ impl Project {
|
||||||
.join(node.base_folder(manifest.target.kind(), true))
|
.join(node.base_folder(manifest.target.kind(), true))
|
||||||
.join(PACKAGES_CONTAINER_NAME),
|
.join(PACKAGES_CONTAINER_NAME),
|
||||||
name,
|
name,
|
||||||
version,
|
version_id.version(),
|
||||||
);
|
);
|
||||||
|
|
||||||
create_dir_all(&container_folder)?;
|
create_dir_all(&container_folder)?;
|
||||||
|
@ -46,7 +46,7 @@ impl Project {
|
||||||
let target = source.download(&node.pkg_ref, &container_folder, self)?;
|
let target = source.download(&node.pkg_ref, &container_folder, self)?;
|
||||||
|
|
||||||
downloaded_graph.entry(name.clone()).or_default().insert(
|
downloaded_graph.entry(name.clone()).or_default().insert(
|
||||||
version.clone(),
|
version_id.clone(),
|
||||||
DownloadedDependencyGraphNode {
|
DownloadedDependencyGraphNode {
|
||||||
node: node.clone(),
|
node: node.clone(),
|
||||||
target,
|
target,
|
||||||
|
|
|
@ -4,10 +4,9 @@ use crate::{
|
||||||
manifest::{ScriptName, Target},
|
manifest::{ScriptName, Target},
|
||||||
names::PackageNames,
|
names::PackageNames,
|
||||||
scripts::execute_script,
|
scripts::execute_script,
|
||||||
source::PackageRef,
|
source::{PackageRef, VersionId},
|
||||||
Project, PACKAGES_CONTAINER_NAME,
|
Project, PACKAGES_CONTAINER_NAME,
|
||||||
};
|
};
|
||||||
use semver::Version;
|
|
||||||
use std::{collections::BTreeMap, fs::create_dir_all};
|
use std::{collections::BTreeMap, fs::create_dir_all};
|
||||||
|
|
||||||
pub mod generator;
|
pub mod generator;
|
||||||
|
@ -16,10 +15,10 @@ impl Project {
|
||||||
pub fn link_dependencies(&self, graph: &DownloadedGraph) -> Result<(), errors::LinkingError> {
|
pub fn link_dependencies(&self, graph: &DownloadedGraph) -> Result<(), errors::LinkingError> {
|
||||||
let manifest = self.deser_manifest()?;
|
let manifest = self.deser_manifest()?;
|
||||||
|
|
||||||
let mut package_types = BTreeMap::<&PackageNames, BTreeMap<&Version, Vec<String>>>::new();
|
let mut package_types = BTreeMap::<&PackageNames, BTreeMap<&VersionId, Vec<String>>>::new();
|
||||||
|
|
||||||
for (name, versions) in graph {
|
for (name, versions) in graph {
|
||||||
for (version, node) in versions {
|
for (version_id, node) in versions {
|
||||||
let Some(lib_file) = node.target.lib_path() else {
|
let Some(lib_file) = node.target.lib_path() else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -30,7 +29,7 @@ impl Project {
|
||||||
.join(node.node.base_folder(manifest.target.kind(), true))
|
.join(node.node.base_folder(manifest.target.kind(), true))
|
||||||
.join(PACKAGES_CONTAINER_NAME),
|
.join(PACKAGES_CONTAINER_NAME),
|
||||||
name,
|
name,
|
||||||
version,
|
version_id.version(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let lib_file = lib_file.to_path(&container_folder);
|
let lib_file = lib_file.to_path(&container_folder);
|
||||||
|
@ -58,7 +57,7 @@ impl Project {
|
||||||
package_types
|
package_types
|
||||||
.entry(name)
|
.entry(name)
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(version, types);
|
.insert(version_id, types);
|
||||||
|
|
||||||
#[cfg(feature = "roblox")]
|
#[cfg(feature = "roblox")]
|
||||||
if let Target::Roblox { build_files, .. } = &node.target {
|
if let Target::Roblox { build_files, .. } = &node.target {
|
||||||
|
@ -87,7 +86,7 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, versions) in graph {
|
for (name, versions) in graph {
|
||||||
for (version, node) in versions {
|
for (version_id, node) in versions {
|
||||||
let base_folder = self.path().join(
|
let base_folder = self.path().join(
|
||||||
self.path()
|
self.path()
|
||||||
.join(node.node.base_folder(manifest.target.kind(), true)),
|
.join(node.node.base_folder(manifest.target.kind(), true)),
|
||||||
|
@ -96,13 +95,15 @@ impl Project {
|
||||||
let base_folder = base_folder.canonicalize()?;
|
let base_folder = base_folder.canonicalize()?;
|
||||||
let packages_container_folder = base_folder.join(PACKAGES_CONTAINER_NAME);
|
let packages_container_folder = base_folder.join(PACKAGES_CONTAINER_NAME);
|
||||||
|
|
||||||
let container_folder =
|
let container_folder = node.node.container_folder(
|
||||||
node.node
|
&packages_container_folder,
|
||||||
.container_folder(&packages_container_folder, name, version);
|
name,
|
||||||
|
version_id.version(),
|
||||||
|
);
|
||||||
|
|
||||||
if let Some((alias, types)) = package_types
|
if let Some((alias, types)) = package_types
|
||||||
.get(name)
|
.get(name)
|
||||||
.and_then(|v| v.get(version))
|
.and_then(|v| v.get(version_id))
|
||||||
.and_then(|types| node.node.direct.as_ref().map(|(alias, _)| (alias, types)))
|
.and_then(|types| node.node.direct.as_ref().map(|(alias, _)| (alias, types)))
|
||||||
{
|
{
|
||||||
let module = generator::generate_linking_module(
|
let module = generator::generate_linking_module(
|
||||||
|
@ -118,23 +119,23 @@ impl Project {
|
||||||
std::fs::write(base_folder.join(format!("{alias}.luau")), module)?;
|
std::fs::write(base_folder.join(format!("{alias}.luau")), module)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (dependency_name, (dependency_version, dependency_alias)) in
|
for (dependency_name, (dependency_version_id, dependency_alias)) in
|
||||||
&node.node.dependencies
|
&node.node.dependencies
|
||||||
{
|
{
|
||||||
let Some(dependency_node) = graph
|
let Some(dependency_node) = graph
|
||||||
.get(dependency_name)
|
.get(dependency_name)
|
||||||
.and_then(|v| v.get(dependency_version))
|
.and_then(|v| v.get(dependency_version_id))
|
||||||
else {
|
else {
|
||||||
return Err(errors::LinkingError::DependencyNotFound(
|
return Err(errors::LinkingError::DependencyNotFound(
|
||||||
dependency_name.to_string(),
|
dependency_name.to_string(),
|
||||||
dependency_version.to_string(),
|
dependency_version_id.to_string(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
let dependency_container_folder = dependency_node.node.container_folder(
|
let dependency_container_folder = dependency_node.node.container_folder(
|
||||||
&packages_container_folder,
|
&packages_container_folder,
|
||||||
dependency_name,
|
dependency_name,
|
||||||
dependency_version,
|
dependency_version_id.version(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let linker_folder = container_folder
|
let linker_folder = container_folder
|
||||||
|
@ -153,7 +154,7 @@ impl Project {
|
||||||
)?,
|
)?,
|
||||||
package_types
|
package_types
|
||||||
.get(dependency_name)
|
.get(dependency_name)
|
||||||
.and_then(|v| v.get(dependency_version))
|
.and_then(|v| v.get(dependency_version_id))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
manifest::{DependencyType, OverrideKey, Target, TargetKind},
|
manifest::{DependencyType, OverrideKey, Target, TargetKind},
|
||||||
names::{PackageName, PackageNames},
|
names::{PackageName, PackageNames},
|
||||||
source::{DependencySpecifiers, PackageRef, PackageRefs},
|
source::{DependencySpecifiers, PackageRef, PackageRefs, VersionId},
|
||||||
};
|
};
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -10,16 +10,16 @@ use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type Graph<Node> = BTreeMap<PackageNames, BTreeMap<Version, Node>>;
|
pub type Graph<Node> = BTreeMap<PackageNames, BTreeMap<VersionId, Node>>;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct DependencyGraphNode {
|
pub struct DependencyGraphNode {
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub direct: Option<(String, DependencySpecifiers)>,
|
pub direct: Option<(String, DependencySpecifiers)>,
|
||||||
pub pkg_ref: PackageRefs,
|
|
||||||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
pub dependencies: BTreeMap<PackageNames, (Version, String)>,
|
pub dependencies: BTreeMap<PackageNames, (VersionId, String)>,
|
||||||
pub ty: DependencyType,
|
pub ty: DependencyType,
|
||||||
|
pub pkg_ref: PackageRefs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DependencyGraphNode {
|
impl DependencyGraphNode {
|
||||||
|
@ -49,7 +49,7 @@ pub type DependencyGraph = Graph<DependencyGraphNode>;
|
||||||
pub fn insert_node(
|
pub fn insert_node(
|
||||||
graph: &mut DependencyGraph,
|
graph: &mut DependencyGraph,
|
||||||
name: PackageNames,
|
name: PackageNames,
|
||||||
version: Version,
|
version: VersionId,
|
||||||
mut node: DependencyGraphNode,
|
mut node: DependencyGraphNode,
|
||||||
is_top_level: bool,
|
is_top_level: bool,
|
||||||
) {
|
) {
|
||||||
|
@ -85,8 +85,9 @@ pub fn insert_node(
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct DownloadedDependencyGraphNode {
|
pub struct DownloadedDependencyGraphNode {
|
||||||
pub node: DependencyGraphNode,
|
|
||||||
pub target: Target,
|
pub target: Target,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub node: DependencyGraphNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DownloadedGraph = Graph<DownloadedDependencyGraphNode>;
|
pub type DownloadedGraph = Graph<DownloadedDependencyGraphNode>;
|
||||||
|
@ -95,6 +96,7 @@ pub type DownloadedGraph = Graph<DownloadedDependencyGraphNode>;
|
||||||
pub struct Lockfile {
|
pub struct Lockfile {
|
||||||
pub name: PackageName,
|
pub name: PackageName,
|
||||||
pub version: Version,
|
pub version: Version,
|
||||||
|
pub target: TargetKind,
|
||||||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
pub overrides: BTreeMap<OverrideKey, DependencySpecifiers>,
|
pub overrides: BTreeMap<OverrideKey, DependencySpecifiers>,
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,13 @@ use crate::{
|
||||||
names::PackageNames,
|
names::PackageNames,
|
||||||
source::{
|
source::{
|
||||||
pesde::PesdePackageSource, DependencySpecifiers, PackageRef, PackageSource, PackageSources,
|
pesde::PesdePackageSource, DependencySpecifiers, PackageRef, PackageSource, PackageSources,
|
||||||
|
VersionId,
|
||||||
},
|
},
|
||||||
Project, DEFAULT_INDEX_NAME,
|
Project, DEFAULT_INDEX_NAME,
|
||||||
};
|
};
|
||||||
use semver::Version;
|
|
||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
|
|
||||||
impl Project {
|
impl Project {
|
||||||
// TODO: account for targets using the is_compatible_with method
|
|
||||||
pub fn dependency_graph(
|
pub fn dependency_graph(
|
||||||
&self,
|
&self,
|
||||||
previous_graph: Option<&DependencyGraph>,
|
previous_graph: Option<&DependencyGraph>,
|
||||||
|
@ -106,14 +105,17 @@ impl Project {
|
||||||
alias.to_string(),
|
alias.to_string(),
|
||||||
spec,
|
spec,
|
||||||
ty,
|
ty,
|
||||||
None::<(PackageNames, Version)>,
|
None::<(PackageNames, VersionId)>,
|
||||||
vec![alias.to_string()],
|
vec![alias.to_string()],
|
||||||
false,
|
false,
|
||||||
|
manifest.target.kind(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<VecDeque<_>>();
|
.collect::<VecDeque<_>>();
|
||||||
|
|
||||||
while let Some((alias, specifier, ty, dependant, path, overridden)) = queue.pop_front() {
|
while let Some((alias, specifier, ty, dependant, path, overridden, target)) =
|
||||||
|
queue.pop_front()
|
||||||
|
{
|
||||||
let depth = path.len() - 1;
|
let depth = path.len() - 1;
|
||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
|
@ -155,10 +157,10 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (name, resolved) = source
|
let (name, resolved) = source
|
||||||
.resolve(&specifier, self)
|
.resolve(&specifier, self, target)
|
||||||
.map_err(|e| Box::new(e.into()))?;
|
.map_err(|e| Box::new(e.into()))?;
|
||||||
|
|
||||||
let Some(target_version) = graph
|
let Some(target_version_id) = graph
|
||||||
.get(&name)
|
.get(&name)
|
||||||
.and_then(|versions| {
|
.and_then(|versions| {
|
||||||
versions
|
versions
|
||||||
|
@ -170,11 +172,9 @@ impl Project {
|
||||||
.or_else(|| resolved.last_key_value().map(|(ver, _)| ver))
|
.or_else(|| resolved.last_key_value().map(|(ver, _)| ver))
|
||||||
.cloned()
|
.cloned()
|
||||||
else {
|
else {
|
||||||
log::warn!(
|
return Err(Box::new(errors::DependencyGraphError::NoMatchingVersion(
|
||||||
"{}could not find any version for {specifier} ({alias})",
|
format!("{specifier} ({})", manifest.target.kind()),
|
||||||
"\t".repeat(depth)
|
)));
|
||||||
);
|
|
||||||
continue;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty = if depth == 0 && ty == DependencyType::Peer {
|
let ty = if depth == 0 && ty == DependencyType::Peer {
|
||||||
|
@ -183,25 +183,25 @@ impl Project {
|
||||||
ty
|
ty
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((dependant_name, dependant_version)) = dependant {
|
if let Some((dependant_name, dependant_version_id)) = dependant {
|
||||||
graph
|
graph
|
||||||
.get_mut(&dependant_name)
|
.get_mut(&dependant_name)
|
||||||
.and_then(|versions| versions.get_mut(&dependant_version))
|
.and_then(|versions| versions.get_mut(&dependant_version_id))
|
||||||
.and_then(|node| {
|
.and_then(|node| {
|
||||||
node.dependencies
|
node.dependencies
|
||||||
.insert(name.clone(), (target_version.clone(), alias.clone()))
|
.insert(name.clone(), (target_version_id.clone(), alias.clone()))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(already_resolved) = graph
|
if let Some(already_resolved) = graph
|
||||||
.get_mut(&name)
|
.get_mut(&name)
|
||||||
.and_then(|versions| versions.get_mut(&target_version))
|
.and_then(|versions| versions.get_mut(&target_version_id))
|
||||||
{
|
{
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"{}{}@{} already resolved",
|
"{}{}@{} already resolved",
|
||||||
"\t".repeat(depth),
|
"\t".repeat(depth),
|
||||||
name,
|
name,
|
||||||
target_version
|
target_version_id
|
||||||
);
|
);
|
||||||
|
|
||||||
if already_resolved.ty == DependencyType::Peer && ty == DependencyType::Standard {
|
if already_resolved.ty == DependencyType::Peer && ty == DependencyType::Standard {
|
||||||
|
@ -211,7 +211,7 @@ impl Project {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pkg_ref = &resolved[&target_version];
|
let pkg_ref = &resolved[&target_version_id];
|
||||||
let node = DependencyGraphNode {
|
let node = DependencyGraphNode {
|
||||||
direct: if depth == 0 {
|
direct: if depth == 0 {
|
||||||
Some((alias.clone(), specifier.clone()))
|
Some((alias.clone(), specifier.clone()))
|
||||||
|
@ -225,7 +225,7 @@ impl Project {
|
||||||
insert_node(
|
insert_node(
|
||||||
&mut graph,
|
&mut graph,
|
||||||
name.clone(),
|
name.clone(),
|
||||||
target_version.clone(),
|
target_version_id.clone(),
|
||||||
node.clone(),
|
node.clone(),
|
||||||
depth == 0,
|
depth == 0,
|
||||||
);
|
);
|
||||||
|
@ -234,7 +234,7 @@ impl Project {
|
||||||
"{}resolved {}@{} from new dependency graph",
|
"{}resolved {}@{} from new dependency graph",
|
||||||
"\t".repeat(depth),
|
"\t".repeat(depth),
|
||||||
name,
|
name,
|
||||||
target_version
|
target_version_id
|
||||||
);
|
);
|
||||||
|
|
||||||
for (dependency_alias, (dependency_spec, dependency_ty)) in
|
for (dependency_alias, (dependency_spec, dependency_ty)) in
|
||||||
|
@ -262,20 +262,21 @@ impl Project {
|
||||||
dependency_alias,
|
dependency_alias,
|
||||||
overridden.cloned().unwrap_or(dependency_spec),
|
overridden.cloned().unwrap_or(dependency_spec),
|
||||||
dependency_ty,
|
dependency_ty,
|
||||||
Some((name.clone(), target_version.clone())),
|
Some((name.clone(), target_version_id.clone())),
|
||||||
path.iter()
|
path.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.chain(std::iter::once(alias.to_string()))
|
.chain(std::iter::once(alias.to_string()))
|
||||||
.collect(),
|
.collect(),
|
||||||
overridden.is_some(),
|
overridden.is_some(),
|
||||||
|
pkg_ref.target_kind(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, versions) in &graph {
|
for (name, versions) in &graph {
|
||||||
for (version, node) in versions {
|
for (version_id, node) in versions {
|
||||||
if node.ty == DependencyType::Peer {
|
if node.ty == DependencyType::Peer {
|
||||||
log::warn!("peer dependency {name}@{version} was not resolved");
|
log::warn!("peer dependency {name}@{version_id} was not resolved");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,5 +311,8 @@ pub mod errors {
|
||||||
|
|
||||||
#[error("error resolving package")]
|
#[error("error resolving package")]
|
||||||
Resolve(#[from] crate::source::errors::ResolveError),
|
Resolve(#[from] crate::source::errors::ResolveError),
|
||||||
|
|
||||||
|
#[error("no matching version found for {0}")]
|
||||||
|
NoMatchingVersion(String),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use std::{
|
|
||||||
collections::BTreeMap,
|
|
||||||
fmt::{Debug, Display},
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
|
|
||||||
use semver::Version;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
manifest::{DependencyType, Target, TargetKind},
|
manifest::{DependencyType, Target, TargetKind},
|
||||||
names::PackageNames,
|
names::PackageNames,
|
||||||
Project,
|
Project,
|
||||||
};
|
};
|
||||||
|
use semver::Version;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_with::{DeserializeFromStr, SerializeDisplay};
|
||||||
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
fmt::{Debug, Display},
|
||||||
|
path::Path,
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod pesde;
|
pub mod pesde;
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ impl Display for DependencySpecifiers {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "snake_case", tag = "ref_ty")]
|
||||||
pub enum PackageRefs {
|
pub enum PackageRefs {
|
||||||
Pesde(pesde::pkg_ref::PesdePackageRef),
|
Pesde(pesde::pkg_ref::PesdePackageRef),
|
||||||
}
|
}
|
||||||
|
@ -68,7 +69,43 @@ impl PackageRef for PackageRefs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ResolveResult<Ref> = (PackageNames, BTreeMap<Version, Ref>);
|
#[derive(
|
||||||
|
Debug, SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
|
||||||
|
)]
|
||||||
|
pub struct VersionId(Version, TargetKind);
|
||||||
|
|
||||||
|
impl VersionId {
|
||||||
|
pub fn version(&self) -> &Version {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn target(&self) -> &TargetKind {
|
||||||
|
&self.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for VersionId {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} {}", self.0, self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for VersionId {
|
||||||
|
type Err = errors::VersionIdParseError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let Some((version, target)) = s.split_once(' ') else {
|
||||||
|
return Err(errors::VersionIdParseError::Malformed(s.to_string()));
|
||||||
|
};
|
||||||
|
|
||||||
|
let version = version.parse()?;
|
||||||
|
let target = target.parse()?;
|
||||||
|
|
||||||
|
Ok(VersionId(version, target))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ResolveResult<Ref> = (PackageNames, BTreeMap<VersionId, Ref>);
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
||||||
pub enum PackageSources {
|
pub enum PackageSources {
|
||||||
|
@ -89,6 +126,7 @@ pub trait PackageSource: Debug {
|
||||||
&self,
|
&self,
|
||||||
specifier: &Self::Specifier,
|
specifier: &Self::Specifier,
|
||||||
project: &Project,
|
project: &Project,
|
||||||
|
project_target: TargetKind,
|
||||||
) -> Result<ResolveResult<Self::Ref>, Self::ResolveError>;
|
) -> Result<ResolveResult<Self::Ref>, Self::ResolveError>;
|
||||||
|
|
||||||
fn download(
|
fn download(
|
||||||
|
@ -115,10 +153,11 @@ impl PackageSource for PackageSources {
|
||||||
&self,
|
&self,
|
||||||
specifier: &Self::Specifier,
|
specifier: &Self::Specifier,
|
||||||
project: &Project,
|
project: &Project,
|
||||||
|
project_target: TargetKind,
|
||||||
) -> Result<ResolveResult<Self::Ref>, Self::ResolveError> {
|
) -> Result<ResolveResult<Self::Ref>, Self::ResolveError> {
|
||||||
match (self, specifier) {
|
match (self, specifier) {
|
||||||
(PackageSources::Pesde(source), DependencySpecifiers::Pesde(specifier)) => source
|
(PackageSources::Pesde(source), DependencySpecifiers::Pesde(specifier)) => source
|
||||||
.resolve(specifier, project)
|
.resolve(specifier, project, project_target)
|
||||||
.map(|(name, results)| {
|
.map(|(name, results)| {
|
||||||
(
|
(
|
||||||
name,
|
name,
|
||||||
|
@ -179,4 +218,17 @@ pub mod errors {
|
||||||
#[error("error downloading pesde package")]
|
#[error("error downloading pesde package")]
|
||||||
Pesde(#[from] crate::source::pesde::errors::DownloadError),
|
Pesde(#[from] crate::source::pesde::errors::DownloadError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum VersionIdParseError {
|
||||||
|
#[error("malformed entry key {0}")]
|
||||||
|
Malformed(String),
|
||||||
|
|
||||||
|
#[error("malformed version")]
|
||||||
|
Version(#[from] semver::Error),
|
||||||
|
|
||||||
|
#[error("malformed target")]
|
||||||
|
Target(#[from] crate::manifest::errors::TargetKindFromStr),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,16 @@
|
||||||
use std::{
|
use std::{collections::BTreeMap, fmt::Debug, hash::Hash, path::Path};
|
||||||
collections::BTreeMap,
|
|
||||||
fmt::{Debug, Display},
|
|
||||||
hash::Hash,
|
|
||||||
path::Path,
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use gix::remote::Direction;
|
use gix::remote::Direction;
|
||||||
use semver::Version;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::{DeserializeFromStr, SerializeDisplay};
|
|
||||||
|
|
||||||
use pkg_ref::PesdePackageRef;
|
use pkg_ref::PesdePackageRef;
|
||||||
use specifier::PesdeDependencySpecifier;
|
use specifier::PesdeDependencySpecifier;
|
||||||
|
|
||||||
|
use crate::manifest::TargetKind;
|
||||||
use crate::{
|
use crate::{
|
||||||
manifest::{DependencyType, Target, TargetKind},
|
manifest::{DependencyType, Target},
|
||||||
names::{PackageName, PackageNames},
|
names::{PackageName, PackageNames},
|
||||||
source::{hash, DependencySpecifiers, PackageSource, ResolveResult},
|
source::{hash, DependencySpecifiers, PackageSource, ResolveResult, VersionId},
|
||||||
util::authenticate_conn,
|
util::authenticate_conn,
|
||||||
Project, REQWEST_CLIENT,
|
Project, REQWEST_CLIENT,
|
||||||
};
|
};
|
||||||
|
@ -307,6 +300,7 @@ impl PackageSource for PesdePackageSource {
|
||||||
&self,
|
&self,
|
||||||
specifier: &Self::Specifier,
|
specifier: &Self::Specifier,
|
||||||
project: &Project,
|
project: &Project,
|
||||||
|
project_target: TargetKind,
|
||||||
) -> Result<ResolveResult<Self::Ref>, Self::ResolveError> {
|
) -> Result<ResolveResult<Self::Ref>, Self::ResolveError> {
|
||||||
let (scope, name) = specifier.name.as_str();
|
let (scope, name) = specifier.name.as_str();
|
||||||
let string = match self.read_file([scope, name], project) {
|
let string = match self.read_file([scope, name], project) {
|
||||||
|
@ -322,10 +316,17 @@ impl PackageSource for PesdePackageSource {
|
||||||
PackageNames::Pesde(specifier.name.clone()),
|
PackageNames::Pesde(specifier.name.clone()),
|
||||||
entries
|
entries
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(EntryKey(version, _), _)| specifier.version.matches(version))
|
.filter(|(VersionId(version, target), _)| {
|
||||||
.map(|(EntryKey(version, _), entry)| {
|
specifier.version.matches(version)
|
||||||
|
&& specifier
|
||||||
|
.target
|
||||||
|
.map_or(project_target.is_compatible_with(target), |t| t == *target)
|
||||||
|
})
|
||||||
|
.map(|(id, entry)| {
|
||||||
|
let version = id.version().clone();
|
||||||
|
|
||||||
(
|
(
|
||||||
version.clone(),
|
id,
|
||||||
PesdePackageRef {
|
PesdePackageRef {
|
||||||
name: specifier.name.clone(),
|
name: specifier.name.clone(),
|
||||||
version,
|
version,
|
||||||
|
@ -413,33 +414,7 @@ pub struct IndexFileEntry {
|
||||||
pub dependencies: BTreeMap<String, (DependencySpecifiers, DependencyType)>,
|
pub dependencies: BTreeMap<String, (DependencySpecifiers, DependencyType)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
pub type IndexFile = BTreeMap<VersionId, IndexFileEntry>;
|
||||||
Debug, SerializeDisplay, DeserializeFromStr, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
|
|
||||||
)]
|
|
||||||
pub struct EntryKey(pub Version, pub TargetKind);
|
|
||||||
|
|
||||||
impl Display for EntryKey {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{} {}", self.0, self.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for EntryKey {
|
|
||||||
type Err = errors::EntryKeyParseError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let Some((version, target)) = s.split_once(' ') else {
|
|
||||||
return Err(errors::EntryKeyParseError::Malformed(s.to_string()));
|
|
||||||
};
|
|
||||||
|
|
||||||
let version = version.parse()?;
|
|
||||||
let target = target.parse()?;
|
|
||||||
|
|
||||||
Ok(EntryKey(version, target))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type IndexFile = BTreeMap<EntryKey, IndexFileEntry>;
|
|
||||||
|
|
||||||
pub mod errors {
|
pub mod errors {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -593,17 +568,4 @@ pub mod errors {
|
||||||
#[error("error unpacking package")]
|
#[error("error unpacking package")]
|
||||||
Unpack(#[from] std::io::Error),
|
Unpack(#[from] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
#[non_exhaustive]
|
|
||||||
pub enum EntryKeyParseError {
|
|
||||||
#[error("malformed entry key {0}")]
|
|
||||||
Malformed(String),
|
|
||||||
|
|
||||||
#[error("malformed version")]
|
|
||||||
Version(#[from] semver::Error),
|
|
||||||
|
|
||||||
#[error("malformed target")]
|
|
||||||
Target(#[from] crate::manifest::errors::TargetKindFromStr),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{names::PackageName, source::DependencySpecifier};
|
use crate::{manifest::TargetKind, names::PackageName, source::DependencySpecifier};
|
||||||
use semver::VersionReq;
|
use semver::VersionReq;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
@ -9,6 +9,8 @@ pub struct PesdeDependencySpecifier {
|
||||||
pub version: VersionReq,
|
pub version: VersionReq,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub index: Option<String>,
|
pub index: Option<String>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub target: Option<TargetKind>,
|
||||||
}
|
}
|
||||||
impl DependencySpecifier for PesdeDependencySpecifier {}
|
impl DependencySpecifier for PesdeDependencySpecifier {}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue