Skip to content

Commit

Permalink
actually using the lock file to pull dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
tanneberger committed Sep 20, 2024
1 parent 36509d6 commit 2f28b63
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 67 deletions.
114 changes: 54 additions & 60 deletions src/package/lock.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use colored::Colorize;
use serde::{
de::{Error, StdError},
Deserialize, Deserializer, Serialize, Serializer,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use versions::Versioning;

use log::error;
use serde::de::Error as DeserializationError;
use serde::ser::Error as SerializationError;
use std::cmp::PartialEq;
use std::collections::HashMap;
use std::fmt::{Debug, Display, Formatter};
use std::fmt::Display;
use std::fs;
use std::path::{Path, PathBuf};
use std::str::FromStr;
Expand All @@ -21,45 +21,25 @@ use crate::package::{
};
use crate::util::errors::LingoError;

struct ParseLockSourceError {}

impl StdError for ParseLockSourceError {}

impl Debug for ParseLockSourceError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.serialize_str("ParseLockSourceError")
}
}

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

impl Error for ParseLockSourceError {
fn custom<T>(_: T) -> Self
where
T: Display,
{
todo!()
}
}
pub struct ParseLockSourceError {}

/// Different package sources types, available inside the lock file.
#[derive(PartialEq)]
enum PackageLockSourceType {
pub enum PackageLockSourceType {
REGISTRY,
GIT,
TARBALL,
PATH,
}

struct PackageLockSource {
source_type: PackageLockSourceType,
uri: String,
rev: Option<String>,
/// Struct that saves the source uri string
pub struct PackageLockSource {
pub source_type: PackageLockSourceType,
pub uri: String,
pub rev: Option<String>,
}

// Tries to parse the enum value from given string
impl FromStr for PackageLockSourceType {
type Err = ParseLockSourceError;

Expand All @@ -74,6 +54,7 @@ impl FromStr for PackageLockSourceType {
}
}

/// generates the corresponding string based on enum value
impl Display for PackageLockSourceType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let str = match self {
Expand All @@ -96,6 +77,8 @@ impl From<ProjectSource> for PackageLockSourceType {
}
}

/// Parses the whole source uri string of a package
/// the uri string follows the pattern <type>+<url>(#<git-rev>)
impl FromStr for PackageLockSource {
type Err = ParseLockSourceError;

Expand Down Expand Up @@ -128,36 +111,16 @@ impl FromStr for PackageLockSource {
}
}

impl Serialize for PackageLockSource {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let source_type = self.source_type.to_string();
let mut serialized_string = format!("{}+{}", source_type, self.uri);

if self.source_type == PackageLockSourceType::GIT {
if let Some(rev) = self.rev.clone() {
serialized_string = format!("{}#{}", serialized_string, rev)
} else {
println!("ERROR cannot generate lock file for git without rev");
}
}

serializer.serialize_str(&serialized_string)
}
}

#[derive(Deserialize, Serialize)]
pub struct PackageLock {
name: String,
pub name: String,
#[serde(
serialize_with = "serialize_version",
deserialize_with = "deserialize_version"
)]
version: Versioning,
source: PackageLockSource,
checksum: String,
pub version: Versioning,
pub source: PackageLockSource,
pub checksum: String,
}

impl From<DependencyTreeNode> for PackageLock {
Expand Down Expand Up @@ -194,6 +157,27 @@ impl<'de> Deserialize<'de> for PackageLockSource {
}
}

impl Serialize for PackageLockSource {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let source_type = self.source_type.to_string();
let mut serialized_string = format!("{}+{}", source_type, self.uri);

if self.source_type == PackageLockSourceType::GIT {
if let Some(rev) = self.rev.clone() {
serialized_string = format!("{}#{}", serialized_string, rev)
} else {
error!("expected and revision but got none during serialization of lock file!");
return Err(S::Error::custom("expected revision but gone None"));
}
}

serializer.serialize_str(&serialized_string)
}
}

#[derive(Deserialize, Serialize, Default)]
pub struct DependencyLock {
/// mapping from package name to location
Expand Down Expand Up @@ -224,12 +208,22 @@ impl DependencyLock {
for (_, lock) in self.dependencies.iter() {
let temp = lfc_include_folder.join(&lock.name);

print!("{} reading ... ", lock.name.green().bold(),);
if !temp.join("Lingo.toml").exists() {
let mut details = PackageDetails::try_from(&lock.source)?;
let lib_path = lfc_include_folder.join(&lock.name);

details.fetch(&lib_path).expect("cannot pull package");
}

let lingo_toml_text = fs::read_to_string(&temp.join("Lingo.toml"))?;

Check warning on line 218 in src/package/lock.rs

View workflow job for this annotation

GitHub Actions / Clippy Output

the borrowed expression implements the required traits

warning: the borrowed expression implements the required traits --> src/package/lock.rs:218:54 | 218 | let lingo_toml_text = fs::read_to_string(&temp.join("Lingo.toml"))?; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: change this to: `temp.join("Lingo.toml")` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args = note: `#[warn(clippy::needless_borrows_for_generic_args)]` on by default
let read_toml = toml::from_str::<ConfigFile>(&lingo_toml_text)?.to_config(&temp);

println!("{}", read_toml.package.version);
println!(
"{} {} ... {}",
"Reading".green().bold(),
lock.name,
read_toml.package.version
);

let lib = match read_toml.library {
Some(value) => value,
Expand Down
34 changes: 27 additions & 7 deletions src/package/management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use url::{ParseError, Url};

use crate::package::lock::{PackageLockSource, PackageLockSourceType};
use crate::package::{
lock::DependencyLock,
target_properties::LibraryTargetProperties,
Expand Down Expand Up @@ -40,6 +43,27 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Re
Ok(())
}

impl TryFrom<&PackageLockSource> for PackageDetails {
type Error = ParseError;

fn try_from(value: &PackageLockSource) -> Result<Self, Self::Error> {
let url = &value.uri;
Ok(PackageDetails {
version: Default::default(),
mutual_exclusive: match value.source_type {
PackageLockSourceType::REGISTRY => {
todo!()
}
PackageLockSourceType::GIT => ProjectSource::Git(Url::from_str(url)?),
PackageLockSourceType::TARBALL => ProjectSource::TarBall(Url::from_str(url)?),
PackageLockSourceType::PATH => ProjectSource::Path(PathBuf::from(url)),
},
git_tag: value.rev.clone().map(|rev| GitLock::Rev(rev)),

Check warning on line 61 in src/package/management.rs

View workflow job for this annotation

GitHub Actions / Clippy Output

redundant closure

warning: redundant closure --> src/package/management.rs:61:44 | 61 | git_tag: value.rev.clone().map(|rev| GitLock::Rev(rev)), | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `GitLock::Rev` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure = note: `#[warn(clippy::redundant_closure)]` on by default
git_rev: value.rev.clone(),
})
}
}

impl PackageDetails {
/// this function fetches the specified location and places it at the given location
pub fn fetch(&mut self, library_path: &PathBuf) -> anyhow::Result<()> {
Expand Down Expand Up @@ -97,7 +121,7 @@ impl DependencyManager {
// checks if a Lingo.lock file exists
if lock_file.exists() {
// reads and parses Lockfile
lock = toml::from_str::<DependencyLock>(&std::fs::read_to_string(lock_file)?)
lock = toml::from_str::<DependencyLock>(&fs::read_to_string(lock_file)?)
.expect("cannot parse lock");

// if a lock file is present it will load the dependencies from it and checks
Expand All @@ -114,20 +138,17 @@ impl DependencyManager {
manager = DependencyManager::default();

// starts recursively pulling dependencies
println!("pull");
let root_nodes = manager.pull(dependencies.clone(), target_path)?;

// flattens the dependency tree and makes the package selection
let selection = DependencyManager::flatten(root_nodes.clone())?;
println!("selection {}", selection.len());

// creates a lock file struct from the selected packages
lock = DependencyLock::create(selection);
println!("locking {}", lock.dependencies.len());

// writes the lock file down
let mut lock_file = File::create(target_path.join("../Lingo.lock"))?;
let serialized_toml = toml::to_string(&lock).expect("cannot generate toml");
println!("{}", serialized_toml);

lock_file.write_all(serialized_toml.as_ref())?;

Expand Down Expand Up @@ -155,15 +176,14 @@ impl DependencyManager {

while !self.pulling_queue.is_empty() {
if let Some((package_name, package_details)) = self.pulling_queue.pop() {
print!("{} pulling ...", package_name.green().bold());
print!("{} {} ...", "Cloning".green().bold(), package_name);
let node = match self.non_recursive_fetching(
&package_name,
package_details,
&sub_dependency_path,
) {
Ok(value) => value,
Err(e) => {
println!("error: {:?}!", e);
return Err(e);
}
};
Expand Down

0 comments on commit 2f28b63

Please sign in to comment.