From b33b8ecaf9f633bf3234aa5ae92bd11481fa7f4b Mon Sep 17 00:00:00 2001 From: Rynco Maekawa Date: Thu, 1 Aug 2024 17:45:44 +0800 Subject: [PATCH 1/7] Add git package definition --- crates/moonutil/src/mooncakes.rs | 37 ++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/crates/moonutil/src/mooncakes.rs b/crates/moonutil/src/mooncakes.rs index f5dab4c3..6d19db6d 100644 --- a/crates/moonutil/src/mooncakes.rs +++ b/crates/moonutil/src/mooncakes.rs @@ -18,6 +18,7 @@ use std::{ collections::HashMap, + fmt::Display, fs::File, io::BufReader, path::{Path, PathBuf}, @@ -89,14 +90,42 @@ impl FromStr for ModuleName { } } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct GitSource { + url: String, + branch: Option, + revision: Option, +} + +impl Display for GitSource { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.url)?; + if self.branch.is_some() || self.revision.is_some() { + write!(f, " (")?; + let mut first = true; + if let Some(branch) = &self.branch { + write!(f, "branch: {}", branch)?; + first = false; + } + if let Some(revision) = &self.revision { + if !first { + write!(f, ", ")?; + } + write!(f, "revision: {}", revision)?; + } + write!(f, ")")?; + } + Ok(()) + } +} + #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum ModuleSourceKind { /// Module comes from some registry. If param is `None`, it comes from the default /// registry. Otherwise it comes from a specific registry (unused for now). Registry(Option), // Registry ID? /// Module comes from a git repository. - // TODO: add branch/commit - Git(String), + Git(GitSource), /// Module comes from a local path. The path must be absolute. Local(PathBuf), } @@ -167,11 +196,11 @@ impl ModuleSource { }) } - pub fn git(name: ModuleName, url: String, version: Version) -> Self { + pub fn git(name: ModuleName, details: GitSource, version: Version) -> Self { ModuleSource { name, version, - source: ModuleSourceKind::Git(url), + source: ModuleSourceKind::Git(details), } } } From 1f068cde696e9c56fe63a30e42b3b2e640d688c5 Mon Sep 17 00:00:00 2001 From: Rynco Maekawa Date: Thu, 1 Aug 2024 17:53:05 +0800 Subject: [PATCH 2/7] Refine git dependency declaration --- crates/moonutil/src/dependency.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/moonutil/src/dependency.rs b/crates/moonutil/src/dependency.rs index 6a5ff4ad..5db98a17 100644 --- a/crates/moonutil/src/dependency.rs +++ b/crates/moonutil/src/dependency.rs @@ -33,12 +33,17 @@ pub struct DependencyInfo { /// Local path to the dependency. Overrides the version requirement. #[serde(skip_serializing_if = "Option::is_none")] pub path: Option, - /// Git repository URL. Overrides the version requirement. + + /// Git repository URL. Overrides the version requirement unless the dependency comes from a + /// registry. #[serde(skip_serializing_if = "Option::is_none")] pub git: Option, /// Git branch to use. #[serde(skip_serializing_if = "Option::is_none", rename = "branch")] pub git_branch: Option, + /// Git revision to use. + #[serde(skip_serializing_if = "Option::is_none", rename = "revision")] + pub git_revision: Option, } fn version_is_default(version: &VersionReq) -> bool { @@ -70,7 +75,10 @@ pub enum DependencyInfoJson { impl DependencyInfo { /// Check if the requirement is simple. That is, it only contains a version requirement fn is_simple(&self) -> bool { - self.path.is_none() && self.git.is_none() && self.git_branch.is_none() + self.path.is_none() + && self.git.is_none() + && self.git_branch.is_none() + && self.git_revision.is_none() } #[allow(clippy::needless_update)] // More fields will be added later From 8bf810fcb9855aa84500bd837c5242b736cc040d Mon Sep 17 00:00:00 2001 From: Rynco Maekawa Date: Fri, 2 Aug 2024 11:45:49 +0800 Subject: [PATCH 3/7] Add git dependency support for resolver --- Cargo.lock | 88 ++++++++++++++++++++ Cargo.toml | 1 + crates/mooncake/Cargo.toml | 2 + crates/mooncake/src/resolver.rs | 1 + crates/mooncake/src/resolver/env.rs | 60 +++++++++++++- crates/mooncake/src/resolver/git.rs | 121 ++++++++++++++++++++++++++++ crates/mooncake/src/resolver/mvs.rs | 79 +++++++++++------- crates/moonutil/Cargo.toml | 1 + crates/moonutil/src/hash.rs | 15 ++++ crates/moonutil/src/lib.rs | 1 + crates/moonutil/src/moon_dir.rs | 12 +++ crates/moonutil/src/mooncakes.rs | 6 +- 12 files changed, 351 insertions(+), 36 deletions(-) create mode 100644 crates/mooncake/src/resolver/git.rs create mode 100644 crates/moonutil/src/hash.rs diff --git a/Cargo.lock b/Cargo.lock index fd7fcf82..727b398b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,6 +218,10 @@ name = "cc" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +dependencies = [ + "jobserver", + "libc", +] [[package]] name = "cfg-if" @@ -749,6 +753,21 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +[[package]] +name = "git2" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" +dependencies = [ + "bitflags 2.6.0", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + [[package]] name = "h2" version = "0.3.26" @@ -1054,6 +1073,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -1095,6 +1123,46 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libgit2-sys" +version = "0.17.0+1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + +[[package]] +name = "libssh2-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "line-index" version = "0.1.1" @@ -1268,6 +1336,7 @@ dependencies = [ "dunce", "expect-test", "form_urlencoded", + "git2", "indexmap", "log", "moonutil", @@ -1281,6 +1350,7 @@ dependencies = [ "test-log", "thiserror", "tokio", + "url", "walkdir", "zip", ] @@ -1308,6 +1378,7 @@ dependencies = [ "serde", "serde_json_lenient", "thiserror", + "twox-hash", "vergen", "walkdir", ] @@ -1968,6 +2039,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.11.1" @@ -2265,6 +2342,17 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "rand", + "static_assertions", +] + [[package]] name = "typenum" version = "1.17.0" diff --git a/Cargo.toml b/Cargo.toml index cf3a444c..808508b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,7 @@ test-log = "0.2" fs4 = { version = "0.8.3", features = ["sync"] } ariadne = { version = "0.4.1", features = ["auto-color"] } clap_complete = { version = "4.5.4" } +twox-hash = { version = "1.6.3" } [profile.release] debug = false diff --git a/crates/mooncake/Cargo.toml b/crates/mooncake/Cargo.toml index c4cbf1f4..d176b0c2 100644 --- a/crates/mooncake/Cargo.toml +++ b/crates/mooncake/Cargo.toml @@ -46,6 +46,8 @@ indexmap.workspace = true petgraph.workspace = true thiserror.workspace = true dunce.workspace = true +git2 = "0.19.0" +url = "2.5.2" [dev-dependencies] expect-test.workspace = true diff --git a/crates/mooncake/src/resolver.rs b/crates/mooncake/src/resolver.rs index 875923f1..5702657a 100644 --- a/crates/mooncake/src/resolver.rs +++ b/crates/mooncake/src/resolver.rs @@ -26,6 +26,7 @@ use thiserror::Error; use crate::registry::RegistryList; pub mod env; +mod git; pub mod mvs; pub use mvs::MvsSolver; diff --git a/crates/mooncake/src/resolver/env.rs b/crates/mooncake/src/resolver/env.rs index 9cd953ae..2dcc9bcd 100644 --- a/crates/mooncake/src/resolver/env.rs +++ b/crates/mooncake/src/resolver/env.rs @@ -22,12 +22,14 @@ use std::{ rc::Rc, }; +use anyhow::Context; use moonutil::{ - common::read_module_desc_file_in_dir, + common::{read_module_desc_file_in_dir, MOON_MOD_JSON}, module::MoonMod, - mooncakes::{ModuleName, ModuleSource, ModuleSourceKind}, + mooncakes::{GitSource, ModuleName, ModuleSource, ModuleSourceKind}, }; use semver::Version; +use walkdir::WalkDir; use crate::registry::RegistryList; @@ -37,6 +39,7 @@ pub struct ResolverEnv<'a> { registries: &'a RegistryList, errors: Vec, local_module_cache: HashMap>, + git_module_cache: HashMap)>>, } impl<'a> ResolverEnv<'a> { @@ -45,6 +48,7 @@ impl<'a> ResolverEnv<'a> { registries, errors: Vec::new(), local_module_cache: HashMap::new(), + git_module_cache: HashMap::new(), } } @@ -104,4 +108,56 @@ impl<'a> ResolverEnv<'a> { .insert(path.to_owned(), Rc::clone(&rc_module)); Ok(rc_module) } + + pub fn resolve_git_module( + &mut self, + git_info: &GitSource, + expected_name: &ModuleName, + ) -> Result, ResolverError> { + // Check cache + if let Some(mods) = self.git_module_cache.get(git_info) { + if let Some((_, module)) = mods.get(expected_name) { + return Ok(module.clone()); + } + } + + let checkout = super::git::resolve(git_info) + .with_context(|| format!("Failed to resolve git source {}", git_info)) + .map_err(ResolverError::Other)?; + let mods = recursively_scan_for_moon_mods(&checkout) + .with_context(|| format!("Failed to scan for moon mods in {}", checkout.display())) + .map_err(ResolverError::Other)?; + + // populate cache + let mut mods_map = HashMap::new(); + for (path, module) in mods { + mods_map.insert( + module.name.parse().map_err(|e| { + ResolverError::Other(anyhow::anyhow!("Failed to parse module name: {}", e)) + })?, + (path, module.clone()), + ); + } + let entry = self + .git_module_cache + .entry(git_info.clone()) + .or_insert(mods_map); + + entry + .get(expected_name) + .map(|(_, module)| module.clone()) + .ok_or_else(|| ResolverError::ModuleMissing(expected_name.clone())) + } +} + +fn recursively_scan_for_moon_mods(path: &Path) -> anyhow::Result)>> { + let mut mods = Vec::new(); + for entry in WalkDir::new(path) { + let entry = entry?; + if entry.file_name() == MOON_MOD_JSON { + let module = read_module_desc_file_in_dir(entry.path())?; + mods.push((entry.path().to_owned(), Rc::new(module))); + } + } + Ok(mods) } diff --git a/crates/mooncake/src/resolver/git.rs b/crates/mooncake/src/resolver/git.rs new file mode 100644 index 00000000..db88009e --- /dev/null +++ b/crates/mooncake/src/resolver/git.rs @@ -0,0 +1,121 @@ +//! Resolves git-sourced modules. +//! +//! Git modules reside in 2 different locations: +//! - A raw git repository is checked out into the registry cache. +//! - For each different revision of the git repository, a separate directory is created in the +//! registry cache, and is checked out into that directory. +//! +//! This mimics the behavior of cargo's git dependencies. + +use std::path::{Path, PathBuf}; + +use anyhow::Context; +use git2::{build::CheckoutBuilder, FetchOptions, Oid, Repository}; +use moonutil::{ + hash::short_hash, + moon_dir::{git_checkouts_dir, git_repos_dir}, + mooncakes::GitSource, +}; +use url::Url; + +fn ident(url: &Url) -> &str { + url.path_segments() + .and_then(|s| s.last()) + .unwrap_or("") + .trim_end_matches(".git") +} + +fn repo_name(url: &Url) -> String { + let id = ident(url); + let hash = short_hash(url); + format!("{}-{}", id, hash) +} + +fn repo_path(url: &Url) -> PathBuf { + git_repos_dir().join(repo_name(url)) +} + +fn repo_checkout_path(url: &Url, commit: Oid) -> PathBuf { + git_checkouts_dir() + .join(repo_name(url)) + .join(commit.to_string()) +} + +pub fn init_repo_dir(url: &Url) -> anyhow::Result<(PathBuf, Repository)> { + let path = repo_path(url); + std::fs::create_dir_all(&path).context("failed to create git repository directory")?; + git2::Repository::init_bare(&path).context("failed to initialize git repository")?; + let repo = git2::Repository::open_bare(&path).context("failed to open git repository")?; + repo.remote("origin", url.as_str())?; + + Ok((path, repo)) +} + +pub fn open_or_init_repo_dir(url: &Url) -> anyhow::Result<(PathBuf, Repository)> { + let path = repo_path(url); + if path.exists() { + let repo = git2::Repository::open_bare(&path).context("failed to open git repository")?; + Ok((path, repo)) + } else { + init_repo_dir(url) + } +} + +fn pull_branch(repo: &Repository, branch: &str) -> anyhow::Result { + let mut remote = repo.find_remote("origin")?; + remote.fetch(&[branch], Some(&mut FetchOptions::new().depth(1)), None)?; + + let branch_ref = format!("refs/remotes/origin/{}", branch); + let branch_ref = repo.find_reference(&branch_ref)?; + let branch_commit = branch_ref.peel_to_commit()?; + Ok(branch_commit.id()) +} + +fn pull_default_branch(repo: &Repository) -> anyhow::Result { + let default_branch = repo + .find_remote("origin")? + .default_branch() + .context("No default branch found in remote")?; + let default_branch = default_branch + .as_str() + .ok_or_else(|| anyhow::anyhow!("Malformed default branch name in remote"))?; + + pull_branch(repo, default_branch) +} + +fn pull_specific_revision(repo: &Repository, revision: &str) -> anyhow::Result { + let mut remote = repo.find_remote("origin")?; + remote.fetch(&[revision], Some(FetchOptions::new().depth(1)), None)?; + let commit = repo.revparse_single(revision)?; + Ok(commit.id()) +} + +fn checkout(repo: &Repository, commit: Oid, dst: &Path) -> anyhow::Result<()> { + let commit = repo.find_commit(commit)?; + let tree = commit.tree()?; + repo.checkout_tree( + &tree.into_object(), + Some(CheckoutBuilder::new().target_dir(dst)), + )?; + Ok(()) +} + +pub fn resolve(source: &GitSource) -> anyhow::Result { + let source_url = Url::parse(&source.url).context("Malformed git source url")?; + // Open or initialize the repository. + let (_, repo) = open_or_init_repo_dir(&source_url)?; + // Find the revision to checkout. + let commit = if let Some(branch) = &source.branch { + pull_branch(&repo, branch)? + } else if let Some(revision) = &source.revision { + pull_specific_revision(&repo, revision)? + } else { + pull_default_branch(&repo)? + }; + // Checkout the revision to the cache. + let checkout_path = repo_checkout_path(&source_url, commit); + if !checkout_path.exists() { + checkout(&repo, commit, &checkout_path)?; + } + Ok(checkout_path) +} diff --git a/crates/mooncake/src/resolver/mvs.rs b/crates/mooncake/src/resolver/mvs.rs index 0d754f76..c8d1c195 100644 --- a/crates/mooncake/src/resolver/mvs.rs +++ b/crates/mooncake/src/resolver/mvs.rs @@ -342,39 +342,11 @@ fn resolve_pkg( ) -> Result<(ModuleSource, Rc), ResolverError> { if let Some(path) = &req.path { if local_dep_allowed(dependant) { - // Try resolving using local dependency - let root = root_path_of(dependant); - assert!( - root.is_absolute(), - "Root path of {} is not absolute! Got: {}", - dependant, - root.display() - ); - let dep_path = root.join(path); - let dep_path = - dunce::canonicalize(dep_path).map_err(|err| ResolverError::Other(err.into()))?; - let res = env.resolve_local_module(&dep_path)?; - let ms = ModuleSource { - name: pkg_name.clone(), - version: res.version.clone().expect("Expected version in module"), - source: ModuleSourceKind::Local(dep_path), - }; - // Assert version matches - if let Some(v) = &res.version { - if !req.version.matches(v) { - return Err(ResolverError::LocalDepVersionMismatch( - Box::new(ms), - req.version.clone(), - )); - } - } - return Ok((ms, res)); + return resolve_pkg_local(dependant, path, env, pkg_name, req); } } - if let Some(_url) = &req.git { - if git_dep_allowed(dependant) { - // TODO: Try resolving using git dependency - } + if req.git.is_some() && git_dep_allowed(dependant) { + return resolve_pkg_git(dependant, req, env, pkg_name); } // If neither git nor local dependencies can be resolved (either because the user // didn't specify it at all, or because the repo comes from a registry), we fallback @@ -394,6 +366,51 @@ fn resolve_pkg( Ok((ms, module)) } +fn resolve_pkg_local( + dependant: &ModuleSource, + path: &String, + env: &mut ResolverEnv, + pkg_name: &ModuleName, + req: &DependencyInfo, +) -> Result<(ModuleSource, Rc), ResolverError> { + // Try resolving using local dependency + let root = root_path_of(dependant); + assert!( + root.is_absolute(), + "Root path of {} is not absolute! Got: {}", + dependant, + root.display() + ); + let dep_path = root.join(path); + let dep_path = dunce::canonicalize(dep_path).map_err(|err| ResolverError::Other(err.into()))?; + let res = env.resolve_local_module(&dep_path)?; + let ms = ModuleSource { + name: pkg_name.clone(), + version: res.version.clone().expect("Expected version in module"), + source: ModuleSourceKind::Local(dep_path), + }; + // Assert version matches + if let Some(v) = &res.version { + if !req.version.matches(v) { + return Err(ResolverError::LocalDepVersionMismatch( + Box::new(ms), + req.version.clone(), + )); + } + } + + Ok((ms, res)) +} + +fn resolve_pkg_git( + dependant: &ModuleSource, + info: &DependencyInfo, + env: &mut ResolverEnv, + pkg_name: &ModuleName, +) -> Result<(ModuleSource, Rc), ResolverError> { + todo!() +} + #[cfg(test)] mod test { use expect_test::expect; diff --git a/crates/moonutil/Cargo.toml b/crates/moonutil/Cargo.toml index 555abf3c..62b80b0d 100644 --- a/crates/moonutil/Cargo.toml +++ b/crates/moonutil/Cargo.toml @@ -43,6 +43,7 @@ ariadne.workspace = true env_logger.workspace = true log.workspace = true thiserror.workspace = true +twox-hash.workspace = true [dev-dependencies] expect-test.workspace = true diff --git a/crates/moonutil/src/hash.rs b/crates/moonutil/src/hash.rs new file mode 100644 index 00000000..70410cd3 --- /dev/null +++ b/crates/moonutil/src/hash.rs @@ -0,0 +1,15 @@ +use std::hash::{Hash, Hasher}; + +use twox_hash::xxh3; + +/// A 64-bit stable hash of the given data. +pub fn short_hash(data: impl Hash) -> u64 { + let mut hasher = xxh3::Hash64::with_seed(0); + data.hash(&mut hasher); + hasher.finish() +} + +/// A 16-character hexadecimal representation of the hash of the given data. +pub fn short_hash_str(data: impl Hash) -> String { + format!("{:016x}", short_hash(data)) +} diff --git a/crates/moonutil/src/lib.rs b/crates/moonutil/src/lib.rs index 933f0d84..65cfbe17 100644 --- a/crates/moonutil/src/lib.rs +++ b/crates/moonutil/src/lib.rs @@ -24,6 +24,7 @@ pub mod dependency; pub mod dirs; pub mod git; pub mod graph; +pub mod hash; pub mod module; pub mod moon_dir; pub mod mooncake_bin; diff --git a/crates/moonutil/src/moon_dir.rs b/crates/moonutil/src/moon_dir.rs index 34738050..102f301f 100644 --- a/crates/moonutil/src/moon_dir.rs +++ b/crates/moonutil/src/moon_dir.rs @@ -123,6 +123,18 @@ pub fn moon_tmp_dir() -> anyhow::Result { Ok(p) } +pub fn git_dir() -> PathBuf { + home().join("git") +} + +pub fn git_repos_dir() -> PathBuf { + git_dir().join("repos") +} + +pub fn git_checkouts_dir() -> PathBuf { + git_dir().join("checkouts") +} + #[test] fn test_moon_dir() { use expect_test::expect; diff --git a/crates/moonutil/src/mooncakes.rs b/crates/moonutil/src/mooncakes.rs index 6d19db6d..00d58237 100644 --- a/crates/moonutil/src/mooncakes.rs +++ b/crates/moonutil/src/mooncakes.rs @@ -92,9 +92,9 @@ impl FromStr for ModuleName { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct GitSource { - url: String, - branch: Option, - revision: Option, + pub url: String, + pub branch: Option, + pub revision: Option, } impl Display for GitSource { From 04c625f5dbfbdc9dde36ef75343fb9e3ac002397 Mon Sep 17 00:00:00 2001 From: Rynco Maekawa Date: Fri, 2 Aug 2024 11:51:09 +0800 Subject: [PATCH 4/7] Add git package resolving --- crates/mooncake/src/dep_dir.rs | 4 +--- crates/mooncake/src/resolver.rs | 2 +- crates/mooncake/src/resolver/mvs.rs | 18 ++++++++++++++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/crates/mooncake/src/dep_dir.rs b/crates/mooncake/src/dep_dir.rs index 4fe09537..5d11babb 100644 --- a/crates/mooncake/src/dep_dir.rs +++ b/crates/mooncake/src/dep_dir.rs @@ -265,9 +265,7 @@ fn map_source_to_dir(dep_dir: &DepDir, module: &ModuleSource) -> PathBuf { pkg_to_dir(dep_dir, &module.name.username, &module.name.pkgname) } ModuleSourceKind::Local(path) => path.clone(), - ModuleSourceKind::Git(url) => { - todo!("Git dependency is not yet supported. Got git url: {}", url) - } + ModuleSourceKind::Git(url) => crate::resolver::git::resolve(url).unwrap(), } } diff --git a/crates/mooncake/src/resolver.rs b/crates/mooncake/src/resolver.rs index 5702657a..35712ac0 100644 --- a/crates/mooncake/src/resolver.rs +++ b/crates/mooncake/src/resolver.rs @@ -26,7 +26,7 @@ use thiserror::Error; use crate::registry::RegistryList; pub mod env; -mod git; +pub mod git; pub mod mvs; pub use mvs::MvsSolver; diff --git a/crates/mooncake/src/resolver/mvs.rs b/crates/mooncake/src/resolver/mvs.rs index c8d1c195..eb5ffd73 100644 --- a/crates/mooncake/src/resolver/mvs.rs +++ b/crates/mooncake/src/resolver/mvs.rs @@ -26,7 +26,7 @@ use anyhow::anyhow; use moonutil::{ dependency::DependencyInfo, module::MoonMod, - mooncakes::{ModuleName, ModuleSource, ModuleSourceKind}, + mooncakes::{GitSource, ModuleName, ModuleSource, ModuleSourceKind}, version::as_caret_comparator, }; use semver::Version; @@ -346,7 +346,7 @@ fn resolve_pkg( } } if req.git.is_some() && git_dep_allowed(dependant) { - return resolve_pkg_git(dependant, req, env, pkg_name); + return resolve_pkg_git(req, env, pkg_name); } // If neither git nor local dependencies can be resolved (either because the user // didn't specify it at all, or because the repo comes from a registry), we fallback @@ -403,12 +403,22 @@ fn resolve_pkg_local( } fn resolve_pkg_git( - dependant: &ModuleSource, info: &DependencyInfo, env: &mut ResolverEnv, pkg_name: &ModuleName, ) -> Result<(ModuleSource, Rc), ResolverError> { - todo!() + let git_info = GitSource { + url: info.git.clone().unwrap(), + branch: info.git_branch.clone(), + revision: info.git_revision.clone(), + }; + let res = env.resolve_git_module(&git_info, pkg_name)?; + let ms = ModuleSource { + name: pkg_name.clone(), + version: res.version.clone().expect("Expected version in module"), + source: ModuleSourceKind::Git(git_info), + }; + Ok((ms, res)) } #[cfg(test)] From b3f8ed56e6c54c347c95a723b5a0509afd0d2c41 Mon Sep 17 00:00:00 2001 From: Rynco Maekawa Date: Fri, 2 Aug 2024 18:05:42 +0800 Subject: [PATCH 5/7] Add tests to git dependency --- Cargo.lock | 11 + crates/mooncake/Cargo.toml | 2 + crates/mooncake/src/resolver/env.rs | 17 +- crates/mooncake/src/resolver/git.rs | 256 +++++++++++++++++- .../mooncake/test/git_test_template/README.md | 1 + .../test/git_test_template/lib/hello.mbt | 3 + .../test/git_test_template/lib/moon.pkg.json | 1 + .../test/git_test_template/moon.mod.json | 9 + .../git_test_template/nonroot_pkg/README.md | 1 + .../nonroot_pkg/lib/hello.mbt | 3 + .../nonroot_pkg/lib/moon.pkg.json | 1 + .../nonroot_pkg/moon.mod.json | 9 + crates/moonutil/src/file_lock.rs | 3 + 13 files changed, 294 insertions(+), 23 deletions(-) create mode 100644 crates/mooncake/test/git_test_template/README.md create mode 100644 crates/mooncake/test/git_test_template/lib/hello.mbt create mode 100644 crates/mooncake/test/git_test_template/lib/moon.pkg.json create mode 100644 crates/mooncake/test/git_test_template/moon.mod.json create mode 100644 crates/mooncake/test/git_test_template/nonroot_pkg/README.md create mode 100644 crates/mooncake/test/git_test_template/nonroot_pkg/lib/hello.mbt create mode 100644 crates/mooncake/test/git_test_template/nonroot_pkg/lib/moon.pkg.json create mode 100644 crates/mooncake/test/git_test_template/nonroot_pkg/moon.mod.json create mode 100644 crates/moonutil/src/file_lock.rs diff --git a/Cargo.lock b/Cargo.lock index 727b398b..7e298619 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,6 +345,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "copy_dir" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "543d1dd138ef086e2ff05e3a48cf9da045da2033d16f8538fd76b86cd49b2ca3" +dependencies = [ + "walkdir", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -1332,6 +1341,7 @@ dependencies = [ "bytes", "clap", "colored", + "copy_dir", "dialoguer", "dunce", "expect-test", @@ -1347,6 +1357,7 @@ dependencies = [ "serde_json", "serde_json_lenient", "sha2", + "tempfile", "test-log", "thiserror", "tokio", diff --git a/crates/mooncake/Cargo.toml b/crates/mooncake/Cargo.toml index d176b0c2..7083b3fc 100644 --- a/crates/mooncake/Cargo.toml +++ b/crates/mooncake/Cargo.toml @@ -52,3 +52,5 @@ url = "2.5.2" [dev-dependencies] expect-test.workspace = true test-log.workspace = true +tempfile.workspace = true +copy_dir = "0.1.3" diff --git a/crates/mooncake/src/resolver/env.rs b/crates/mooncake/src/resolver/env.rs index 2dcc9bcd..ffc39718 100644 --- a/crates/mooncake/src/resolver/env.rs +++ b/crates/mooncake/src/resolver/env.rs @@ -24,16 +24,15 @@ use std::{ use anyhow::Context; use moonutil::{ - common::{read_module_desc_file_in_dir, MOON_MOD_JSON}, + common::read_module_desc_file_in_dir, module::MoonMod, mooncakes::{GitSource, ModuleName, ModuleSource, ModuleSourceKind}, }; use semver::Version; -use walkdir::WalkDir; use crate::registry::RegistryList; -use super::ResolverError; +use super::{git::recursively_scan_for_moon_mods, ResolverError}; pub struct ResolverEnv<'a> { registries: &'a RegistryList, @@ -149,15 +148,3 @@ impl<'a> ResolverEnv<'a> { .ok_or_else(|| ResolverError::ModuleMissing(expected_name.clone())) } } - -fn recursively_scan_for_moon_mods(path: &Path) -> anyhow::Result)>> { - let mut mods = Vec::new(); - for entry in WalkDir::new(path) { - let entry = entry?; - if entry.file_name() == MOON_MOD_JSON { - let module = read_module_desc_file_in_dir(entry.path())?; - mods.push((entry.path().to_owned(), Rc::new(module))); - } - } - Ok(mods) -} diff --git a/crates/mooncake/src/resolver/git.rs b/crates/mooncake/src/resolver/git.rs index db88009e..f458165b 100644 --- a/crates/mooncake/src/resolver/git.rs +++ b/crates/mooncake/src/resolver/git.rs @@ -7,16 +7,22 @@ //! //! This mimics the behavior of cargo's git dependencies. -use std::path::{Path, PathBuf}; +use std::{ + path::{Path, PathBuf}, + rc::Rc, +}; use anyhow::Context; use git2::{build::CheckoutBuilder, FetchOptions, Oid, Repository}; use moonutil::{ + common::{read_module_desc_file_in_dir, read_module_from_json, MOON_MOD_JSON}, hash::short_hash, + module::MoonMod, moon_dir::{git_checkouts_dir, git_repos_dir}, mooncakes::GitSource, }; use url::Url; +use walkdir::WalkDir; fn ident(url: &Url) -> &str { url.path_segments() @@ -63,7 +69,13 @@ pub fn open_or_init_repo_dir(url: &Url) -> anyhow::Result<(PathBuf, Repository)> fn pull_branch(repo: &Repository, branch: &str) -> anyhow::Result { let mut remote = repo.find_remote("origin")?; - remote.fetch(&[branch], Some(&mut FetchOptions::new().depth(1)), None)?; + if !remote.connected() { + remote.connect(git2::Direction::Fetch)?; + } + + remote + .fetch(&[branch], None, None) + .context("Failed to fetch from remote")?; let branch_ref = format!("refs/remotes/origin/{}", branch); let branch_ref = repo.find_reference(&branch_ref)?; @@ -72,15 +84,23 @@ fn pull_branch(repo: &Repository, branch: &str) -> anyhow::Result { } fn pull_default_branch(repo: &Repository) -> anyhow::Result { - let default_branch = repo - .find_remote("origin")? - .default_branch() - .context("No default branch found in remote")?; + let mut remote = repo.find_remote("origin")?; + // if the default branch is not set, we connect to the remote and try again + let default_branch = if let Ok(default_branch) = remote.default_branch() { + default_branch + } else { + remote.connect(git2::Direction::Fetch)?; + remote + .default_branch() + .context("Failed to get default branch")? + }; let default_branch = default_branch .as_str() .ok_or_else(|| anyhow::anyhow!("Malformed default branch name in remote"))?; - - pull_branch(repo, default_branch) + let default_branch = default_branch.trim_start_matches("refs/heads/"); + let res = pull_branch(repo, default_branch); + remote.disconnect()?; + res } fn pull_specific_revision(repo: &Repository, revision: &str) -> anyhow::Result { @@ -115,7 +135,227 @@ pub fn resolve(source: &GitSource) -> anyhow::Result { // Checkout the revision to the cache. let checkout_path = repo_checkout_path(&source_url, commit); if !checkout_path.exists() { + std::fs::create_dir_all(&checkout_path)?; checkout(&repo, commit, &checkout_path)?; } Ok(checkout_path) } + +pub fn recursively_scan_for_moon_mods(path: &Path) -> anyhow::Result)>> { + let mut mods = Vec::new(); + for entry in WalkDir::new(path) { + let entry = entry?; + if entry.file_name() == MOON_MOD_JSON { + let dir = entry.path().parent().unwrap(); + let module = read_module_from_json(entry.path()).context("Failed to read module")?; + mods.push((dir.into(), Rc::new(module))); + } + } + Ok(mods) +} + +#[cfg(test)] +mod test { + use std::path::Path; + + use expect_test::expect; + use walkdir::WalkDir; + + const SAMPLE_GIT_REPO_DIR: &str = "test/git_test_template"; + + fn make_sample_git_repo(path: &Path) { + // cp -r crates/mooncake/test/git_test_template/* repo/ + copy_dir::copy_dir(SAMPLE_GIT_REPO_DIR, path).unwrap(); + + // git init . + let repo = git2::Repository::init(path).unwrap(); + + // config user.{name,email} + repo.config() + .unwrap() + .set_str("user.name", "mooncake-tester") + .unwrap(); + repo.config() + .unwrap() + .set_str("user.email", "me@example.com") + .unwrap(); + + // git add . + let mut index = repo.index().unwrap(); + index + .add_all(["*"].iter(), git2::IndexAddOption::DEFAULT, None) + .unwrap(); + index.write().unwrap(); + let tree_id = index.write_tree().unwrap(); + let tree = repo.find_tree(tree_id).unwrap(); + + // git commit -m "Initial commit" + let head = repo + .commit( + Some("HEAD"), + &repo.signature().unwrap(), + &repo.signature().unwrap(), + "Initial commit", + &tree, + &[], + ) + .unwrap(); + + // git branch main + let commit = repo.find_commit(head).unwrap(); + repo.branch("main", &commit, false).unwrap(); + repo.set_head("refs/heads/main").unwrap(); + + // generate another branch with a different file + + // git checkout -b other + repo.branch("other", &commit, false).unwrap(); + repo.set_head("refs/heads/other").unwrap(); + + // echo "other file" > other_file + let other_path = path.join("other_file"); + std::fs::write(&other_path, "other file").unwrap(); + + // git add other_file + index.add_path(Path::new("other_file")).unwrap(); + index.write().unwrap(); + + // git commit -m "Add other file" + let tree_id = index.write_tree().unwrap(); + let tree = repo.find_tree(tree_id).unwrap(); + repo.commit( + Some("HEAD"), + &repo.signature().unwrap(), + &repo.signature().unwrap(), + "Add other file", + &tree, + &[&commit], + ) + .unwrap(); + + // set default branch back to main + repo.set_head("refs/heads/main").unwrap(); + } + + fn list_dir_contents(dir: &Path) -> String { + WalkDir::new(dir) + .sort_by_file_name() + .into_iter() + .map(|e| { + e.unwrap() + .path() + .strip_prefix(dir) + .unwrap() + .to_string_lossy() + .to_string() + }) + .collect::>() + .join("\n") + } + + #[test] + fn test_basic_git_resolver() { + let temp_dir = tempfile::tempdir().unwrap(); + let repo_path = temp_dir.path().join("repo"); + make_sample_git_repo(&repo_path); + + let test_moon_home = temp_dir.path().join("moon_home"); + std::fs::create_dir_all(&test_moon_home).unwrap(); + std::env::set_var("MOON_HOME", test_moon_home); + + // Try to resolve the git repository. + let source = moonutil::mooncakes::GitSource { + url: format!("file://{}", repo_path.display()), + branch: None, + revision: None, + }; + + let checkout = super::resolve(&source).unwrap(); + assert!(checkout.exists()); + + // Check that the checkout is correct. + let dir_contents = list_dir_contents(&checkout); + expect![[r#" + + README.md + lib + lib/hello.mbt + lib/moon.pkg.json + moon.mod.json + nonroot_pkg + nonroot_pkg/README.md + nonroot_pkg/lib + nonroot_pkg/lib/hello.mbt + nonroot_pkg/lib/moon.pkg.json + nonroot_pkg/moon.mod.json"#]] + .assert_eq(&dir_contents); + } + + #[test] + fn test_git_with_branch_specified() { + let temp_dir = tempfile::tempdir().unwrap(); + let repo_path = temp_dir.path().join("repo"); + make_sample_git_repo(&repo_path); + + let test_moon_home = temp_dir.path().join("moon_home"); + std::fs::create_dir_all(&test_moon_home).unwrap(); + std::env::set_var("MOON_HOME", test_moon_home); + + // Try to resolve the git repository. + let source = moonutil::mooncakes::GitSource { + url: format!("file://{}", repo_path.display()), + branch: Some("other".into()), + revision: None, + }; + + let checkout = super::resolve(&source).unwrap(); + assert!(checkout.exists()); + + // Check that the checkout is correct. + let dir_contents = list_dir_contents(&checkout); + expect![[r#" + + README.md + lib + lib/hello.mbt + lib/moon.pkg.json + moon.mod.json + nonroot_pkg + nonroot_pkg/README.md + nonroot_pkg/lib + nonroot_pkg/lib/hello.mbt + nonroot_pkg/lib/moon.pkg.json + nonroot_pkg/moon.mod.json + other_file"#]] + .assert_eq(&dir_contents); + } + + #[test] + fn test_find_all_packages() { + let temp_dir = tempfile::tempdir().unwrap(); + let repo_path = temp_dir.path().join("repo"); + make_sample_git_repo(&repo_path); + + let test_moon_home = temp_dir.path().join("moon_home"); + std::fs::create_dir_all(&test_moon_home).unwrap(); + std::env::set_var("MOON_HOME", test_moon_home); + + // Try to resolve the git repository. + let source = moonutil::mooncakes::GitSource { + url: format!("file://{}", repo_path.display()), + branch: None, + revision: None, + }; + + let checkout = super::resolve(&source).unwrap(); + assert!(checkout.exists()); + + // Check that the checkout is correct. + let mods = super::recursively_scan_for_moon_mods(&checkout).unwrap(); + let mods = mods + .into_iter() + .map(|(_, module)| module.name.clone()) + .collect::>(); + assert_eq!(mods, vec!["testing/test", "testing/nonroot-test"]); + } +} diff --git a/crates/mooncake/test/git_test_template/README.md b/crates/mooncake/test/git_test_template/README.md new file mode 100644 index 00000000..a263e7d4 --- /dev/null +++ b/crates/mooncake/test/git_test_template/README.md @@ -0,0 +1 @@ +# testing/test \ No newline at end of file diff --git a/crates/mooncake/test/git_test_template/lib/hello.mbt b/crates/mooncake/test/git_test_template/lib/hello.mbt new file mode 100644 index 00000000..9012592a --- /dev/null +++ b/crates/mooncake/test/git_test_template/lib/hello.mbt @@ -0,0 +1,3 @@ +pub fn hello() -> String { + "Hello, world!" +} diff --git a/crates/mooncake/test/git_test_template/lib/moon.pkg.json b/crates/mooncake/test/git_test_template/lib/moon.pkg.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/crates/mooncake/test/git_test_template/lib/moon.pkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/crates/mooncake/test/git_test_template/moon.mod.json b/crates/mooncake/test/git_test_template/moon.mod.json new file mode 100644 index 00000000..67d03cee --- /dev/null +++ b/crates/mooncake/test/git_test_template/moon.mod.json @@ -0,0 +1,9 @@ +{ + "name": "testing/test", + "version": "0.1.0", + "readme": "README.md", + "repository": "", + "license": "Apache-2.0", + "keywords": [], + "description": "" +} \ No newline at end of file diff --git a/crates/mooncake/test/git_test_template/nonroot_pkg/README.md b/crates/mooncake/test/git_test_template/nonroot_pkg/README.md new file mode 100644 index 00000000..a263e7d4 --- /dev/null +++ b/crates/mooncake/test/git_test_template/nonroot_pkg/README.md @@ -0,0 +1 @@ +# testing/test \ No newline at end of file diff --git a/crates/mooncake/test/git_test_template/nonroot_pkg/lib/hello.mbt b/crates/mooncake/test/git_test_template/nonroot_pkg/lib/hello.mbt new file mode 100644 index 00000000..9012592a --- /dev/null +++ b/crates/mooncake/test/git_test_template/nonroot_pkg/lib/hello.mbt @@ -0,0 +1,3 @@ +pub fn hello() -> String { + "Hello, world!" +} diff --git a/crates/mooncake/test/git_test_template/nonroot_pkg/lib/moon.pkg.json b/crates/mooncake/test/git_test_template/nonroot_pkg/lib/moon.pkg.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/crates/mooncake/test/git_test_template/nonroot_pkg/lib/moon.pkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/crates/mooncake/test/git_test_template/nonroot_pkg/moon.mod.json b/crates/mooncake/test/git_test_template/nonroot_pkg/moon.mod.json new file mode 100644 index 00000000..5afcbb7b --- /dev/null +++ b/crates/mooncake/test/git_test_template/nonroot_pkg/moon.mod.json @@ -0,0 +1,9 @@ +{ + "name": "testing/nonroot-test", + "version": "0.1.0", + "readme": "README.md", + "repository": "", + "license": "Apache-2.0", + "keywords": [], + "description": "" +} diff --git a/crates/moonutil/src/file_lock.rs b/crates/moonutil/src/file_lock.rs new file mode 100644 index 00000000..4ae37756 --- /dev/null +++ b/crates/moonutil/src/file_lock.rs @@ -0,0 +1,3 @@ +use std::path::PathBuf; + +struct FileLock(PathBuf); From b585618545fbf8d1069104c7ee282f0729f89468 Mon Sep 17 00:00:00 2001 From: Rynco Maekawa Date: Fri, 2 Aug 2024 18:14:54 +0800 Subject: [PATCH 6/7] License header --- crates/mooncake/src/resolver/git.rs | 20 ++++++++++++++++++- .../git_test_template/README.md | 0 .../git_test_template/lib/hello.mbt | 0 .../git_test_template/lib/moon.pkg.json | 0 .../git_test_template/moon.mod.json | 0 .../git_test_template/nonroot_pkg/README.md | 0 .../nonroot_pkg/lib/hello.mbt | 0 .../nonroot_pkg/lib/moon.pkg.json | 0 .../nonroot_pkg/moon.mod.json | 0 crates/moonutil/src/file_lock.rs | 3 --- crates/moonutil/src/hash.rs | 18 +++++++++++++++++ 11 files changed, 37 insertions(+), 4 deletions(-) rename crates/mooncake/{test => tests}/git_test_template/README.md (100%) rename crates/mooncake/{test => tests}/git_test_template/lib/hello.mbt (100%) rename crates/mooncake/{test => tests}/git_test_template/lib/moon.pkg.json (100%) rename crates/mooncake/{test => tests}/git_test_template/moon.mod.json (100%) rename crates/mooncake/{test => tests}/git_test_template/nonroot_pkg/README.md (100%) rename crates/mooncake/{test => tests}/git_test_template/nonroot_pkg/lib/hello.mbt (100%) rename crates/mooncake/{test => tests}/git_test_template/nonroot_pkg/lib/moon.pkg.json (100%) rename crates/mooncake/{test => tests}/git_test_template/nonroot_pkg/moon.mod.json (100%) delete mode 100644 crates/moonutil/src/file_lock.rs diff --git a/crates/mooncake/src/resolver/git.rs b/crates/mooncake/src/resolver/git.rs index f458165b..b96d0a8a 100644 --- a/crates/mooncake/src/resolver/git.rs +++ b/crates/mooncake/src/resolver/git.rs @@ -1,3 +1,21 @@ +// moon: The build system and package manager for MoonBit. +// Copyright (C) 2024 International Digital Economy Academy +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// For inquiries, you can contact us via e-mail at jichuruanjian@idea.edu.cn. + //! Resolves git-sourced modules. //! //! Git modules reside in 2 different locations: @@ -161,7 +179,7 @@ mod test { use expect_test::expect; use walkdir::WalkDir; - const SAMPLE_GIT_REPO_DIR: &str = "test/git_test_template"; + const SAMPLE_GIT_REPO_DIR: &str = "tests/git_test_template"; fn make_sample_git_repo(path: &Path) { // cp -r crates/mooncake/test/git_test_template/* repo/ diff --git a/crates/mooncake/test/git_test_template/README.md b/crates/mooncake/tests/git_test_template/README.md similarity index 100% rename from crates/mooncake/test/git_test_template/README.md rename to crates/mooncake/tests/git_test_template/README.md diff --git a/crates/mooncake/test/git_test_template/lib/hello.mbt b/crates/mooncake/tests/git_test_template/lib/hello.mbt similarity index 100% rename from crates/mooncake/test/git_test_template/lib/hello.mbt rename to crates/mooncake/tests/git_test_template/lib/hello.mbt diff --git a/crates/mooncake/test/git_test_template/lib/moon.pkg.json b/crates/mooncake/tests/git_test_template/lib/moon.pkg.json similarity index 100% rename from crates/mooncake/test/git_test_template/lib/moon.pkg.json rename to crates/mooncake/tests/git_test_template/lib/moon.pkg.json diff --git a/crates/mooncake/test/git_test_template/moon.mod.json b/crates/mooncake/tests/git_test_template/moon.mod.json similarity index 100% rename from crates/mooncake/test/git_test_template/moon.mod.json rename to crates/mooncake/tests/git_test_template/moon.mod.json diff --git a/crates/mooncake/test/git_test_template/nonroot_pkg/README.md b/crates/mooncake/tests/git_test_template/nonroot_pkg/README.md similarity index 100% rename from crates/mooncake/test/git_test_template/nonroot_pkg/README.md rename to crates/mooncake/tests/git_test_template/nonroot_pkg/README.md diff --git a/crates/mooncake/test/git_test_template/nonroot_pkg/lib/hello.mbt b/crates/mooncake/tests/git_test_template/nonroot_pkg/lib/hello.mbt similarity index 100% rename from crates/mooncake/test/git_test_template/nonroot_pkg/lib/hello.mbt rename to crates/mooncake/tests/git_test_template/nonroot_pkg/lib/hello.mbt diff --git a/crates/mooncake/test/git_test_template/nonroot_pkg/lib/moon.pkg.json b/crates/mooncake/tests/git_test_template/nonroot_pkg/lib/moon.pkg.json similarity index 100% rename from crates/mooncake/test/git_test_template/nonroot_pkg/lib/moon.pkg.json rename to crates/mooncake/tests/git_test_template/nonroot_pkg/lib/moon.pkg.json diff --git a/crates/mooncake/test/git_test_template/nonroot_pkg/moon.mod.json b/crates/mooncake/tests/git_test_template/nonroot_pkg/moon.mod.json similarity index 100% rename from crates/mooncake/test/git_test_template/nonroot_pkg/moon.mod.json rename to crates/mooncake/tests/git_test_template/nonroot_pkg/moon.mod.json diff --git a/crates/moonutil/src/file_lock.rs b/crates/moonutil/src/file_lock.rs deleted file mode 100644 index 4ae37756..00000000 --- a/crates/moonutil/src/file_lock.rs +++ /dev/null @@ -1,3 +0,0 @@ -use std::path::PathBuf; - -struct FileLock(PathBuf); diff --git a/crates/moonutil/src/hash.rs b/crates/moonutil/src/hash.rs index 70410cd3..c2166217 100644 --- a/crates/moonutil/src/hash.rs +++ b/crates/moonutil/src/hash.rs @@ -1,3 +1,21 @@ +// moon: The build system and package manager for MoonBit. +// Copyright (C) 2024 International Digital Economy Academy +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// For inquiries, you can contact us via e-mail at jichuruanjian@idea.edu.cn. + use std::hash::{Hash, Hasher}; use twox_hash::xxh3; From cc60c8d7c722b4239cbdd7860e585470629fad0b Mon Sep 17 00:00:00 2001 From: Rynco Maekawa Date: Fri, 2 Aug 2024 18:18:05 +0800 Subject: [PATCH 7/7] Skip license header check for mooncake test template --- licenserc.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/licenserc.toml b/licenserc.toml index 0486f58a..01164bbe 100644 --- a/licenserc.toml +++ b/licenserc.toml @@ -43,4 +43,5 @@ excludes = [ "crates/moon/tests/test_cases/**", "!crates/moon/tests/test_cases/mod.rs", "crates/moonbuild/template/**", + "crates/mooncake/tests/**", ]