feat: basic ability to have many projects in one repo
This commit is contained in:
parent
e0732c2ecf
commit
5f9b5ac781
|
@ -144,6 +144,7 @@ dependencies = [
|
||||||
"dirs",
|
"dirs",
|
||||||
"fslock",
|
"fslock",
|
||||||
"futures",
|
"futures",
|
||||||
|
"glob",
|
||||||
"hex",
|
"hex",
|
||||||
"ignore",
|
"ignore",
|
||||||
"indexmap 1.9.3",
|
"indexmap 1.9.3",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::server::Server;
|
use crate::server::Server;
|
||||||
use aiken_project::{config::Config, paths};
|
use aiken_project::{config::ProjectConfig, paths};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use lsp_server::Connection;
|
use lsp_server::Connection;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
@ -23,7 +23,7 @@ pub fn start() -> Result<(), Error> {
|
||||||
let config = if paths::project_config().exists() {
|
let config = if paths::project_config().exists() {
|
||||||
tracing::info!("Aiken project detected");
|
tracing::info!("Aiken project detected");
|
||||||
|
|
||||||
Some(Config::load(&root).expect("failed to load aiken.toml"))
|
Some(ProjectConfig::load(&root).expect("failed to load aiken.toml"))
|
||||||
} else {
|
} else {
|
||||||
tracing::info!("Aiken project config not found");
|
tracing::info!("Aiken project config not found");
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ use aiken_lang::{
|
||||||
tipo::pretty::Printer,
|
tipo::pretty::Printer,
|
||||||
};
|
};
|
||||||
use aiken_project::{
|
use aiken_project::{
|
||||||
config::{self, Config},
|
config::{self, ProjectConfig},
|
||||||
error::{Error as ProjectError, GetSource},
|
error::{Error as ProjectError, GetSource},
|
||||||
module::CheckedModule,
|
module::CheckedModule,
|
||||||
};
|
};
|
||||||
|
@ -50,7 +50,7 @@ pub struct Server {
|
||||||
// Project root directory
|
// Project root directory
|
||||||
root: PathBuf,
|
root: PathBuf,
|
||||||
|
|
||||||
config: Option<config::Config>,
|
config: Option<config::ProjectConfig>,
|
||||||
|
|
||||||
/// Files that have been edited in memory
|
/// Files that have been edited in memory
|
||||||
edited: HashMap<String, String>,
|
edited: HashMap<String, String>,
|
||||||
|
@ -235,7 +235,7 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
DidChangeWatchedFiles::METHOD => {
|
DidChangeWatchedFiles::METHOD => {
|
||||||
if let Ok(config) = Config::load(&self.root) {
|
if let Ok(config) = ProjectConfig::load(&self.root) {
|
||||||
self.config = Some(config);
|
self.config = Some(config);
|
||||||
self.create_new_compiler();
|
self.create_new_compiler();
|
||||||
self.compile(connection)?;
|
self.compile(connection)?;
|
||||||
|
@ -603,7 +603,7 @@ impl Server {
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
initialize_params: InitializeParams,
|
initialize_params: InitializeParams,
|
||||||
config: Option<config::Config>,
|
config: Option<config::ProjectConfig>,
|
||||||
root: PathBuf,
|
root: PathBuf,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut server = Server {
|
let mut server = Server {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use aiken_lang::{ast::Tracing, line_numbers::LineNumbers, test_framework::PropertyTest};
|
use aiken_lang::{ast::Tracing, line_numbers::LineNumbers, test_framework::PropertyTest};
|
||||||
use aiken_project::{config::Config, error::Error as ProjectError, module::CheckedModule, Project};
|
use aiken_project::{config::ProjectConfig, error::Error as ProjectError, module::CheckedModule, Project};
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -18,7 +18,7 @@ pub struct LspProject {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LspProject {
|
impl LspProject {
|
||||||
pub fn new(config: Config, root: PathBuf, telemetry: super::telemetry::Lsp) -> Self {
|
pub fn new(config: ProjectConfig, root: PathBuf, telemetry: super::telemetry::Lsp) -> Self {
|
||||||
Self {
|
Self {
|
||||||
project: Project::new_with_config(config, root, telemetry),
|
project: Project::new_with_config(config, root, telemetry),
|
||||||
modules: HashMap::new(),
|
modules: HashMap::new(),
|
||||||
|
|
|
@ -22,6 +22,7 @@ ciborium = "0.2.2"
|
||||||
dirs = "4.0.0"
|
dirs = "4.0.0"
|
||||||
fslock = "0.2.1"
|
fslock = "0.2.1"
|
||||||
futures = "0.3.26"
|
futures = "0.3.26"
|
||||||
|
glob = "0.3.2"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ignore = "0.4.20"
|
ignore = "0.4.20"
|
||||||
indexmap = "1.9.2"
|
indexmap = "1.9.2"
|
||||||
|
|
|
@ -6,7 +6,7 @@ pub mod schema;
|
||||||
pub mod validator;
|
pub mod validator;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{self, Config, PlutusVersion},
|
config::{self, ProjectConfig, PlutusVersion},
|
||||||
module::CheckedModules,
|
module::CheckedModules,
|
||||||
};
|
};
|
||||||
use aiken_lang::gen_uplc::CodeGenerator;
|
use aiken_lang::gen_uplc::CodeGenerator;
|
||||||
|
@ -58,7 +58,7 @@ pub enum LookupResult<'a, T> {
|
||||||
|
|
||||||
impl Blueprint {
|
impl Blueprint {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: &Config,
|
config: &ProjectConfig,
|
||||||
modules: &CheckedModules,
|
modules: &CheckedModules,
|
||||||
generator: &mut CodeGenerator,
|
generator: &mut CodeGenerator,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
|
@ -179,8 +179,8 @@ impl Blueprint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Config> for Preamble {
|
impl From<&ProjectConfig> for Preamble {
|
||||||
fn from(config: &Config) -> Self {
|
fn from(config: &ProjectConfig) -> Self {
|
||||||
Preamble {
|
Preamble {
|
||||||
title: config.name.to_string(),
|
title: config.name.to_string(),
|
||||||
description: if config.description.is_empty() {
|
description: if config.description.is_empty() {
|
||||||
|
|
|
@ -7,6 +7,7 @@ use aiken_lang::{
|
||||||
parser::token::Base,
|
parser::token::Base,
|
||||||
};
|
};
|
||||||
pub use aiken_lang::{plutus_version::PlutusVersion, version::compiler_version};
|
pub use aiken_lang::{plutus_version::PlutusVersion, version::compiler_version};
|
||||||
|
use glob::glob;
|
||||||
use miette::NamedSource;
|
use miette::NamedSource;
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use serde::{
|
use serde::{
|
||||||
|
@ -14,30 +15,94 @@ use serde::{
|
||||||
ser::{self, SerializeSeq, SerializeStruct},
|
ser::{self, SerializeSeq, SerializeStruct},
|
||||||
Deserialize, Serialize,
|
Deserialize, Serialize,
|
||||||
};
|
};
|
||||||
use std::{collections::BTreeMap, fmt::Display, fs, io, path::Path};
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
fmt::Display,
|
||||||
|
fs, io,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone)]
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
pub struct Config {
|
pub struct ProjectConfig {
|
||||||
pub name: PackageName,
|
pub name: PackageName,
|
||||||
|
|
||||||
pub version: String,
|
pub version: String,
|
||||||
|
|
||||||
#[serde(
|
#[serde(
|
||||||
deserialize_with = "deserialize_version",
|
deserialize_with = "deserialize_version",
|
||||||
serialize_with = "serialize_version",
|
serialize_with = "serialize_version",
|
||||||
default = "default_version"
|
default = "default_version"
|
||||||
)]
|
)]
|
||||||
pub compiler: Version,
|
pub compiler: Version,
|
||||||
|
|
||||||
#[serde(default, deserialize_with = "validate_v3_only")]
|
#[serde(default, deserialize_with = "validate_v3_only")]
|
||||||
pub plutus: PlutusVersion,
|
pub plutus: PlutusVersion,
|
||||||
|
|
||||||
pub license: Option<String>,
|
pub license: Option<String>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub description: String,
|
pub description: String,
|
||||||
|
|
||||||
pub repository: Option<Repository>,
|
pub repository: Option<Repository>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub dependencies: Vec<Dependency>,
|
pub dependencies: Vec<Dependency>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub config: BTreeMap<String, BTreeMap<String, SimpleExpr>>,
|
pub config: BTreeMap<String, BTreeMap<String, SimpleExpr>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
struct RawWorkspaceConfig {
|
||||||
|
members: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawWorkspaceConfig {
|
||||||
|
pub fn expand_members(self, root: &Path) -> Vec<PathBuf> {
|
||||||
|
let mut result = Vec::new();
|
||||||
|
|
||||||
|
for member in self.members {
|
||||||
|
let pattern = root.join(member);
|
||||||
|
|
||||||
|
let glob_result: Vec<_> = pattern
|
||||||
|
.to_str()
|
||||||
|
.and_then(|s| glob(s).ok())
|
||||||
|
.map_or(Vec::new(), |g| g.filter_map(Result::ok).collect());
|
||||||
|
|
||||||
|
if glob_result.is_empty() {
|
||||||
|
// No matches (or glob failed), treat as literal path
|
||||||
|
result.push(pattern);
|
||||||
|
} else {
|
||||||
|
// Glob worked, add all matches
|
||||||
|
result.extend(glob_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WorkspaceConfig {
|
||||||
|
pub members: Vec<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WorkspaceConfig {
|
||||||
|
pub fn load(dir: &Path) -> Result<WorkspaceConfig, Error> {
|
||||||
|
let config_path = dir.join(paths::project_config());
|
||||||
|
let raw_config = fs::read_to_string(&config_path).map_err(|_| Error::MissingManifest {
|
||||||
|
path: dir.to_path_buf(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let raw: RawWorkspaceConfig = toml::from_str(&raw_config).map_err(|e| {
|
||||||
|
from_toml_de_error(e, config_path, raw_config, TomlLoadingContext::Workspace)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let members = raw.expand_members(dir);
|
||||||
|
|
||||||
|
Ok(WorkspaceConfig { members })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum SimpleExpr {
|
pub enum SimpleExpr {
|
||||||
Int(i64),
|
Int(i64),
|
||||||
|
@ -303,9 +368,9 @@ impl Display for Platform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl ProjectConfig {
|
||||||
pub fn default(name: &PackageName) -> Self {
|
pub fn default(name: &PackageName) -> Self {
|
||||||
Config {
|
ProjectConfig {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
version: "0.0.0".to_string(),
|
version: "0.0.0".to_string(),
|
||||||
compiler: default_version(),
|
compiler: default_version(),
|
||||||
|
@ -338,23 +403,14 @@ impl Config {
|
||||||
fs::write(aiken_toml_path, aiken_toml)
|
fs::write(aiken_toml_path, aiken_toml)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(dir: &Path) -> Result<Config, Error> {
|
pub fn load(dir: &Path) -> Result<ProjectConfig, Error> {
|
||||||
let config_path = dir.join(paths::project_config());
|
let config_path = dir.join(paths::project_config());
|
||||||
let raw_config = fs::read_to_string(&config_path).map_err(|_| Error::MissingManifest {
|
let raw_config = fs::read_to_string(&config_path).map_err(|_| Error::MissingManifest {
|
||||||
path: dir.to_path_buf(),
|
path: dir.to_path_buf(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result: Self = toml::from_str(&raw_config).map_err(|e| Error::TomlLoading {
|
let result: Self = toml::from_str(&raw_config).map_err(|e| {
|
||||||
ctx: TomlLoadingContext::Project,
|
from_toml_de_error(e, config_path, raw_config, TomlLoadingContext::Project)
|
||||||
path: config_path.clone(),
|
|
||||||
src: raw_config.clone(),
|
|
||||||
named: NamedSource::new(config_path.display().to_string(), raw_config).into(),
|
|
||||||
// this isn't actually a legit way to get the span
|
|
||||||
location: e.span().map(|range| Span {
|
|
||||||
start: range.start,
|
|
||||||
end: range.end,
|
|
||||||
}),
|
|
||||||
help: e.message().to_string(),
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
@ -388,6 +444,26 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_toml_de_error(
|
||||||
|
e: toml::de::Error,
|
||||||
|
config_path: PathBuf,
|
||||||
|
raw_config: String,
|
||||||
|
ctx: TomlLoadingContext,
|
||||||
|
) -> Error {
|
||||||
|
Error::TomlLoading {
|
||||||
|
ctx,
|
||||||
|
path: config_path.clone(),
|
||||||
|
src: raw_config.clone(),
|
||||||
|
named: NamedSource::new(config_path.display().to_string(), raw_config).into(),
|
||||||
|
// this isn't actually a legit way to get the span
|
||||||
|
location: e.span().map(|range| Span {
|
||||||
|
start: range.start,
|
||||||
|
end: range.end,
|
||||||
|
}),
|
||||||
|
help: e.message().to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod built_info {
|
mod built_info {
|
||||||
include!(concat!(env!("OUT_DIR"), "/built.rs"));
|
include!(concat!(env!("OUT_DIR"), "/built.rs"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Config, Dependency},
|
config::{ProjectConfig, Dependency},
|
||||||
error::{Error, TomlLoadingContext},
|
error::{Error, TomlLoadingContext},
|
||||||
package_name::PackageName,
|
package_name::PackageName,
|
||||||
paths,
|
paths,
|
||||||
|
@ -133,7 +133,7 @@ impl From<&Manifest> for LocalPackages {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn download<T>(event_listener: &T, root_path: &Path, config: &Config) -> Result<Manifest, Error>
|
pub fn download<T>(event_listener: &T, root_path: &Path, config: &ProjectConfig) -> Result<Manifest, Error>
|
||||||
where
|
where
|
||||||
T: EventListener,
|
T: EventListener,
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Config, Dependency, Platform},
|
config::{ProjectConfig, Dependency, Platform},
|
||||||
error::{Error, TomlLoadingContext},
|
error::{Error, TomlLoadingContext},
|
||||||
package_name::PackageName,
|
package_name::PackageName,
|
||||||
paths,
|
paths,
|
||||||
|
@ -27,7 +27,7 @@ pub struct Manifest {
|
||||||
impl Manifest {
|
impl Manifest {
|
||||||
pub fn load<T>(
|
pub fn load<T>(
|
||||||
event_listener: &T,
|
event_listener: &T,
|
||||||
config: &Config,
|
config: &ProjectConfig,
|
||||||
root_path: &Path,
|
root_path: &Path,
|
||||||
) -> Result<(Self, bool), Error>
|
) -> Result<(Self, bool), Error>
|
||||||
where
|
where
|
||||||
|
@ -121,7 +121,7 @@ pub struct Package {
|
||||||
pub source: Platform,
|
pub source: Platform,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_versions<T>(config: &Config, event_listener: &T) -> Result<Manifest, Error>
|
fn resolve_versions<T>(config: &ProjectConfig, event_listener: &T) -> Result<Manifest, Error>
|
||||||
where
|
where
|
||||||
T: EventListener,
|
T: EventListener,
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Config, Repository},
|
config::{ProjectConfig, Repository},
|
||||||
module::CheckedModule,
|
module::CheckedModule,
|
||||||
};
|
};
|
||||||
use aiken_lang::{
|
use aiken_lang::{
|
||||||
|
@ -104,7 +104,7 @@ impl DocLink {
|
||||||
/// The documentation is built using template files located at the root of this crate.
|
/// The documentation is built using template files located at the root of this crate.
|
||||||
/// With the documentation, we also build a client-side search index to ease navigation
|
/// With the documentation, we also build a client-side search index to ease navigation
|
||||||
/// across multiple modules.
|
/// across multiple modules.
|
||||||
pub fn generate_all(root: &Path, config: &Config, modules: Vec<&CheckedModule>) -> Vec<DocFile> {
|
pub fn generate_all(root: &Path, config: &ProjectConfig, modules: Vec<&CheckedModule>) -> Vec<DocFile> {
|
||||||
let timestamp = new_timestamp();
|
let timestamp = new_timestamp();
|
||||||
let modules_links = generate_modules_links(&modules);
|
let modules_links = generate_modules_links(&modules);
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ pub fn generate_all(root: &Path, config: &Config, modules: Vec<&CheckedModule>)
|
||||||
|
|
||||||
fn generate_module(
|
fn generate_module(
|
||||||
root: &Path,
|
root: &Path,
|
||||||
config: &Config,
|
config: &ProjectConfig,
|
||||||
module: &CheckedModule,
|
module: &CheckedModule,
|
||||||
modules: &[DocLink],
|
modules: &[DocLink],
|
||||||
source: &DocLink,
|
source: &DocLink,
|
||||||
|
@ -376,7 +376,7 @@ fn generate_static_assets(search_indexes: Vec<SearchIndex>) -> Vec<DocFile> {
|
||||||
|
|
||||||
fn generate_readme(
|
fn generate_readme(
|
||||||
root: &Path,
|
root: &Path,
|
||||||
config: &Config,
|
config: &ProjectConfig,
|
||||||
modules: &[DocLink],
|
modules: &[DocLink],
|
||||||
source: &DocLink,
|
source: &DocLink,
|
||||||
timestamp: &Duration,
|
timestamp: &Duration,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Config, Platform},
|
config::{ProjectConfig, Platform},
|
||||||
CheckedModule,
|
CheckedModule,
|
||||||
};
|
};
|
||||||
use aiken_lang::{ast::Span, line_numbers::LineNumbers};
|
use aiken_lang::{ast::Span, line_numbers::LineNumbers};
|
||||||
|
@ -12,7 +12,7 @@ pub struct SourceLinker {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceLinker {
|
impl SourceLinker {
|
||||||
pub fn new(root: &Path, config: &Config, module: &CheckedModule) -> Self {
|
pub fn new(root: &Path, config: &ProjectConfig, module: &CheckedModule) -> Self {
|
||||||
let utf8_path = <&Utf8Path>::try_from(
|
let utf8_path = <&Utf8Path>::try_from(
|
||||||
module
|
module
|
||||||
.input_path
|
.input_path
|
||||||
|
|
|
@ -26,6 +26,7 @@ pub enum TomlLoadingContext {
|
||||||
Project,
|
Project,
|
||||||
Manifest,
|
Manifest,
|
||||||
Package,
|
Package,
|
||||||
|
Workspace,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for TomlLoadingContext {
|
impl fmt::Display for TomlLoadingContext {
|
||||||
|
@ -34,6 +35,7 @@ impl fmt::Display for TomlLoadingContext {
|
||||||
TomlLoadingContext::Project => write!(f, "project"),
|
TomlLoadingContext::Project => write!(f, "project"),
|
||||||
TomlLoadingContext::Manifest => write!(f, "manifest"),
|
TomlLoadingContext::Manifest => write!(f, "manifest"),
|
||||||
TomlLoadingContext::Package => write!(f, "package"),
|
TomlLoadingContext::Package => write!(f, "package"),
|
||||||
|
TomlLoadingContext::Workspace => write!(f, "workspace"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ use crate::{
|
||||||
schema::{Annotated, Schema},
|
schema::{Annotated, Schema},
|
||||||
Blueprint,
|
Blueprint,
|
||||||
},
|
},
|
||||||
config::Config,
|
config::ProjectConfig,
|
||||||
error::{Error, Warning},
|
error::{Error, Warning},
|
||||||
module::{CheckedModule, CheckedModules, ParsedModule, ParsedModules},
|
module::{CheckedModule, CheckedModules, ParsedModule, ParsedModules},
|
||||||
telemetry::Event,
|
telemetry::Event,
|
||||||
|
@ -87,7 +87,7 @@ pub struct Project<T>
|
||||||
where
|
where
|
||||||
T: EventListener,
|
T: EventListener,
|
||||||
{
|
{
|
||||||
config: Config,
|
config: ProjectConfig,
|
||||||
defined_modules: HashMap<String, PathBuf>,
|
defined_modules: HashMap<String, PathBuf>,
|
||||||
checked_modules: CheckedModules,
|
checked_modules: CheckedModules,
|
||||||
id_gen: IdGenerator,
|
id_gen: IdGenerator,
|
||||||
|
@ -108,7 +108,7 @@ where
|
||||||
T: EventListener,
|
T: EventListener,
|
||||||
{
|
{
|
||||||
pub fn new(root: PathBuf, event_listener: T) -> Result<Project<T>, Error> {
|
pub fn new(root: PathBuf, event_listener: T) -> Result<Project<T>, Error> {
|
||||||
let config = Config::load(&root)?;
|
let config = ProjectConfig::load(&root)?;
|
||||||
|
|
||||||
let demanded_compiler_version = format!("v{}", config.compiler);
|
let demanded_compiler_version = format!("v{}", config.compiler);
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ where
|
||||||
Ok(project)
|
Ok(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_config(config: Config, root: PathBuf, event_listener: T) -> Project<T> {
|
pub fn new_with_config(config: ProjectConfig, root: PathBuf, event_listener: T) -> Project<T> {
|
||||||
let id_gen = IdGenerator::new();
|
let id_gen = IdGenerator::new();
|
||||||
|
|
||||||
let mut module_types = HashMap::new();
|
let mut module_types = HashMap::new();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{telemetry::EventTarget, Project};
|
use crate::{config::WorkspaceConfig, telemetry::EventTarget, Project};
|
||||||
use miette::{Diagnostic, IntoDiagnostic};
|
use miette::{Diagnostic, IntoDiagnostic};
|
||||||
use notify::{Event, RecursiveMode, Watcher};
|
use notify::{Event, RecursiveMode, Watcher};
|
||||||
use owo_colors::{OwoColorize, Stream::Stderr};
|
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||||
|
@ -108,6 +108,38 @@ where
|
||||||
current_dir
|
current_dir
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut warnings = Vec::new();
|
||||||
|
let mut errs: Vec<crate::error::Error> = Vec::new();
|
||||||
|
let mut check_count = None;
|
||||||
|
|
||||||
|
if let Ok(workspace) = WorkspaceConfig::load(&project_path) {
|
||||||
|
let res_projects = workspace
|
||||||
|
.members
|
||||||
|
.into_iter()
|
||||||
|
.map(|member| Project::new(member, EventTarget::default()))
|
||||||
|
.collect::<Result<Vec<Project<_>>, crate::error::Error>>();
|
||||||
|
|
||||||
|
let projects = match res_projects {
|
||||||
|
Ok(p) => Ok(p),
|
||||||
|
Err(e) => {
|
||||||
|
e.report();
|
||||||
|
Err(ExitFailure::into_report())
|
||||||
|
}
|
||||||
|
}?;
|
||||||
|
|
||||||
|
for mut project in projects {
|
||||||
|
let build_result = action(&mut project);
|
||||||
|
|
||||||
|
warnings.extend(project.warnings());
|
||||||
|
|
||||||
|
let sum = check_count.unwrap_or(0) + project.checks_count.unwrap_or(0);
|
||||||
|
check_count = if sum > 0 { Some(sum) } else { None };
|
||||||
|
|
||||||
|
if let Err(e) = build_result {
|
||||||
|
errs.extend(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let mut project = match Project::new(project_path, EventTarget::default()) {
|
let mut project = match Project::new(project_path, EventTarget::default()) {
|
||||||
Ok(p) => Ok(p),
|
Ok(p) => Ok(p),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -118,7 +150,15 @@ where
|
||||||
|
|
||||||
let build_result = action(&mut project);
|
let build_result = action(&mut project);
|
||||||
|
|
||||||
let warnings = project.warnings();
|
warnings.extend(project.warnings());
|
||||||
|
|
||||||
|
let sum = check_count.unwrap_or(0) + project.checks_count.unwrap_or(0);
|
||||||
|
check_count = if sum > 0 { Some(sum) } else { None };
|
||||||
|
|
||||||
|
if let Err(e) = build_result {
|
||||||
|
errs.extend(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let warning_count = warnings.len();
|
let warning_count = warnings.len();
|
||||||
|
|
||||||
|
@ -130,7 +170,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(errs) = build_result {
|
if !errs.is_empty() {
|
||||||
for err in &errs {
|
for err in &errs {
|
||||||
err.report()
|
err.report()
|
||||||
}
|
}
|
||||||
|
@ -138,7 +178,7 @@ where
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"{}",
|
"{}",
|
||||||
Summary {
|
Summary {
|
||||||
check_count: project.checks_count,
|
check_count,
|
||||||
warning_count,
|
warning_count,
|
||||||
error_count: errs.len(),
|
error_count: errs.len(),
|
||||||
}
|
}
|
||||||
|
@ -147,17 +187,15 @@ where
|
||||||
return Err(ExitFailure::into_report());
|
return Err(ExitFailure::into_report());
|
||||||
}
|
}
|
||||||
|
|
||||||
if project.checks_count.unwrap_or_default() + warning_count > 0 {
|
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"{}",
|
"{}",
|
||||||
Summary {
|
Summary {
|
||||||
check_count: project.checks_count,
|
check_count,
|
||||||
error_count: 0,
|
error_count: 0,
|
||||||
warning_count
|
warning_count
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if warning_count > 0 && deny {
|
if warning_count > 0 && deny {
|
||||||
Err(ExitFailure::into_report())
|
Err(ExitFailure::into_report())
|
||||||
|
@ -172,6 +210,7 @@ where
|
||||||
/// // Note: doctest disabled, because aiken_project doesn't have an implementation of EventListener I can use
|
/// // Note: doctest disabled, because aiken_project doesn't have an implementation of EventListener I can use
|
||||||
/// use aiken_project::watch::{watch_project, default_filter};
|
/// use aiken_project::watch::{watch_project, default_filter};
|
||||||
/// use aiken_project::{Project};
|
/// use aiken_project::{Project};
|
||||||
|
///
|
||||||
/// watch_project(None, default_filter, 500, |project| {
|
/// watch_project(None, default_filter, 500, |project| {
|
||||||
/// println!("Project changed!");
|
/// println!("Project changed!");
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use aiken_project::{
|
use aiken_project::{
|
||||||
config::{self, Config},
|
config::{self, ProjectConfig},
|
||||||
package_name::{self, PackageName},
|
package_name::{self, PackageName},
|
||||||
};
|
};
|
||||||
use indoc::{formatdoc, indoc};
|
use indoc::{formatdoc, indoc};
|
||||||
|
@ -46,7 +46,7 @@ fn create_project(args: Args, package_name: &PackageName) -> miette::Result<()>
|
||||||
|
|
||||||
readme(&root, &package_name.repo)?;
|
readme(&root, &package_name.repo)?;
|
||||||
|
|
||||||
Config::default(package_name)
|
ProjectConfig::default(package_name)
|
||||||
.save(&root)
|
.save(&root)
|
||||||
.into_diagnostic()?;
|
.into_diagnostic()?;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use aiken_project::{
|
use aiken_project::{
|
||||||
config::{Config, Dependency, Platform},
|
config::{ProjectConfig, Dependency, Platform},
|
||||||
error::Warning,
|
error::Warning,
|
||||||
package_name::PackageName,
|
package_name::PackageName,
|
||||||
pretty,
|
pretty,
|
||||||
|
@ -35,7 +35,7 @@ pub fn exec(args: Args) -> miette::Result<()> {
|
||||||
source: Platform::Github,
|
source: Platform::Github,
|
||||||
};
|
};
|
||||||
|
|
||||||
let config = match Config::load(&root) {
|
let config = match ProjectConfig::load(&root) {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
e.report();
|
e.report();
|
||||||
|
|
Loading…
Reference in New Issue