Skip to content

Commit 3f95dcf

Browse files
committed
fix!: rework lockfile to handle libdeps installed in multiple environments
fixes #8
1 parent eccde3a commit 3f95dcf

File tree

15 files changed

+783
-337
lines changed

15 files changed

+783
-337
lines changed

cli/src/lockfile.rs

Lines changed: 46 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,40 @@
1-
use std::{collections::BTreeMap, fmt::Display, path::PathBuf};
1+
use std::{collections::BTreeMap, fmt::Display};
22

33
use base64::prelude::*;
44
use serde::{Deserialize, Serialize};
55
use url::Url;
66

77
use crate::{
88
manifest::{ExternalSpec, PackageManifest},
9-
registry,
9+
registry::{self, SystemSpec},
1010
};
1111

1212
#[derive(Serialize, Deserialize, Clone, Debug)]
1313
#[serde(tag = "version")]
1414
pub enum Lockfile {
15-
V1 {
15+
#[serde(rename = "2")]
16+
V2 {
1617
dependencies: BTreeMap<String, Dependency>,
1718
},
1819
}
1920

2021
impl Default for Lockfile {
2122
fn default() -> Self {
22-
Self::V1 {
23+
Self::V2 {
2324
dependencies: BTreeMap::default(),
2425
}
2526
}
2627
}
2728

2829
impl Lockfile {
29-
pub fn add_dependency(&mut self, dependency: Dependency) {
30-
let Self::V1 { dependencies, .. } = self;
31-
if let Some(old) = dependencies.insert(dependency.name.clone(), dependency) {
32-
let new = &dependencies[&old.name];
30+
pub fn add_dependency(&mut self, install_path: String, dependency: Dependency) {
31+
let Self::V2 { dependencies, .. } = self;
32+
if let Some(old) = dependencies.insert(install_path.clone(), dependency) {
33+
let new = &dependencies[&install_path];
3334
if old.manifest != new.manifest {
3435
log::warn!(r#"Found duplicate dependency "{old}", using "{new}"#)
3536
}
36-
}
37+
};
3738
}
3839
}
3940

@@ -69,74 +70,58 @@ impl NixSystem {
6970
#[derive(Serialize, Deserialize, Clone, Debug)]
7071
pub struct Dependency {
7172
pub name: String,
72-
pub install_path: PathBuf,
73-
pub version: String,
74-
pub manifest: String,
75-
pub systems: BTreeMap<NixSystem, FetchUrl>,
73+
pub manifest: PackageManifest,
74+
pub src: Src,
75+
}
76+
77+
#[derive(Serialize, Deserialize, Clone, Debug)]
78+
#[serde(rename_all = "camelCase")]
79+
pub enum Src {
80+
Universal(FetchUrl),
81+
Systems(BTreeMap<NixSystem, FetchUrl>),
7682
}
7783

7884
impl Dependency {
79-
pub fn from_url(
80-
manifest: &PackageManifest,
81-
install_path: PathBuf,
82-
package_spec: &ExternalSpec,
83-
sha256: &[u8],
84-
) -> Self {
85-
let systems = NixSystem::ALL
86-
.iter()
87-
.map(|nix_system| (*nix_system, FetchUrl::new(package_spec.uri.clone(), sha256)))
88-
.collect();
89-
Self::new(
90-
manifest,
91-
install_path,
92-
package_spec.name.clone(),
93-
manifest.version.clone(),
94-
systems,
95-
)
85+
pub fn from_url(manifest: PackageManifest, package_spec: &ExternalSpec, sha256: &[u8]) -> Self {
86+
let src = Src::Universal(FetchUrl::new(package_spec.uri.clone(), sha256));
87+
Self::new(manifest, package_spec.name.clone(), src)
9688
}
9789

98-
pub fn from_registry(
99-
manifest: &PackageManifest,
100-
install_path: PathBuf,
101-
package_spec: registry::PackageSpec,
102-
) -> Self {
103-
let version = package_spec.version;
104-
let systems = NixSystem::ALL
90+
pub fn from_registry(manifest: PackageManifest, package_spec: registry::PackageSpec) -> Self {
91+
let src = if let Some(universal) = package_spec
92+
.version
93+
.files
10594
.iter()
106-
.filter_map(|nix_system| {
107-
let file = version.supports(&nix_system.to_registry());
108-
file.map(|file| (*nix_system, FetchUrl::from(file)))
109-
})
110-
.collect();
111-
Self::new(
112-
manifest,
113-
install_path,
114-
package_spec.name,
115-
version.name.clone(),
116-
systems,
117-
)
95+
.find(|f| f.system == SystemSpec::Wildcard)
96+
{
97+
Src::Universal(FetchUrl::from(universal))
98+
} else {
99+
Src::Systems(
100+
NixSystem::ALL
101+
.iter()
102+
.filter_map(|nix_system| {
103+
let file = package_spec.version.supports(&nix_system.to_registry());
104+
file.map(|file| (*nix_system, FetchUrl::from(file)))
105+
})
106+
.collect(),
107+
)
108+
};
109+
110+
Self::new(manifest, package_spec.name, src)
118111
}
119112

120-
fn new(
121-
manifest: &PackageManifest,
122-
install_path: PathBuf,
123-
name: String,
124-
version: String,
125-
systems: BTreeMap<NixSystem, FetchUrl>,
126-
) -> Self {
113+
fn new(manifest: PackageManifest, name: String, src: Src) -> Self {
127114
Self {
128115
name,
129-
install_path,
130-
manifest: serde_json::to_string(manifest).expect("serializable manifest"),
131-
version,
132-
systems,
116+
manifest,
117+
src,
133118
}
134119
}
135120
}
136121

137122
impl Display for Dependency {
138123
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139-
write!(f, "{}@{}", self.name, self.version)
124+
write!(f, "{}@{}", self.name, self.manifest.version)
140125
}
141126
}
142127

cli/src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,11 @@ async fn main() -> eyre::Result<()> {
100100
let mut lockfile = Lockfile::default();
101101

102102
for artifact in global.into_iter().chain(workspace.into_iter()) {
103-
let dependency = client.resolve(artifact).await?;
104-
lockfile.add_dependency(dependency);
103+
let dependency = client.resolve(artifact.manifest).await?;
104+
lockfile.add_dependency(
105+
artifact.install_path.to_string_lossy().into_owned(),
106+
dependency,
107+
);
105108
}
106109

107110
println!("{}", serde_json::to_string_pretty(&lockfile)?);

cli/src/manifest.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub struct Artifact {
1515
}
1616

1717
/// .piopm package manifest file
18-
#[derive(Serialize, Deserialize, Debug)]
18+
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)]
1919
pub struct PackageManifest {
2020
#[serde(rename = "type")]
2121
pub ty: PackageType,
@@ -45,22 +45,22 @@ impl PackageType {
4545
}
4646
}
4747

48-
#[derive(Serialize, Deserialize, Debug)]
48+
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)]
4949
#[serde(untagged)]
5050
pub enum PackageSpec {
5151
PlatformIO(PlatformIOSpec),
5252
External(ExternalSpec),
5353
}
5454

55-
#[derive(Serialize, Deserialize, Debug)]
55+
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)]
5656
pub struct PlatformIOSpec {
5757
pub owner: String,
5858
pub name: String,
5959
#[serde(flatten)]
6060
_extra: BTreeMap<String, Value>,
6161
}
6262

63-
#[derive(Serialize, Deserialize, Debug)]
63+
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)]
6464
pub struct ExternalSpec {
6565
pub name: String,
6666
pub uri: Url,

cli/src/registry/mod.rs

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,34 +40,23 @@ impl Default for RegistryClient {
4040
}
4141

4242
impl RegistryClient {
43-
pub async fn resolve(&self, artifact: Artifact) -> eyre::Result<Dependency> {
44-
match &artifact.manifest.spec {
43+
pub async fn resolve(&self, manifest: PackageManifest) -> eyre::Result<Dependency> {
44+
match &manifest.spec {
4545
crate::manifest::PackageSpec::PlatformIO(PlatformIOSpec { owner, name, .. }) => {
4646
let package_spec = self
47-
.get_package_spec(
48-
owner,
49-
artifact.manifest.ty,
50-
name,
51-
Some(artifact.manifest.version.to_string()),
52-
)
47+
.get_package_spec(owner, manifest.ty, name, Some(manifest.version.to_string()))
5348
.await?;
54-
Ok(Dependency::from_registry(
55-
&artifact.manifest,
56-
artifact.install_path,
57-
package_spec,
58-
))
49+
Ok(Dependency::from_registry(manifest, package_spec))
5950
}
6051
crate::manifest::PackageSpec::External(package_spec) => {
61-
self.get_external(&artifact.manifest, artifact.install_path, package_spec)
62-
.await
52+
self.get_external(&manifest, package_spec).await
6353
}
6454
}
6555
}
6656

67-
pub async fn get_external(
57+
async fn get_external(
6858
&self,
6959
manifest: &PackageManifest,
70-
install_path: PathBuf,
7160
package_spec: &ExternalSpec,
7261
) -> eyre::Result<Dependency> {
7362
let response = self.client.get(package_spec.uri.clone()).send().await?;
@@ -76,15 +65,10 @@ impl RegistryClient {
7665
let mut hash = Sha256::new();
7766
hash.update(bytes);
7867
let hash = hash.finalize();
79-
Ok(Dependency::from_url(
80-
manifest,
81-
install_path,
82-
package_spec,
83-
&hash,
84-
))
68+
Ok(Dependency::from_url(manifest.clone(), package_spec, &hash))
8569
}
8670

87-
pub async fn get_package_spec(
71+
async fn get_package_spec(
8872
&self,
8973
owner: &str,
9074
ty: PackageType,

examples/external-deps/package.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ let
1313
lockfile = ./platformio2nix.lock;
1414
overrides = (
1515
final: prev: {
16-
SlowSoftWire = prev.SlowSoftWire.overrideAttrs (drv: {
16+
"libdeps/uno/SlowSoftWire" = prev."libdeps/uno/SlowSoftWire".overrideAttrs (drv: {
1717
nativeBuildInputs = [ libarchive ];
1818

1919
unpackPhase = ''

0 commit comments

Comments
 (0)