Skip to content

Commit 7320d69

Browse files
committed
feat: construct package entry
1 parent e16682f commit 7320d69

File tree

2 files changed

+124
-57
lines changed

2 files changed

+124
-57
lines changed

src/handlers/publish.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::api::publish::PublishRequest;
22
use crate::db::error::DatabaseError;
33
use crate::db::Database;
4+
use crate::index::{PackageDependencyIdentifier, PackageEntry};
45
use crate::models::{ApiToken, NewPackageDep};
56
use forc_pkg::PackageManifest;
67
use semver::Version;
@@ -34,7 +35,7 @@ pub struct PublishInfo {
3435
pub license: Option<String>,
3536
}
3637

37-
struct PartialPackageDep {
38+
pub struct PartialPackageDep {
3839
pub dependency_package_name: String,
3940
pub dependency_version_req: String,
4041
}
@@ -121,6 +122,22 @@ pub async fn handle_publish(
121122
);
122123

123124
// TODO [https://github.com/FuelLabs/forc.pub/issues/28]: Publish to GitHub index repo.
125+
let package_name = publish_info.package_name.clone();
126+
let package_version = publish_info.num.clone();
127+
let source_cid = upload.source_code_ipfs_hash;
128+
let abi_cid = upload.abi_ipfs_hash;
129+
let dependencies = package_deps
130+
.into_iter()
131+
.map(|package_dep| PackageDependencyIdentifier::from(package_dep))
132+
.collect();
133+
134+
let package_entry = PackageEntry::new(
135+
package_name,
136+
package_version,
137+
source_cid,
138+
abi_cid,
139+
dependencies,
140+
);
124141

125142
Ok(publish_info)
126143
}

src/index.rs

Lines changed: 106 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
use serde::{Deserialize, Serialize};
1515
use std::collections::BTreeMap;
1616

17+
use crate::handlers::publish::PartialPackageDep;
18+
1719
#[derive(Serialize, Deserialize)]
1820
pub struct IndexFile {
1921
/// Each published instance for this specific package, keyed by their
2022
/// versions. The reason we are doing this type of mapping is for use of
21-
/// ease, we are effectively duplicating version of package but keeping
22-
/// `PackageEntry` self contained.
23+
/// ease and deterministic ordering, we are effectively duplicating version
24+
/// of package but keeping `PackageEntry` self contained.
2325
#[serde(flatten)]
2426
versions: BTreeMap<semver::Version, PackageEntry>,
2527
}
@@ -35,7 +37,7 @@ pub struct IndexFile {
3537
/// 5. Dependencies of this package. If there are other packages this package
3638
/// depends on, some information can be directly found in the root package
3739
/// to enable parallel fetching.
38-
#[derive(Serialize, Deserialize)]
40+
#[derive(Serialize, Deserialize, Clone)]
3941
pub struct PackageEntry {
4042
/// Name of the package.
4143
/// This is the actual package name needed in forc.toml file to fetch this
@@ -56,7 +58,46 @@ pub struct PackageEntry {
5658
abi_cid: Option<String>,
5759
/// Dependencies of the current package entry. Can be consumed to enable
5860
/// parallel fetching by the consumers of this index, mainly forc.
59-
dependencies: Vec<Box<PackageEntry>>,
61+
dependencies: Vec<PackageDependencyIdentifier>,
62+
}
63+
64+
#[derive(Serialize, Deserialize, Clone)]
65+
pub struct PackageDependencyIdentifier {
66+
/// Name of the dependency.
67+
/// Name and version information can be used by consumer of this index
68+
/// to resolve dependencies.
69+
package_name: String,
70+
/// Version of the dependency.
71+
/// Name and version information can be used by consumer of this index
72+
/// to resolve dependencies.
73+
version: String,
74+
}
75+
76+
impl PackageEntry {
77+
pub fn new(
78+
package_name: String,
79+
version: semver::Version,
80+
source_cid: String,
81+
abi_cid: Option<String>,
82+
dependencies: Vec<PackageDependencyIdentifier>,
83+
) -> Self {
84+
Self {
85+
package_name,
86+
version,
87+
source_cid,
88+
abi_cid,
89+
dependencies,
90+
}
91+
}
92+
}
93+
94+
impl From<PartialPackageDep> for PackageDependencyIdentifier {
95+
fn from(value: PartialPackageDep) -> Self {
96+
Self {
97+
package_name: value.dependency_package_name,
98+
version: value.dependency_version_req,
99+
}
100+
}
60101
}
61102

62103
#[cfg(test)]
@@ -108,47 +149,39 @@ mod tests {
108149
let v011 = &deserialized.versions[&semver::Version::new(0, 11, 0)];
109150
assert_eq!(v011.source_cid, "QmOlderHash");
110151
assert_eq!(v011.abi_cid, Some("QmOlderAbiHash".to_string()));
152+
assert_eq!(v011.dependencies.len(), 0);
111153

112154
let v012 = &deserialized.versions[&semver::Version::new(0, 12, 0)];
113155
assert_eq!(v012.source_cid, "QmExampleHash");
114156
assert_eq!(v012.abi_cid, Some("QmExampleAbiHash".to_string()));
157+
assert_eq!(v012.dependencies.len(), 0);
115158
}
116159

117160
#[test]
118161
fn test_json_with_dependencies() {
119-
// Test parsing a JSON with nested dependencies
162+
// Test parsing a JSON with dependencies
120163
let json = r#"{
121-
"1.0.0": {
122-
"package_name": "main-package",
123-
"version": "1.0.0",
124-
"source_cid": "QmMainHash",
125-
"abi_cid": null,
126-
"dependencies": [
127-
{
128-
"package_name": "dep-package",
129-
"version": "0.5.0",
130-
"source_cid": "QmDepHash",
131-
"abi_cid": "QmDepAbiHash",
132-
"dependencies": []
133-
},
134-
{
135-
"package_name": "another-dep",
136-
"version": "0.9.1",
137-
"source_cid": "QmAnotherDepHash",
138-
"abi_cid": null,
139-
"dependencies": [
140-
{
141-
"package_name": "nested-dep",
142-
"version": "0.2.0",
143-
"source_cid": "QmNestedHash",
144-
"abi_cid": "QmNestedAbiHash",
145-
"dependencies": []
146-
}
147-
]
148-
}
149-
]
150-
}
151-
}"#;
164+
"1.0.0": {
165+
"package_name": "main-package",
166+
"version": "1.0.0",
167+
"source_cid": "QmMainHash",
168+
"abi_cid": null,
169+
"dependencies": [
170+
{
171+
"package_name": "dep-package",
172+
"version": "^0.5.0"
173+
},
174+
{
175+
"package_name": "another-dep",
176+
"version": "=0.9.1"
177+
},
178+
{
179+
"package_name": "third-dep",
180+
"version": "0.2.0"
181+
}
182+
]
183+
}
184+
}"#;
152185

153186
let deserialized: IndexFile = serde_json::from_str(json).unwrap();
154187

@@ -163,44 +196,35 @@ mod tests {
163196
assert_eq!(main_pkg.source_cid, "QmMainHash");
164197
assert_eq!(main_pkg.abi_cid, None);
165198

166-
// Verify first-level dependencies
167-
assert_eq!(main_pkg.dependencies.len(), 2);
199+
// Verify dependencies
200+
assert_eq!(main_pkg.dependencies.len(), 3);
168201

169202
// Check first dependency
170203
let dep1 = &main_pkg.dependencies[0];
171204
assert_eq!(dep1.package_name, "dep-package");
172-
assert_eq!(dep1.version, semver::Version::new(0, 5, 0));
173-
assert_eq!(dep1.source_cid, "QmDepHash");
174-
assert_eq!(dep1.abi_cid, Some("QmDepAbiHash".to_string()));
175-
assert_eq!(dep1.dependencies.len(), 0);
205+
assert_eq!(dep1.version, "^0.5.0");
176206

177207
// Check second dependency
178208
let dep2 = &main_pkg.dependencies[1];
179209
assert_eq!(dep2.package_name, "another-dep");
180-
assert_eq!(dep2.version, semver::Version::new(0, 9, 1));
181-
assert_eq!(dep2.source_cid, "QmAnotherDepHash");
182-
assert_eq!(dep2.abi_cid, None);
183-
184-
// Verify nested dependency
185-
assert_eq!(dep2.dependencies.len(), 1);
186-
let nested_dep = &dep2.dependencies[0];
187-
assert_eq!(nested_dep.package_name, "nested-dep");
188-
assert_eq!(nested_dep.version, semver::Version::new(0, 2, 0));
189-
assert_eq!(nested_dep.source_cid, "QmNestedHash");
190-
assert_eq!(nested_dep.abi_cid, Some("QmNestedAbiHash".to_string()));
191-
assert_eq!(nested_dep.dependencies.len(), 0);
210+
assert_eq!(dep2.version, "=0.9.1");
211+
212+
// Check third dependency
213+
let dep3 = &main_pkg.dependencies[2];
214+
assert_eq!(dep3.package_name, "third-dep");
215+
assert_eq!(dep3.version, "0.2.0");
192216

193217
// Test round-trip serialization
194218
let serialized = serde_json::to_string_pretty(&deserialized).unwrap();
219+
println!("Re-serialized JSON: {}", serialized);
195220

196221
// Deserialize again to ensure it's valid
197222
let re_deserialized: IndexFile = serde_json::from_str(&serialized).unwrap();
198223
assert_eq!(re_deserialized.versions.len(), 1);
199224

200225
// Verify the structure is preserved
201226
let main_pkg2 = &re_deserialized.versions[&semver::Version::new(1, 0, 0)];
202-
assert_eq!(main_pkg2.dependencies.len(), 2);
203-
assert_eq!(main_pkg2.dependencies[1].dependencies.len(), 1);
227+
assert_eq!(main_pkg2.dependencies.len(), 3);
204228
}
205229

206230
#[test]
@@ -222,5 +246,31 @@ mod tests {
222246
assert_eq!(pkg.package_name, "minimal-package");
223247
assert_eq!(pkg.source_cid, "QmMinimalHash");
224248
assert_eq!(pkg.abi_cid, None);
249+
assert_eq!(pkg.dependencies.len(), 0);
250+
}
251+
252+
#[test]
253+
fn test_package_entry_new() {
254+
// Test the new() constructor method
255+
let dependencies = vec![PackageDependencyIdentifier {
256+
package_name: "dep1".to_string(),
257+
version: "^1.0".to_string(),
258+
}];
259+
260+
let entry = PackageEntry::new(
261+
"test-package".to_string(),
262+
semver::Version::new(2, 0, 0),
263+
"QmTestHash".to_string(),
264+
Some("QmAbiHash".to_string()),
265+
dependencies.clone(),
266+
);
267+
268+
assert_eq!(entry.package_name, "test-package");
269+
assert_eq!(entry.version, semver::Version::new(2, 0, 0));
270+
assert_eq!(entry.source_cid, "QmTestHash");
271+
assert_eq!(entry.abi_cid, Some("QmAbiHash".to_string()));
272+
assert_eq!(entry.dependencies.len(), 1);
273+
assert_eq!(entry.dependencies[0].package_name, "dep1");
274+
assert_eq!(entry.dependencies[0].version, "^1.0");
225275
}
226276
}

0 commit comments

Comments
 (0)