Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
nokazn committed Feb 18, 2024
1 parent ca18c10 commit cce41d8
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 55 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
result
.direnv
node_modules
examples
7 changes: 7 additions & 0 deletions src/cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use std::{path::Path, process::Command};

use crate::core::PackageManagerKind;

pub fn run_install(base_dir: impl AsRef<Path>, kind: PackageManagerKind) {
// Command::new(program)
}
29 changes: 27 additions & 2 deletions src/core.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use serde::{Deserialize, Serialize};
use std::result;
use std::{path::Path, result};
use strum_macros::EnumIter;

use crate::errors::Error;
use crate::{
errors::Error,
lockfile::Lockfile,
project::ProjectRoot,
utils::hash::{Hash, Hashable},
};

pub type Result<T> = result::Result<T, Error>;

Expand Down Expand Up @@ -39,3 +44,23 @@ impl PackageManagerKind {
}
}
}

struct Core;

impl Core {
pub fn run(base_dir: impl AsRef<Path>) -> Result<()> {
let lockfile = Lockfile::new(&base_dir);
let lockfile_kind = lockfile.map(|l| l.kind).ok();
let project_root = ProjectRoot::new(&base_dir, lockfile_kind)?;
project_root.generate_hash();
Ok(())
}

fn generate_cache_key(lockfile: Lockfile, project: ProjectRoot) -> Result<Hash> {
let lockfile_hash = lockfile.generate_hash()?;
let project_hash = project.generate_hash()?;
Ok(Hash(
format!("{}-{}", lockfile_hash, project_hash).to_string(),
))
}
}
7 changes: 4 additions & 3 deletions src/lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use strum::IntoEnumIterator;
use crate::{
core::{PackageManagerKind, Result},
errors::Error,
utils::hash::Hash,
};

#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -37,13 +38,13 @@ impl Lockfile {
None
}

pub fn generate_hash(&self) -> Result<String> {
pub fn generate_hash(&self) -> Result<Hash> {
let mut file = fs::File::open(&self.path).map_err(|error| Error::Any(error.to_string()))?;
let mut hasher = Sha256::new();
io::copy(&mut file, &mut hasher).map_err(|error| Error::Any(error.to_string()))?;
let raw_hash = hasher.finalize();
let hash = Base64::encode_string(&raw_hash);
Ok(hash)
Ok(Hash(hash))
}
}

Expand Down Expand Up @@ -118,7 +119,7 @@ mod tests {
fn test_generate_hash_each(case: GenerateHashTestCase) {
let lockfile = Lockfile::new(case.input).unwrap();
let hash = lockfile.generate_hash().unwrap();
assert_eq!(hash, case.expected);
assert_eq!(hash, Hash(case.expected.to_string()));
}

test_each!(
Expand Down
3 changes: 2 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod cache;
mod cmd;
mod core;
mod errors;
mod lockfile;
Expand All @@ -17,7 +18,7 @@ fn main() {
dbg!(&lockfile, &result.unwrap());

// TODO: 後で消す
let package_json = ProjectRoot::new("./examples", lockfile.kind).unwrap();
let package_json = ProjectRoot::new("./examples", Some(lockfile.kind)).unwrap();
let result = package_json.generate_hash();
dbg!(&result.unwrap());
}
83 changes: 43 additions & 40 deletions src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl WorkspacePackage {
#[derive(Serialize, Deserialize, Hash, Clone, PartialEq, Debug, Default)]
pub struct ProjectRoot {
original: PackageJson,
kind: PackageManagerKind,
pub kind: PackageManagerKind,
root: PackageDependencies,
workspaces: BTreeMap<String, WorkspacePackage>,
}
Expand Down Expand Up @@ -185,17 +185,20 @@ impl Hashable for ProjectRoot {
}

impl ProjectRoot {
pub fn new(base_dir: impl AsRef<Path>, kind: PackageManagerKind) -> Result<Self> {
pub fn new(base_dir: impl AsRef<Path>, kind: Option<PackageManagerKind>) -> Result<Self> {
let original = PackageJson::new(&base_dir)?;
Ok(
let kind = Self::resolve_package_manager_kind(&original, kind);
if let Some(kind) = kind {
Self {
original: original.clone(),
kind: Self::resolve_package_manager_kind(&original, kind),
kind,
root: PackageDependencies::new(original.clone()),
workspaces: Self::resolve_workspaces(&base_dir, kind, original.workspaces),
}
.validate_package_json_fields(&base_dir),
)?
.validate_package_json_fields(&base_dir)
} else {
Err(Error::NoLockfileError(base_dir.as_ref().to_path_buf()))
}
}

fn resolve_workspaces(
Expand All @@ -222,8 +225,8 @@ impl ProjectRoot {

fn resolve_package_manager_kind(
original: &PackageJson,
kind: PackageManagerKind,
) -> PackageManagerKind {
kind: Option<PackageManagerKind>,
) -> Option<PackageManagerKind> {
let package_manager = match &original.packageManager {
Some(package_manager) => package_manager,
None => return kind,
Expand Down Expand Up @@ -252,7 +255,7 @@ impl ProjectRoot {
false
}
})
.unwrap_or(kind),
.or(kind),
None => kind,
}
}
Expand Down Expand Up @@ -351,8 +354,8 @@ mod tests {
);

struct ResolvePackageManagerKindTestCase {
input: (&'static str, PackageManagerKind),
expected: PackageManagerKind,
input: (&'static str, Option<PackageManagerKind>),
expected: Option<PackageManagerKind>,
}

fn test_resolve_package_manager_kind_each(case: ResolvePackageManagerKindTestCase) {
Expand All @@ -362,61 +365,61 @@ mod tests {
};
assert_eq!(
ProjectRoot::resolve_package_manager_kind(&original, case.input.1),
PackageManagerKind::from(case.expected)
case.expected,
);
}

test_each!(
test_resolve_package_manager_kind,
test_resolve_package_manager_kind_each,
"npm" => ResolvePackageManagerKindTestCase {
input: ("npm", PackageManagerKind::Bun),
expected: PackageManagerKind::Npm,
input: ("npm", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Npm),
},
"invalid_npm" => ResolvePackageManagerKindTestCase {
input: (" npm", PackageManagerKind::Bun),
expected: PackageManagerKind::Bun,
input: (" npm", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Bun),
},
"npm_with_valid_version_1" => ResolvePackageManagerKindTestCase {
input: ("[email protected]", PackageManagerKind::Bun),
expected: PackageManagerKind::Npm,
input: ("[email protected]", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Npm),
},
"detect_as_npm_with_invalid_version_1" => ResolvePackageManagerKindTestCase {
input: ("npm@", PackageManagerKind::Bun),
expected: PackageManagerKind::Npm,
input: ("npm@", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Npm),
},
"yarn" => ResolvePackageManagerKindTestCase {
input: ("yarn", PackageManagerKind::Bun),
expected: PackageManagerKind::Yarn,
input: ("yarn", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Yarn),
},
"yarn_with_valid_version_1" => ResolvePackageManagerKindTestCase {
input: ("[email protected]", PackageManagerKind::Bun),
expected: PackageManagerKind::Yarn,
input: ("[email protected]", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Yarn),
},
"yarn_with_valid_version_2" => ResolvePackageManagerKindTestCase {
input: ("[email protected]+sha256.81a00df816059803e6b5148acf03ce313cad36b7f6e5af6efa040a15981a6ffb", PackageManagerKind::Bun),
expected: PackageManagerKind::Yarn,
input: ("[email protected]+sha256.81a00df816059803e6b5148acf03ce313cad36b7f6e5af6efa040a15981a6ffb", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Yarn),
},
"pnpm" => ResolvePackageManagerKindTestCase {
input: ("pnpm", PackageManagerKind::Bun),
expected: PackageManagerKind::Pnpm,
input: ("pnpm", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Pnpm),
},
"pnpm_with_valid_version" => ResolvePackageManagerKindTestCase {
input: ("[email protected]+sha256.2dfc103b0859426dc338ab2796cad7bf83ffb92be0fdd79f65f26ffeb5114ce2", PackageManagerKind::Bun),
expected: PackageManagerKind::Pnpm,
input: ("[email protected]+sha256.2dfc103b0859426dc338ab2796cad7bf83ffb92be0fdd79f65f26ffeb5114ce2", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Pnpm),
},
"detect_as_pnpm_with_invalid_semver" => ResolvePackageManagerKindTestCase {
input: ("pnpm@8", PackageManagerKind::Bun),
expected: PackageManagerKind::Pnpm,
input: ("pnpm@8", Some(PackageManagerKind::Bun)),
expected: Some(PackageManagerKind::Pnpm),
},
"bun_is_not_supported_by_corepack" => ResolvePackageManagerKindTestCase {
input: ("bun", PackageManagerKind::Npm),
expected: PackageManagerKind::Npm,
input: ("bun", Some(PackageManagerKind::Npm)),
expected: Some(PackageManagerKind::Npm),
},
);

struct NewTestCase {
input: (PathBuf, PackageManagerKind),
input: (PathBuf, Option<PackageManagerKind>),
expected: Result<ProjectRoot>,
}

Expand All @@ -440,7 +443,7 @@ mod tests {
"npm" => NewTestCase {
input: (
PathBuf::from("tests/fixtures/workspaces/npm"),
PackageManagerKind::Npm,
Some(PackageManagerKind::Npm),
),
expected: {
let dev_dependencies = btree_map!(
Expand Down Expand Up @@ -472,7 +475,7 @@ mod tests {
"yarn" => NewTestCase {
input: (
PathBuf::from("tests/fixtures/workspaces/yarn"),
PackageManagerKind::Yarn,
Some(PackageManagerKind::Yarn),
),
expected: {
let dev_dependencies = btree_map!(
Expand Down Expand Up @@ -518,14 +521,14 @@ mod tests {
"yarn_private_false" => NewTestCase {
input: (
PathBuf::from("tests/fixtures/workspaces/yarn_private_false"),
PackageManagerKind::Yarn,
Some(PackageManagerKind::Yarn),
),
expected:Err(Error::InvalidPackageJsonPrivateForYarnError(PathBuf::from("tests/fixtures/workspaces/yarn_private_false/package.json")))
},
"pnpm" => NewTestCase {
input: (
PathBuf::from("tests/fixtures/workspaces/pnpm"),
PackageManagerKind::Pnpm,
Some(PackageManagerKind::Pnpm),
),
expected: {
let dev_dependencies = btree_map!(
Expand Down Expand Up @@ -557,7 +560,7 @@ mod tests {
"bun" => NewTestCase {
input: (
PathBuf::from("tests/fixtures/workspaces/bun"),
PackageManagerKind::Bun,
Some(PackageManagerKind::Bun),
),
expected: {
let dev_dependencies = btree_map!(
Expand Down
29 changes: 20 additions & 9 deletions src/utils/hash.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
use base64ct::{Base64, Encoding};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::fmt::Debug;
use std::fmt::{Debug, Display};

use crate::{core::Result, errors::Error};

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)]
pub struct Hash(pub String);

impl Display for Hash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}

impl Hash {
pub fn to_string(&self) -> &str {
self.0.as_str()
Expand All @@ -21,16 +29,19 @@ pub trait Hashable {
Ok(json.into_bytes())
}

fn generate_hash(&self) -> serde_json::Result<Hash>
fn generate_hash(&self) -> Result<Hash>
where
Self: serde::Serialize + Debug,
{
self.to_bytes().map(|bytes| {
let mut generator = Sha256::new();
generator.update(bytes);
let raw_hash = generator.finalize();
let hash = Base64::encode_string(&raw_hash);
Hash(hash)
})
self
.to_bytes()
.map(|bytes| {
let mut generator = Sha256::new();
generator.update(bytes);
let raw_hash = generator.finalize();
let hash = Base64::encode_string(&raw_hash);
Hash(hash)
})
.map_err(|error| Error::Any(error.to_string()))
}
}

0 comments on commit cce41d8

Please sign in to comment.