Skip to content

Commit 189a470

Browse files
Merge pull request #10 from thunderstore-io/package-refactor
Refactor package struct, implement metadata retrieval for r2modman
2 parents 19b0ebb + 734f29a commit 189a470

File tree

4 files changed

+60
-67
lines changed

4 files changed

+60
-67
lines changed

src/main.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::error::Error;
1717
use crate::game::{ecosystem, registry};
1818
use crate::game::import::{self, ImportBase, ImportOverrides};
1919
use crate::package::resolver::DependencyGraph;
20+
use crate::package::Package;
2021
use crate::project::lock::LockFile;
2122
use crate::project::overrides::ProjectOverrides;
2223
use crate::project::Project;
@@ -334,17 +335,14 @@ async fn main() -> Result<(), Error> {
334335
let lock = LockFile::open_or_new(&project.lockfile_path)?;
335336
let graph = DependencyGraph::from_graph(lock.package_graph);
336337

337-
println!("Installed packages:");
338-
339-
340-
341338
for package in graph.digest() {
342-
println!(
343-
"- {}-{} ({})",
344-
package.namespace.bold(),
345-
package.name.bold(),
346-
package.version.to_string().truecolor(90, 90, 90)
347-
);
339+
let package = Package::from_any(package).await?;
340+
let Some(meta) = package.get_metadata().await? else {
341+
continue
342+
};
343+
344+
let str = serde_json::to_string_pretty(&meta)?;
345+
println!("{str}");
348346
}
349347

350348
Ok(())

src/package/install/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ impl Installer {
2929
pub async fn load_and_prepare(package: &Package) -> Result<Installer, Error> {
3030
// Temp, we'll figure out a good solution from the progress reporter later.
3131
let test = VoidProgress {};
32-
let cache_dir = package.resolve(test.add_bar().as_ref()).await?;
32+
let cache_dir = match package.get_path().await {
33+
Some(x) => x,
34+
None => package.download(test.add_bar().as_ref()).await?
35+
};
3336

3437
let manifest = {
3538
let path = cache_dir.join("installer.json");

src/package/mod.rs

+38-52
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod install;
44
pub mod resolver;
55

66
use std::borrow::Borrow;
7+
use std::fs::File;
78
use std::io::{ErrorKind, Read, Seek};
89
use std::path::{Path, PathBuf};
910

@@ -23,6 +24,14 @@ use crate::TCLI_HOME;
2324

2425
use self::index::PackageIndex;
2526

27+
#[derive(Serialize, Deserialize, Debug)]
28+
pub struct PackageMetadata {
29+
#[serde(flatten)]
30+
manifest: PackageManifestV1,
31+
reference: String,
32+
icon: PathBuf,
33+
}
34+
2635
#[derive(Serialize, Deserialize, Debug, Clone)]
2736
pub enum PackageSource {
2837
Remote(String),
@@ -43,7 +52,7 @@ pub struct Package {
4352
impl Package {
4453
/// Attempt to resolve the package from the local cache or remote.
4554
/// This does not download the package, it just finds its "source".
46-
pub async fn resolve_new(ident: impl Borrow<PackageReference>) -> Result<Self, Error> {
55+
pub async fn from_any(ident: impl Borrow<PackageReference>) -> Result<Self, Error> {
4756
if cache::get_cache_location(ident.borrow()).exists() {
4857
return Package::from_cache(ident).await;
4958
}
@@ -110,7 +119,9 @@ impl Package {
110119
/// Load package metadata from an arbitrary path, extracting it into the cache if it passes
111120
// manifest validation.
112121
pub async fn from_path(ident: PackageReference, path: &Path) -> Result<Self, Error> {
113-
let package = Package::from_repo(ident).await?;
122+
// let package = Package::from_repo(ident).await?;
123+
add_to_cache(&ident, File::open(path).map_fs_error(path)?)?;
124+
let package = Package::from_cache(ident).await?;
114125

115126
Ok(Package {
116127
identifier: package.identifier,
@@ -119,64 +130,39 @@ impl Package {
119130
})
120131
}
121132

122-
/// Resolve the package into a discrete path. This will download the package if it is not cached,
123-
// otherwise it will return its cached path.
124-
pub async fn resolve(&self, reporter: &dyn ProgressBarTrait) -> Result<PathBuf, Error> {
133+
/// Resolve the package into a discrete path, returning None if it does not exist locally.
134+
pub async fn get_path(&self) -> Option<PathBuf> {
125135
match &self.source {
126136
PackageSource::Local(path) => add_to_cache(
127137
&self.identifier,
128-
std::fs::File::open(path).map_fs_error(path)?,
129-
),
130-
PackageSource::Remote(_) => self.download(reporter).await,
131-
PackageSource::Cache(path) => Ok(path.clone()),
138+
File::open(path).map_fs_error(path).ok()?,
139+
).ok(),
140+
PackageSource::Cache(path) => Some(path.clone()),
141+
PackageSource::Remote(_) => None,
132142
}
133143
}
134144

135-
pub async fn add(
136-
&self,
137-
project_state: &Path,
138-
reporter: Box<dyn ProgressBarTrait>,
139-
) -> Result<(), Error> {
140-
let cache_path = self.resolve(reporter.as_ref()).await?;
141-
let install_dir = project_state.join(self.identifier.to_string());
142-
143-
if install_dir.is_dir() {
144-
fs::remove_dir_all(&install_dir)
145-
.await
146-
.map_fs_error(&install_dir)?;
147-
}
148-
149-
for item in walkdir::WalkDir::new(&cache_path).into_iter() {
150-
let item = item?;
151-
152-
let dest_path = install_dir.join(item.path().strip_prefix(&cache_path).unwrap());
153-
154-
if item.file_type().is_dir() {
155-
tokio::fs::create_dir_all(&dest_path)
156-
.await
157-
.map_fs_error(&dest_path)?;
158-
} else if item.file_type().is_file() {
159-
tokio::fs::copy(item.path(), &dest_path)
160-
.await
161-
.map_fs_error(&dest_path)?;
162-
}
163-
}
164-
165-
let finished_msg = format!(
166-
"{} {}-{} ({})",
167-
"[✓]".green(),
168-
self.identifier.namespace.bold(),
169-
self.identifier.name.bold(),
170-
self.identifier.version.to_string().truecolor(90, 90, 90)
171-
);
172-
173-
reporter.println(&finished_msg);
174-
reporter.finish_and_clear();
175-
176-
Ok(())
145+
/// Get the metadata associated with this package. This will return None
146+
/// the package does not exist locally.
147+
pub async fn get_metadata(&self) -> Result<Option<PackageMetadata>, Error> {
148+
let Some(package_dir) = self.get_path().await else {
149+
return Ok(None);
150+
};
151+
let manifest = {
152+
let str = fs::read_to_string(package_dir.join("manifest.json")).await?;
153+
serde_json::from_str::<PackageManifestV1>(&str)?
154+
};
155+
let icon = package_dir.join("icon.png");
156+
let reference = package_dir.file_name().unwrap().to_string_lossy().to_string();
157+
158+
Ok(Some(PackageMetadata {
159+
manifest,
160+
reference,
161+
icon,
162+
}))
177163
}
178164

179-
async fn download(&self, reporter: &dyn ProgressBarTrait) -> Result<PathBuf, Error> {
165+
pub async fn download(&self, reporter: &dyn ProgressBarTrait) -> Result<PathBuf, Error> {
180166
let PackageSource::Remote(package_source) = &self.source else {
181167
panic!("Invalid use, this is a local package.")
182168
};

src/project/mod.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ impl Project {
293293
let packages = try_join_all(
294294
packages
295295
.into_iter()
296-
.map(|x| async move { Package::resolve_new(x).await }),
296+
.map(|x| async move { Package::from_any(x).await }),
297297
)
298298
.await?;
299299

@@ -306,7 +306,10 @@ impl Project {
306306
let bar = bar.as_ref();
307307

308308
// Resolve the package, either downloading it or returning its cached path.
309-
let package_dir = package.resolve(bar).await?;
309+
let package_dir = match package.get_path().await {
310+
Some(x) => x,
311+
None => package.download(bar).await?
312+
};
310313
let tracked_files = installer
311314
.install_package(
312315
&package,
@@ -376,7 +379,7 @@ impl Project {
376379
let packages = try_join_all(
377380
packages
378381
.into_iter()
379-
.map(|x| async move { Package::resolve_new(x).await }),
382+
.map(|x| async move { Package::from_any(x).await }),
380383
)
381384
.await?;
382385

@@ -385,7 +388,10 @@ impl Project {
385388
let bar = multi.add_bar();
386389
let bar = bar.as_ref();
387390

388-
let package_dir = package.resolve(bar).await?;
391+
let package_dir = match package.get_path().await {
392+
Some(x) => x,
393+
None => package.download(bar).await?
394+
};
389395
let state_entry = statefile.state.get(&package.identifier);
390396

391397
let tracked_files = state_entry

0 commit comments

Comments
 (0)