pub mod fields;
use std::collections::HashMap;
use plow_package_management::lock::{LockFile, PackageInLockFile};
use plow_package_management::registry::Registry;
use self::fields::FieldsDirectory;
use crate::config::files::workspace_manifest::WorkspaceManifestFile;
use crate::config::PlowConfig;
use crate::manifest::FieldManifest;
use crate::resolve::resolve;
use crate::{error::CliError, error::FieldAccessError::*, error::WorkspaceInitializationError::*};
use dialoguer::{theme::ColorfulTheme, Confirm};
#[allow(clippy::too_many_lines)]
pub fn prepare(config: &PlowConfig) -> Result<(), CliError> {
if Confirm::with_theme(&ColorfulTheme::default())
.with_prompt("Plow will restructure this folder looking for .ttl files and grouping them to another folder backing up the existing ones, would you like to continue?")
.default(true)
.interact()
.unwrap()
{
let manifest_file_path = config.working_dir.path.join("Plow.toml");
if manifest_file_path.exists() {
std::fs::remove_file(&manifest_file_path)
.map_err(|err| FailedToRemoveWorkspaceManifestFile(err.to_string()))?;
}
let lock_file_path = config.working_dir.path.join("Plow.lock");
if lock_file_path.exists() {
std::fs::remove_file(&lock_file_path)
.map_err(|err| FailedToRemoveWorkspaceManifestFile(err.to_string()))?;
}
let fields_dir_path = config.working_dir.path.join("fields");
let maybe_backed_up_fields_dir_path =
FieldsDirectory::backup_if_already_exists(&fields_dir_path, config)?;
let mut fields_dir =
if let Some(ref backed_up_fields_dir_path) = maybe_backed_up_fields_dir_path {
let mut dir = FieldsDirectory::fill_from_backup(backed_up_fields_dir_path)?;
dir.extend_from_root_excluding_fields_dir_and_plow_backup(&config.working_dir.path)?;
dir
} else {
FieldsDirectory::fill_from_root(&config.working_dir.path)?
};
if fields_dir.children.is_empty() && !fields_dir.exists_in_filesystem() {
return Err(NoFieldsInDirectory.into());
}
let linting_failures = fields_dir.lint_all_children();
if let Some((ref failed_paths, _)) = linting_failures {
fields_dir
.children
.retain(|path| !failed_paths.contains(&path.as_path().to_string()));
}
fields_dir.dedup();
if fields_dir.exists_in_filesystem() {
fields_dir.remove()?;
}
if !fields_dir.exists_in_filesystem() {
fields_dir.write_with_children()?;
}
let workspace_manifest_file = WorkspaceManifestFile::from(&fields_dir);
workspace_manifest_file.write()?;
if let Some(ref backed_up_fields_dir_path) = maybe_backed_up_fields_dir_path {
std::fs::remove_dir_all(backed_up_fields_dir_path)
.map_err(|err| FailedToRemoveBackupFieldsDirectory(err.to_string()))?;
}
let registry = crate::sync::sync(config)?;
let mut collection: HashMap<String, (PackageInLockFile, LockFile)> = HashMap::new();
for child in &fields_dir.children {
let root_field_contents = std::fs::read_to_string(&child.as_path()).map_err(|_| {
CliError::from(FailedToFindFieldAtPath {
field_path: child.as_path().to_string(),
})
})?;
let root_field_manifest =
FieldManifest::new(&root_field_contents).map_err(|_| {
CliError::from(FailedToReadFieldManifest {
field_path: child.as_path().to_string(),
})
})?;
#[allow(clippy::unwrap_used)]
let root_field_name = root_field_manifest.field_namespace_and_name().unwrap();
let root_dep_names = root_field_manifest
.field_dependency_names()
.unwrap_or_default();
if let Ok(Some(fresh_lock_file)) = resolve(
config,
&root_field_contents,
&root_field_manifest,
false,
®istry as &dyn Registry,
) {
#[allow(clippy::unwrap_used)]
let root_as_index = root_field_manifest.make_index_from_manifest().unwrap();
if collection.get(&root_field_name).is_some() {
return Err(CliError::from(DuplicateFieldInWorkspace(root_field_name)));
}
collection.insert(
root_field_name.clone(),
(
PackageInLockFile {
name: root_as_index.name,
version: root_as_index.version,
ontology_iri: root_as_index.ontology_iri,
source: None,
cksum: Some(root_as_index.cksum),
dependencies: root_dep_names,
root: true,
},
fresh_lock_file,
),
);
}
}
let lock_file_contents = collection
.into_iter()
.flat_map(|(_, (root, locked_deps))| {
let mut v = vec![];
v.push(root);
let deps = locked_deps
.locked_dependencies
.packages
.iter()
.map(|package_version| {
#[allow(clippy::unwrap_used)]
let metadata = registry
.get_package_version_metadata(package_version)
.unwrap();
PackageInLockFile {
name: package_version.package_name.clone(),
version: package_version.version.clone(),
ontology_iri: metadata.ontology_iri.clone(),
source: None,
cksum: metadata.cksum.clone(),
dependencies: metadata
.dependencies
.iter()
.cloned()
.map(|dep| dep.full_name)
.collect(),
root: false,
}
})
.collect::<Vec<_>>();
v.extend(deps);
v
})
.collect::<Vec<_>>();
if !lock_file_contents.is_empty() {
LockFile::write(Some(config.working_dir.path.clone()), &lock_file_contents)
.map_err(|err| CliError::Wip(err.to_string()))?;
}
if let Some((_, err)) = linting_failures {
return Err(err);
}
Ok(())
} else {
std::process::exit(0x00);
}
}