mirror of
https://github.com/pesde-pkg/pesde.git
synced 2024-12-12 11:00:36 +00:00
feat(wally-compat): ✨ automatically find file to use as lib
This change makes Wally packages' types exported
This commit is contained in:
parent
a40001cf17
commit
9ba7819132
8 changed files with 172 additions and 21 deletions
|
@ -138,6 +138,7 @@ pub enum Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Clone)]
|
#[derive(Parser, Clone)]
|
||||||
|
#[clap(version = env!("CARGO_PKG_VERSION"))]
|
||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
pub command: Command,
|
pub command: Command,
|
||||||
|
|
|
@ -3,6 +3,7 @@ use chrono::Utc;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap},
|
collections::{BTreeMap, HashMap},
|
||||||
fs::{create_dir_all, read, remove_dir_all, write, File},
|
fs::{create_dir_all, read, remove_dir_all, write, File},
|
||||||
|
process::Command as SysCommand,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
@ -114,6 +115,26 @@ pub fn root_command(cmd: Command) -> anyhow::Result<()> {
|
||||||
"Downloading packages".to_string(),
|
"Downloading packages".to_string(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
project.convert_manifests(&resolved_versions_map, |path| {
|
||||||
|
if let Some(sourcemap_generator) = &manifest.sourcemap_generator {
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(target_os = "windows")] {
|
||||||
|
SysCommand::new("pwsh")
|
||||||
|
.args(["-C", &sourcemap_generator])
|
||||||
|
.current_dir(path)
|
||||||
|
.output()
|
||||||
|
.expect("failed to execute process");
|
||||||
|
} else {
|
||||||
|
SysCommand::new("sh")
|
||||||
|
.args(["-c", &sourcemap_generator])
|
||||||
|
.current_dir(path)
|
||||||
|
.output()
|
||||||
|
.expect("failed to execute process");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
let project = Lazy::force_mut(&mut project);
|
let project = Lazy::force_mut(&mut project);
|
||||||
|
|
||||||
project.install(
|
project.install(
|
||||||
|
@ -393,6 +414,8 @@ pub fn root_command(cmd: Command) -> anyhow::Result<()> {
|
||||||
DEFAULT_INDEX_NAME.to_string(),
|
DEFAULT_INDEX_NAME.to_string(),
|
||||||
DEFAULT_INDEX_URL.to_string(),
|
DEFAULT_INDEX_URL.to_string(),
|
||||||
)]),
|
)]),
|
||||||
|
sourcemap_generator: None,
|
||||||
|
|
||||||
dependencies: Default::default(),
|
dependencies: Default::default(),
|
||||||
peer_dependencies: Default::default(),
|
peer_dependencies: Default::default(),
|
||||||
description: none_if_empty!(description),
|
description: none_if_empty!(description),
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use cfg_if::cfg_if;
|
|
||||||
use std::{fs::create_dir_all, path::Path, sync::Arc};
|
use std::{fs::create_dir_all, path::Path, sync::Arc};
|
||||||
|
|
||||||
use git2::{build::RepoBuilder, Repository};
|
use git2::{build::RepoBuilder, Repository};
|
||||||
|
@ -174,16 +173,6 @@ impl GitPackageRef {
|
||||||
|
|
||||||
repo.reset(&obj, git2::ResetType::Hard, None)?;
|
repo.reset(&obj, git2::ResetType::Hard, None)?;
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(feature = "wally")] {
|
|
||||||
Manifest::from_path_or_convert(dest)?;
|
|
||||||
} else {
|
|
||||||
if Manifest::from_path(dest).is_err() {
|
|
||||||
return Err(GitDownloadError::ManifestNotPresent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
|
fs::create_dir_all,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use reqwest::header::AUTHORIZATION;
|
use reqwest::header::AUTHORIZATION;
|
||||||
use std::{fmt::Display, fs::create_dir_all, path::Path, sync::Arc};
|
|
||||||
|
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use serde::{de::IntoDeserializer, Deserialize, Deserializer, Serialize};
|
use serde::{de::IntoDeserializer, Deserialize, Deserializer, Serialize};
|
||||||
use serde_yaml::Value;
|
use serde_yaml::Value;
|
||||||
|
@ -16,7 +21,7 @@ use crate::{
|
||||||
resolution::ResolvedVersionsMap,
|
resolution::ResolvedVersionsMap,
|
||||||
},
|
},
|
||||||
index::{CredentialsFn, Index},
|
index::{CredentialsFn, Index},
|
||||||
manifest::Realm,
|
manifest::{Manifest, Realm},
|
||||||
multithread::MultithreadedJob,
|
multithread::MultithreadedJob,
|
||||||
package_name::PackageName,
|
package_name::PackageName,
|
||||||
project::{get_index, get_index_by_url, InstallProjectError, Project},
|
project::{get_index, get_index_by_url, InstallProjectError, Project},
|
||||||
|
@ -239,6 +244,32 @@ impl PackageRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An error that occurred while converting a manifest
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum ConvertManifestsError {
|
||||||
|
/// An error that occurred while converting the manifest
|
||||||
|
#[error("error converting the manifest")]
|
||||||
|
Manifest(#[from] crate::manifest::ManifestConvertError),
|
||||||
|
|
||||||
|
/// An error that occurred while reading the sourcemap
|
||||||
|
#[error("error reading the sourcemap")]
|
||||||
|
Sourcemap(#[from] std::io::Error),
|
||||||
|
|
||||||
|
/// An error that occurred while parsing the sourcemap
|
||||||
|
#[cfg(feature = "wally")]
|
||||||
|
#[error("error parsing the sourcemap")]
|
||||||
|
Parse(#[from] serde_json::Error),
|
||||||
|
|
||||||
|
/// An error that occurred while writing the manifest
|
||||||
|
#[error("error writing the manifest")]
|
||||||
|
Write(#[from] serde_yaml::Error),
|
||||||
|
|
||||||
|
/// A manifest is not present in a dependency, and the wally feature is not enabled
|
||||||
|
#[cfg(not(feature = "wally"))]
|
||||||
|
#[error("wally feature is not enabled, but the manifest is not present in the dependency")]
|
||||||
|
ManifestNotPresent,
|
||||||
|
}
|
||||||
|
|
||||||
impl Project {
|
impl Project {
|
||||||
/// Downloads the project's dependencies
|
/// Downloads the project's dependencies
|
||||||
pub fn download(
|
pub fn download(
|
||||||
|
@ -283,6 +314,80 @@ impl Project {
|
||||||
|
|
||||||
Ok(job)
|
Ok(job)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts the manifests of the project's dependencies
|
||||||
|
#[cfg(feature = "wally")]
|
||||||
|
pub fn convert_manifests<F: Fn(PathBuf)>(
|
||||||
|
&self,
|
||||||
|
map: &ResolvedVersionsMap,
|
||||||
|
generate_sourcemap: F,
|
||||||
|
) -> Result<(), ConvertManifestsError> {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct SourcemapNode {
|
||||||
|
#[serde(default)]
|
||||||
|
file_paths: Vec<relative_path::RelativePathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
for versions in map.values() {
|
||||||
|
for resolved_package in versions.values() {
|
||||||
|
let source = match &resolved_package.pkg_ref {
|
||||||
|
PackageRef::Wally(_) | PackageRef::Git(_) => {
|
||||||
|
resolved_package.directory(self.path()).1
|
||||||
|
}
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut manifest = Manifest::from_path_or_convert(&source)?;
|
||||||
|
|
||||||
|
generate_sourcemap(source.to_path_buf());
|
||||||
|
|
||||||
|
let sourcemap = source.join("sourcemap.json");
|
||||||
|
let sourcemap: SourcemapNode = if sourcemap.exists() {
|
||||||
|
serde_json::from_str(&std::fs::read_to_string(&sourcemap)?)?
|
||||||
|
} else {
|
||||||
|
log::warn!("sourcemap for {resolved_package} not found, skipping...");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
manifest.exports.lib = sourcemap
|
||||||
|
.file_paths
|
||||||
|
.into_iter()
|
||||||
|
.find(|path| {
|
||||||
|
path.extension()
|
||||||
|
.is_some_and(|ext| ext == "lua" || ext == "luau")
|
||||||
|
})
|
||||||
|
.or_else(|| Some(relative_path::RelativePathBuf::from("true")));
|
||||||
|
|
||||||
|
serde_yaml::to_writer(&std::fs::File::create(&source.join(crate::MANIFEST_FILE_NAME))?, &manifest)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors if dependencies don't have manifests, enable the `wally` feature to convert them
|
||||||
|
#[cfg(not(feature = "wally"))]
|
||||||
|
pub fn convert_manifests<F: Fn(PathBuf)>(
|
||||||
|
&self,
|
||||||
|
map: &ResolvedVersionsMap,
|
||||||
|
_generate_sourcemap: F,
|
||||||
|
) -> Result<(), ConvertManifestsError> {
|
||||||
|
for versions in map.values() {
|
||||||
|
for resolved_package in versions.values() {
|
||||||
|
let source = match &resolved_package.pkg_ref {
|
||||||
|
PackageRef::Git(_) => resolved_package.directory(self.path()).1,
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if Manifest::from_path_or_convert(&source).is_err() {
|
||||||
|
return Err(ConvertManifestsError::ManifestNotPresent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for PackageRef {
|
impl Display for PackageRef {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use url::Url;
|
||||||
use crate::{
|
use crate::{
|
||||||
dependencies::{maybe_authenticated_request, DependencySpecifier},
|
dependencies::{maybe_authenticated_request, DependencySpecifier},
|
||||||
index::{remote_callbacks, IndexFileEntry, WallyIndex},
|
index::{remote_callbacks, IndexFileEntry, WallyIndex},
|
||||||
manifest::{DependencyType, Manifest, ManifestConvertError, Realm},
|
manifest::{DependencyType, ManifestConvertError, Realm},
|
||||||
package_name::{
|
package_name::{
|
||||||
FromStrPackageNameParseError, WallyPackageName, WallyPackageNameValidationError,
|
FromStrPackageNameParseError, WallyPackageName, WallyPackageNameValidationError,
|
||||||
},
|
},
|
||||||
|
@ -225,7 +225,10 @@ impl WallyPackageRef {
|
||||||
) -> Result<(), WallyDownloadError> {
|
) -> Result<(), WallyDownloadError> {
|
||||||
let response =
|
let response =
|
||||||
maybe_authenticated_request(reqwest_client, url.as_str(), registry_auth_token)
|
maybe_authenticated_request(reqwest_client, url.as_str(), registry_auth_token)
|
||||||
.header("Wally-Version", "0.3.2")
|
.header(
|
||||||
|
"Wally-Version",
|
||||||
|
std::env::var("WALLY_VERSION").unwrap_or("0.3.2".to_string()),
|
||||||
|
)
|
||||||
.send()?;
|
.send()?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
|
@ -248,8 +251,6 @@ impl WallyPackageRef {
|
||||||
let mut archive = zip::read::ZipArchive::new(Cursor::new(bytes))?;
|
let mut archive = zip::read::ZipArchive::new(Cursor::new(bytes))?;
|
||||||
archive.extract(dest.as_ref())?;
|
archive.extract(dest.as_ref())?;
|
||||||
|
|
||||||
Manifest::from_path_or_convert(dest.as_ref())?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::HashSet,
|
||||||
fs::{read_to_string, write},
|
fs::{read_to_string, write},
|
||||||
iter,
|
iter,
|
||||||
path::{Component, Path, PathBuf},
|
path::{Component, Path, PathBuf},
|
||||||
|
@ -127,6 +128,7 @@ pub(crate) fn link<P: AsRef<Path>, Q: AsRef<Path>>(
|
||||||
resolved_pkg: &ResolvedPackage,
|
resolved_pkg: &ResolvedPackage,
|
||||||
destination_dir: P,
|
destination_dir: P,
|
||||||
parent_dependency_packages_dir: Q,
|
parent_dependency_packages_dir: Q,
|
||||||
|
only_name: bool,
|
||||||
) -> Result<(), LinkingError> {
|
) -> Result<(), LinkingError> {
|
||||||
let (_, source_dir) = resolved_pkg.directory(project.path());
|
let (_, source_dir) = resolved_pkg.directory(project.path());
|
||||||
let file = Manifest::from_path(&source_dir)?;
|
let file = Manifest::from_path(&source_dir)?;
|
||||||
|
@ -153,7 +155,11 @@ pub(crate) fn link<P: AsRef<Path>, Q: AsRef<Path>>(
|
||||||
destination_dir.as_ref().to_path_buf()
|
destination_dir.as_ref().to_path_buf()
|
||||||
};
|
};
|
||||||
|
|
||||||
let destination_file = destination_dir.join(format!("{}{}.lua", pkg_name.prefix(), name));
|
let destination_file = destination_dir.join(format!(
|
||||||
|
"{}{}.lua",
|
||||||
|
if only_name { "" } else { pkg_name.prefix() },
|
||||||
|
name
|
||||||
|
));
|
||||||
|
|
||||||
let realm_folder = project.path().join(resolved_pkg.packages_folder());
|
let realm_folder = project.path().join(resolved_pkg.packages_folder());
|
||||||
let in_different_folders = realm_folder != parent_dependency_packages_dir.as_ref();
|
let in_different_folders = realm_folder != parent_dependency_packages_dir.as_ref();
|
||||||
|
@ -227,6 +233,12 @@ impl Project {
|
||||||
&self,
|
&self,
|
||||||
map: &ResolvedVersionsMap,
|
map: &ResolvedVersionsMap,
|
||||||
) -> Result<(), LinkingDependenciesError> {
|
) -> Result<(), LinkingDependenciesError> {
|
||||||
|
let root_deps: HashSet<String> = HashSet::from_iter(
|
||||||
|
map.iter()
|
||||||
|
.flat_map(|(_, v)| v)
|
||||||
|
.filter_map(|(_, v)| v.is_root.then_some(v.pkg_ref.name().name().to_string())),
|
||||||
|
);
|
||||||
|
|
||||||
for (name, versions) in map {
|
for (name, versions) in map {
|
||||||
for (version, resolved_pkg) in versions {
|
for (version, resolved_pkg) in versions {
|
||||||
let (container_dir, _) = resolved_pkg.directory(self.path());
|
let (container_dir, _) = resolved_pkg.directory(self.path());
|
||||||
|
@ -247,6 +259,10 @@ impl Project {
|
||||||
dep,
|
dep,
|
||||||
&container_dir,
|
&container_dir,
|
||||||
&self.path().join(resolved_pkg.packages_folder()),
|
&self.path().join(resolved_pkg.packages_folder()),
|
||||||
|
resolved_pkg
|
||||||
|
.dependencies
|
||||||
|
.iter()
|
||||||
|
.any(|(n, _)| n.name() == dep_name.name()),
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
LinkingDependenciesError(
|
LinkingDependenciesError(
|
||||||
|
@ -267,7 +283,14 @@ impl Project {
|
||||||
linking_dir.display()
|
linking_dir.display()
|
||||||
);
|
);
|
||||||
|
|
||||||
link(self, resolved_pkg, linking_dir, linking_dir).map_err(|e| {
|
link(
|
||||||
|
self,
|
||||||
|
resolved_pkg,
|
||||||
|
linking_dir,
|
||||||
|
linking_dir,
|
||||||
|
root_deps.contains(name.name()),
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
LinkingDependenciesError(
|
LinkingDependenciesError(
|
||||||
e,
|
e,
|
||||||
name.clone(),
|
name.clone(),
|
||||||
|
|
|
@ -110,7 +110,6 @@ impl FromStr for Realm {
|
||||||
|
|
||||||
/// The manifest of a package
|
/// The manifest of a package
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
// #[serde(deny_unknown_fields)]
|
|
||||||
pub struct Manifest {
|
pub struct Manifest {
|
||||||
/// The name of the package
|
/// The name of the package
|
||||||
pub name: StandardPackageName,
|
pub name: StandardPackageName,
|
||||||
|
@ -129,6 +128,10 @@ pub struct Manifest {
|
||||||
pub realm: Option<Realm>,
|
pub realm: Option<Realm>,
|
||||||
/// Indices of the package
|
/// Indices of the package
|
||||||
pub indices: BTreeMap<String, String>,
|
pub indices: BTreeMap<String, String>,
|
||||||
|
/// The command to generate a `sourcemap.json`
|
||||||
|
#[cfg(feature = "wally")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub sourcemap_generator: Option<String>,
|
||||||
|
|
||||||
/// The dependencies of the package
|
/// The dependencies of the package
|
||||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||||
|
@ -289,6 +292,8 @@ impl Manifest {
|
||||||
crate::project::DEFAULT_INDEX_NAME.to_string(),
|
crate::project::DEFAULT_INDEX_NAME.to_string(),
|
||||||
"".to_string(),
|
"".to_string(),
|
||||||
)]),
|
)]),
|
||||||
|
sourcemap_generator: None,
|
||||||
|
|
||||||
dependencies,
|
dependencies,
|
||||||
peer_dependencies: Vec::new(),
|
peer_dependencies: Vec::new(),
|
||||||
description: wally_manifest.package.description,
|
description: wally_manifest.package.description,
|
||||||
|
|
|
@ -41,6 +41,8 @@ fn test_resolves_package() {
|
||||||
private: true,
|
private: true,
|
||||||
realm: None,
|
realm: None,
|
||||||
indices: Default::default(),
|
indices: Default::default(),
|
||||||
|
sourcemap_generator: None,
|
||||||
|
|
||||||
dependencies: vec![],
|
dependencies: vec![],
|
||||||
peer_dependencies: vec![],
|
peer_dependencies: vec![],
|
||||||
description: Some(description.to_string()),
|
description: Some(description.to_string()),
|
||||||
|
@ -78,6 +80,8 @@ fn test_resolves_package() {
|
||||||
private: true,
|
private: true,
|
||||||
realm: None,
|
realm: None,
|
||||||
indices: Default::default(),
|
indices: Default::default(),
|
||||||
|
sourcemap_generator: None,
|
||||||
|
|
||||||
dependencies: vec![specifier.clone()],
|
dependencies: vec![specifier.clone()],
|
||||||
peer_dependencies: vec![specifier_2.clone()],
|
peer_dependencies: vec![specifier_2.clone()],
|
||||||
description: Some(description.to_string()),
|
description: Some(description.to_string()),
|
||||||
|
|
Loading…
Reference in a new issue