Collection: more work, pkg_builders
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
2e75c8a8f9
commit
c80cabe74e
112
bok-macro/src/collection.rs
Normal file
112
bok-macro/src/collection.rs
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2024 Luca Fulchir <luca.fulchir@runesauth.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 with LLVM exception (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License and of the exception at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://spdx.org/licenses/LLVM-exception.html
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use ::proc_macro::TokenStream;
|
||||
use ::quote::quote;
|
||||
use ::syn::parse_macro_input;
|
||||
|
||||
pub(crate) fn collection(
|
||||
attrs: TokenStream,
|
||||
input: TokenStream,
|
||||
) -> TokenStream {
|
||||
let ast = parse_macro_input!(input as ::syn::ItemStruct);
|
||||
if ast.ident.to_string() != "Collection" {
|
||||
use ::syn::spanned::Spanned;
|
||||
return ::syn::Error::new(
|
||||
ast.span(),
|
||||
"#[::bok_macro::collection(..)] should only be called on `struct \
|
||||
Collection{}`",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
use crate::PathList;
|
||||
|
||||
let deps_list = parse_macro_input!(attrs as PathList);
|
||||
let mut all_deps_builder = deps_list.0.iter();
|
||||
let name = all_deps_builder.next().expect(
|
||||
"`#[::bok_macro::collection(..)]` must have at least two arguments, \
|
||||
the first is the repo path",
|
||||
);
|
||||
|
||||
let mut asdf = Vec::new();
|
||||
for d in deps_list.0.iter() {
|
||||
let d_str = d
|
||||
.segments
|
||||
.iter()
|
||||
.fold(String::new(), |a, b| a + "_" + &b.ident.to_string());
|
||||
asdf.push(::quote::format_ident!("{}", d_str));
|
||||
}
|
||||
|
||||
quote! {
|
||||
use ::bok_macro::collection_dep;
|
||||
#(
|
||||
const #asdf : u32 = 42;
|
||||
)
|
||||
*
|
||||
#(#[::bok_macro::collection_dep(#all_deps_builder)])
|
||||
*
|
||||
pub struct Collection {
|
||||
repo: ::std::sync::Arc<#name>,
|
||||
pkgs: ::std::sync::RwLock<
|
||||
::std::vec::Vec<
|
||||
::std::sync::Arc<
|
||||
dyn ::bok::PkgBuilder>>>,
|
||||
}
|
||||
impl ::bok::Collection for Collection {}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
pub(crate) fn collection_dep(
|
||||
attrs: TokenStream,
|
||||
input: TokenStream,
|
||||
__source_path: TokenStream,
|
||||
) -> TokenStream {
|
||||
let local = parse_macro_input!(input as ::syn::ItemStruct);
|
||||
let dep = parse_macro_input!(attrs as ::syn::ItemTrait);
|
||||
|
||||
let local_ident = &local.ident;
|
||||
let dep_ident = parse_macro_input!(__source_path as ::syn::Path);
|
||||
|
||||
let mut all_deps = Vec::with_capacity(dep.items.len());
|
||||
for fn_it in dep.items.iter() {
|
||||
let ::syn::TraitItem::Fn(func) = fn_it else {
|
||||
continue;
|
||||
};
|
||||
let sig = &func.sig;
|
||||
let pkgbuilder_name = &sig.ident;
|
||||
|
||||
let builder: ::syn::ImplItemFn = ::syn::parse_quote! {
|
||||
#sig {
|
||||
::std::boxed::Box::new(
|
||||
self.repo.#pkgbuilder_name()
|
||||
)
|
||||
}
|
||||
};
|
||||
all_deps.push(builder);
|
||||
}
|
||||
|
||||
quote! {
|
||||
#local
|
||||
impl #dep_ident for #local_ident {
|
||||
#(#all_deps)
|
||||
*
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
#![feature(proc_macro_span)]
|
||||
use ::proc_macro::TokenStream;
|
||||
|
||||
mod collection;
|
||||
mod pkgs;
|
||||
mod repos;
|
||||
|
||||
@ -80,7 +81,7 @@ pub fn repo_impl(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||
crate::repos::repo_impl(attrs, input)
|
||||
}
|
||||
|
||||
/// Internal. **Do not use unless you know what you are doing**
|
||||
/// **Internal. Do not use unless you know what you are doing**
|
||||
/// Create the methods that will return the builders and packages
|
||||
/// Usage:
|
||||
/// ```
|
||||
@ -96,7 +97,7 @@ pub fn repo_impl_methods(
|
||||
crate::repos::repo_impl_methods(attrs, input, __source_path)
|
||||
}
|
||||
|
||||
/// Internal. **Do not use unless you know what you are doing**
|
||||
/// **Internal. Do not use unless you know what you are doing**
|
||||
/// given a Repository and a trait "BokDeps...",
|
||||
/// implement all the fn returning the dependencies needed by the package
|
||||
///
|
||||
@ -114,6 +115,23 @@ pub fn repo_impl_pkg_deps(
|
||||
crate::repos::repo_impl_pkg_deps(attrs, input)
|
||||
}
|
||||
|
||||
/// **Internal**
|
||||
///
|
||||
/// add implementation of a collection
|
||||
#[proc_macro_attribute]
|
||||
pub fn collection(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||
crate::collection::collection(attrs, input)
|
||||
}
|
||||
|
||||
/// **Internal**
|
||||
///
|
||||
/// add implementation of a `BokBuilderDeps` trait
|
||||
#[::macro_magic::import_tokens_attr]
|
||||
#[proc_macro_attribute]
|
||||
pub fn collection_dep(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||
crate::collection::collection_dep(attrs, input, __source_path)
|
||||
}
|
||||
|
||||
//
|
||||
// ####### Package stuff ##########
|
||||
//
|
||||
@ -208,7 +226,7 @@ pub fn package_impl(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||
crate::pkgs::package_impl(attrs, input)
|
||||
}
|
||||
|
||||
/// Internal, **don't use unless you know what you are doing.**
|
||||
/// ** Internal, don't use unless you know what you are doing.**
|
||||
/// Use as #[::bok::package_impl_base(::my::Package)]
|
||||
/// implements common ::bok::Pkg methods and takes the package methods
|
||||
/// not implemented by the user from the base package
|
||||
@ -224,7 +242,7 @@ pub fn package_impl(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||
/// e.g.:
|
||||
/// ```
|
||||
/// #[::bok::package_impl_base(MyPackage)]
|
||||
/// #[::macro_magic::export_tokens(bok_pkg_mypackage)]
|
||||
/// #[::macro_magic::export_tokens(_bok_pkg_mypackage)]
|
||||
/// impl ::bok::Pkg for MyPackage {
|
||||
/// fn build(&self) -> Result<(),()> {
|
||||
/// ...
|
||||
@ -240,6 +258,38 @@ pub fn package_impl_base(
|
||||
crate::pkgs::package_impl_base(attrs, input)
|
||||
}
|
||||
|
||||
/// ** Internal, don't use unless you know what you are doing.**
|
||||
/// Use as #[::bok::package_impl_builder(::my::Package)]
|
||||
/// implements common ::bok::PkgBuilder methods and takes
|
||||
/// the package methods not implemented by the user from the base package
|
||||
///
|
||||
/// does not export symbols.
|
||||
///
|
||||
/// should be called with the same path as the package that implements
|
||||
/// ::bok::Pkg
|
||||
///
|
||||
/// will rewrite itself with the exported impl path of the base package
|
||||
/// so that macro_magic can import the base impl
|
||||
///
|
||||
/// e.g.:
|
||||
/// ```
|
||||
/// #[::bok::package_impl_builder(MyPackage)]
|
||||
/// #[::macro_magic::export_tokens(_bok_pkgbuilder_mypackage)]
|
||||
/// impl ::bok::PkgBuilder for MyPackage {
|
||||
/// fn set_dependencies(&self, ...) -> Result<(),()> {
|
||||
/// ...
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[::macro_magic::import_tokens_attr]
|
||||
#[proc_macro_attribute]
|
||||
pub fn package_impl_builder(
|
||||
attrs: TokenStream,
|
||||
input: TokenStream,
|
||||
) -> TokenStream {
|
||||
crate::pkgs::package_impl_builder(attrs, input, __source_path)
|
||||
}
|
||||
|
||||
/// Unless you know what you are doing, use `#[::bok::package(MyBasePackage)]`
|
||||
/// instead needs a `.base` field
|
||||
///
|
||||
|
@ -268,6 +268,17 @@ pub(crate) fn deps_build(
|
||||
quote::format_ident!("{}", ident.to_string().to_case(Case::Snake))
|
||||
})
|
||||
.collect::<Vec<::syn::Ident>>();
|
||||
let deps_builders = packages
|
||||
.0
|
||||
.iter()
|
||||
.map(|x| {
|
||||
let ident = x.segments.last().unwrap().ident.clone();
|
||||
quote::format_ident!(
|
||||
"{}_builder",
|
||||
ident.to_string().to_case(Case::Snake)
|
||||
)
|
||||
})
|
||||
.collect::<Vec<::syn::Ident>>();
|
||||
|
||||
quote! {
|
||||
#(#local_attrs)
|
||||
@ -283,7 +294,7 @@ pub(crate) fn deps_build(
|
||||
}
|
||||
#[::macro_magic::export_tokens(#pkg_builder_trait)]
|
||||
pub trait #pkg_builder_trait {
|
||||
#(fn #deps(&self) -> ::std::boxed::Box<dyn ::bok::PkgBuilder>;)
|
||||
#(fn #deps_builders(&self) -> ::std::boxed::Box<dyn ::bok::PkgBuilder>;)
|
||||
*
|
||||
}
|
||||
}
|
||||
@ -303,41 +314,47 @@ pub(crate) fn package_impl(
|
||||
) -> TokenStream {
|
||||
let mut ast = parse_macro_input!(input as ::syn::ItemImpl);
|
||||
|
||||
if let Some((_, trait_name, _)) = &ast.trait_ {
|
||||
let s = &trait_name.segments;
|
||||
if s.len() != 2
|
||||
|| s[0].ident.to_string() != "bok"
|
||||
|| s[1].ident.to_string() != "Pkg"
|
||||
{
|
||||
//
|
||||
// only add the generic parameter and nothing else
|
||||
//
|
||||
let ::syn::Type::Path(t_id) = &ast.self_ty.as_ref() else {
|
||||
return ::syn::Error::new(
|
||||
ast.span(),
|
||||
"package_impl: Type is not Path",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
};
|
||||
let trait_deps = ::quote::format_ident!(
|
||||
"BokDeps{}",
|
||||
t_id.path.segments.last().unwrap().ident
|
||||
);
|
||||
let g: ::syn::ItemImpl = ::syn::parse_quote! {
|
||||
impl<R> trait_name for #t_id<R> where R: ::bok::Repository + #trait_deps {}
|
||||
};
|
||||
ast.generics = g.generics;
|
||||
ast.self_ty = g.self_ty;
|
||||
// TODO: if the trait is `::std::default::Default`
|
||||
// then add the `_bok_base` and `_bok_repo` defaults automatically
|
||||
return quote! {
|
||||
#ast
|
||||
}
|
||||
let Some((_, trait_name, _)) = &ast.trait_ else {
|
||||
return ::syn::Error::new(
|
||||
ast.span(),
|
||||
"package_impl: trait name not foun",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
};
|
||||
let s = &trait_name.segments;
|
||||
if s.len() != 2
|
||||
|| s[0].ident.to_string() != "bok"
|
||||
|| (s[1].ident.to_string() != "Pkg"
|
||||
&& s[1].ident.to_string() != "PkgBuilder")
|
||||
{
|
||||
//
|
||||
// only add the generic parameter and nothing else
|
||||
//
|
||||
let ::syn::Type::Path(t_id) = &ast.self_ty.as_ref() else {
|
||||
return ::syn::Error::new(
|
||||
ast.span(),
|
||||
"package_impl: Type is not Path",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
};
|
||||
let trait_deps = ::quote::format_ident!(
|
||||
"BokDeps{}",
|
||||
t_id.path.segments.last().unwrap().ident
|
||||
);
|
||||
let g: ::syn::ItemImpl = ::syn::parse_quote! {
|
||||
impl<R> trait_name for #t_id<R> where R: ::bok::Repository + #trait_deps {}
|
||||
};
|
||||
ast.generics = g.generics;
|
||||
ast.self_ty = g.self_ty;
|
||||
// TODO: if the trait is `::std::default::Default`
|
||||
// then add the `_bok_base` and `_bok_repo` defaults automatically
|
||||
return quote! {
|
||||
#ast
|
||||
}
|
||||
.into();
|
||||
}
|
||||
let ast = ast; // remove mut
|
||||
|
||||
let name_pkg = match &*ast.self_ty {
|
||||
::syn::Type::Path(tp) => match tp.path.get_ident() {
|
||||
@ -360,6 +377,16 @@ pub(crate) fn package_impl(
|
||||
.into()
|
||||
}
|
||||
};
|
||||
|
||||
if trait_name.segments[1].ident.to_string() == "PkgBuilder" {
|
||||
return quote! {
|
||||
use ::bok_macro::package_impl_builder;
|
||||
#[::bok_macro::package_impl_builder(#name_pkg)]
|
||||
#ast
|
||||
}
|
||||
.into();
|
||||
}
|
||||
|
||||
let full_path_name = proc_macro2::Ident::new(
|
||||
&("_bok_pkg_".to_owned() + &name_pkg.to_string()),
|
||||
proc_macro2::Span::call_site(),
|
||||
@ -518,6 +545,267 @@ pub(crate) fn package_impl_base(
|
||||
.into();
|
||||
}
|
||||
|
||||
// implement PkgBuilder
|
||||
pub(crate) fn package_impl_builder(
|
||||
attrs: TokenStream,
|
||||
input: TokenStream,
|
||||
__source_path: TokenStream,
|
||||
) -> TokenStream {
|
||||
let local = parse_macro_input!(input as ::syn::ItemImpl);
|
||||
let pkg = parse_macro_input!(attrs as ::syn::ItemStruct);
|
||||
|
||||
let local_path = &local.trait_.as_ref().unwrap().1;
|
||||
if local_path.segments.len() != 2
|
||||
|| local_path.segments[0].ident.to_string() != "bok"
|
||||
|| local_path.segments[1].ident.to_string() != "PkgBuilder"
|
||||
{
|
||||
return ::syn::Error::new(
|
||||
local.span(),
|
||||
"package_impl_builder: can only be called on `impl \
|
||||
::bok::PkgBuilder`",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
let local_funcs = local.items.iter().filter(|&it| match it {
|
||||
::syn::ImplItem::Fn(_) => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
let ::syn::Fields::Named(elements) = pkg.fields else {
|
||||
return ::syn::Error::new(
|
||||
local.span(),
|
||||
"package_impl_builder: only named fields supported in base pkg",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
};
|
||||
|
||||
let pkg_name = pkg.ident;
|
||||
let name_builder = ::quote::format_ident!("{}Builder", pkg_name);
|
||||
let trait_deps = ::quote::format_ident!("BokDeps{}", pkg_name);
|
||||
let non_opt_fields = elements.named.iter().filter_map(|field| {
|
||||
if let Some(id) = field.ident.clone() {
|
||||
if id.to_string() == "version"
|
||||
|| id.to_string() == "_bok_base"
|
||||
|| id.to_string() == "_bok_repo"
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
match &field.ty {
|
||||
syn::Type::Path(pth) => {
|
||||
let first_path = pth.path.segments.first().unwrap();
|
||||
if first_path.ident == "Option" {
|
||||
None
|
||||
} else {
|
||||
let id = &field.ident;
|
||||
Some(quote! {#id})
|
||||
}
|
||||
}
|
||||
t => Some(quote! {#t}),
|
||||
}
|
||||
});
|
||||
let opt_fields = elements.named.iter().filter_map(|field| {
|
||||
if let Some(id) = field.ident.clone() {
|
||||
if id.to_string() == "version"
|
||||
|| id.to_string() == "_bok_base"
|
||||
|| id.to_string() == "_bok_repo"
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
match &field.ty {
|
||||
syn::Type::Path(pth) => {
|
||||
let first_path = pth.path.segments.first().unwrap();
|
||||
if first_path.ident == "Option" {
|
||||
let id = &field.ident;
|
||||
Some(quote! {#id})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
let non_opt_types = elements.named.iter().filter_map(|field| {
|
||||
if let Some(id) = field.ident.clone() {
|
||||
if id.to_string() == "version"
|
||||
|| id.to_string() == "_bok_base"
|
||||
|| id.to_string() == "_bok_repo"
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
match &field.ty {
|
||||
syn::Type::Path(pth) => {
|
||||
let first_path = pth.path.segments.first().unwrap();
|
||||
if first_path.ident == "Option" {
|
||||
None
|
||||
} else {
|
||||
let t = &field.ty;
|
||||
Some(quote! {#t})
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
let opt_types = elements.named.iter().filter_map(|field| {
|
||||
if let Some(id) = field.ident.clone() {
|
||||
if id.to_string() == "version"
|
||||
|| id.to_string() == "_bok_base"
|
||||
|| id.to_string() == "_bok_repo"
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if let ::syn::Type::Path(pth) = &field.ty {
|
||||
let first_path = pth.path.segments.first().unwrap();
|
||||
if first_path.ident == "Option" {
|
||||
if let syn::PathArguments::AngleBracketed(
|
||||
syn::AngleBracketedGenericArguments { args, .. },
|
||||
) = &first_path.arguments
|
||||
{
|
||||
if let Some(syn::GenericArgument::Type(syn::Type::Path(
|
||||
p,
|
||||
))) = args.first()
|
||||
{
|
||||
let id = &p.path.segments.first().unwrap().ident;
|
||||
return Some(quote! {#id});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
|
||||
let non_opt_types2 = non_opt_types.clone();
|
||||
let non_opt_fields2 = non_opt_fields.clone();
|
||||
let non_opt_fields3 = non_opt_fields.clone();
|
||||
let non_opt_fields4 = non_opt_fields.clone();
|
||||
let non_opt_fields5 = non_opt_fields.clone();
|
||||
let non_opt_fields6 = non_opt_fields.clone();
|
||||
let opt_fields2 = opt_fields.clone();
|
||||
let opt_fields3 = opt_fields.clone();
|
||||
let opt_fields4 = opt_fields.clone();
|
||||
let opt_types2 = opt_types.clone();
|
||||
let full_export_path_name = proc_macro2::Ident::new(
|
||||
&("_bok_pkgbuilder_".to_owned() + &pkg_name.to_string()),
|
||||
proc_macro2::Span::call_site(),
|
||||
);
|
||||
|
||||
quote! {
|
||||
#[derive(::std::default::Default, ::std::fmt::Debug)]
|
||||
pub struct #name_builder<R>
|
||||
where
|
||||
R: ::bok::Repository + 'static + #trait_deps,
|
||||
{
|
||||
_bok_repo: ::std::marker::PhantomData<R>,
|
||||
#(#non_opt_fields: ::std::option::Option<#non_opt_types>,)*
|
||||
#(#opt_fields: ::std::option::Option<#opt_types>,)*
|
||||
}
|
||||
//#[::macro_magic::export_tokens(#full_export_path_name)]
|
||||
impl<R> ::bok::PkgBuilder for #name_builder<R>
|
||||
where
|
||||
R: ::bok::Repository + 'static + #trait_deps,
|
||||
{
|
||||
fn name(&self) -> ::bok::PkgName {
|
||||
use ::bok::Pkg;
|
||||
#pkg_name::<R>::default().name()
|
||||
}
|
||||
fn path(&self) -> ::bok::Path<::bok::PkgName> {
|
||||
use ::bok::Pkg;
|
||||
#pkg_name::<R>::default().path()
|
||||
}
|
||||
fn version(&self) -> ::bok::Version {
|
||||
use ::bok::Pkg;
|
||||
#pkg_name::<R>::default().version()
|
||||
}
|
||||
fn as_any(&self) -> &dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
fn default_unused(&mut self) -> &mut dyn ::bok::PkgBuilder {
|
||||
let def = #pkg_name::<R>::default();
|
||||
#(if self.#non_opt_fields5.is_none() {
|
||||
self.#non_opt_fields5 = Some(def.#non_opt_fields5);
|
||||
})*
|
||||
|
||||
self
|
||||
}
|
||||
fn build(&mut self) ->
|
||||
Result<
|
||||
Box<dyn ::bok::Pkg>,
|
||||
::std::boxed::Box<dyn ::std::error::Error>
|
||||
> {
|
||||
#(if self.#non_opt_fields2.is_none() {
|
||||
return ::std::result::Result::Err("unset field".into());
|
||||
})*
|
||||
Ok(
|
||||
Box::new(#pkg_name::<R> {
|
||||
_bok_base: ::std::marker::PhantomData::default(),
|
||||
_bok_repo: ::std::marker::PhantomData::default(),
|
||||
version: #pkg_name::<R>::default().version,
|
||||
#(#non_opt_fields3 : self.#non_opt_fields3.clone().unwrap(),)*
|
||||
#(#opt_fields2 : self.#opt_fields2.clone(),)*
|
||||
})
|
||||
)
|
||||
}
|
||||
#(#local_funcs)
|
||||
*
|
||||
}
|
||||
impl<R> #name_builder<R>
|
||||
where
|
||||
R: ::bok::Repository +'static + #trait_deps,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
_bok_repo: ::std::marker::PhantomData::default(),
|
||||
#(#non_opt_fields6: None,)*
|
||||
#(#opt_fields4: None,)*
|
||||
}
|
||||
}
|
||||
pub fn as_any(&self) -> &dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
pub fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
pub fn as_builder(&self) -> &dyn ::bok::PkgBuilder {
|
||||
self
|
||||
}
|
||||
pub fn as_builder_mut(&mut self) -> &mut dyn ::bok::PkgBuilder {
|
||||
self
|
||||
}
|
||||
#(pub fn #non_opt_fields4 (&mut self, val : #non_opt_types2) -> &mut Self {
|
||||
if self.#non_opt_fields4 != None &&
|
||||
self.#non_opt_fields4 != Some(val) {
|
||||
panic!("Package \"{}\": mandatory attribute set multiple times: \"{}\"",
|
||||
::std::stringify!(#pkg_name),
|
||||
::std::stringify!(#non_opt_fields4));
|
||||
}
|
||||
self.#non_opt_fields4 = Some(val);
|
||||
self
|
||||
})
|
||||
*
|
||||
#(pub fn #opt_fields3 (&mut self, val : #opt_types2) -> &mut Self {
|
||||
if self.#opt_fields3 != None &&
|
||||
self.#opt_fields3 != Some(val) {
|
||||
panic!("Package \"{}\": optional attribute set multiple times: \"{}\"",
|
||||
::std::stringify!(#pkg_name),
|
||||
::std::stringify!(#opt_fields3));
|
||||
}
|
||||
self.#opt_fields3 = Some(val);
|
||||
self
|
||||
})
|
||||
*
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
// implements ::bok::Pkg:
|
||||
// * add base methods
|
||||
// * copy the non-implemented methods from the base
|
||||
@ -586,7 +874,7 @@ pub(crate) fn package_impl_base_add(
|
||||
|
||||
for mut impl_item in ast.items.iter_mut() {
|
||||
if let ::syn::ImplItem::Fn(ref mut fn_impl) = &mut impl_item {
|
||||
if ["prepare", "configure", "build", "check", "install"]
|
||||
if ["prepare", "configure", "build", "test", "install"]
|
||||
.iter()
|
||||
.find(|&f| *f == fn_impl.sig.ident.to_string().as_str())
|
||||
.is_none()
|
||||
@ -687,8 +975,7 @@ pub(crate) fn package_impl_base_add(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
for name in
|
||||
["prepare", "configure", "build", "check", "install"].into_iter()
|
||||
for name in ["prepare", "configure", "build", "test", "install"].into_iter()
|
||||
{
|
||||
let Err(e) = maybe_add_fn(&name_pkg.to_string(), ast, &base_ast, name)
|
||||
else {
|
||||
@ -707,8 +994,6 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
||||
|
||||
let name = input.ident.clone();
|
||||
let name_builder = quote::format_ident!("{name}Builder");
|
||||
let name_builder2 = name_builder.clone();
|
||||
let name_builder3 = name_builder.clone();
|
||||
let elements = match &input.data {
|
||||
::syn::Data::Struct(s) => match &s.fields {
|
||||
syn::Fields::Named(n) => n.named.clone(),
|
||||
@ -752,108 +1037,6 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
||||
None
|
||||
});
|
||||
let all_types2 = all_types.clone();
|
||||
let non_opt_fields = elements.iter().filter_map(|field| {
|
||||
if let Some(id) = field.ident.clone() {
|
||||
if id.to_string() == "version"
|
||||
|| id.to_string() == "_bok_base"
|
||||
|| id.to_string() == "_bok_repo"
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
match &field.ty {
|
||||
syn::Type::Path(pth) => {
|
||||
let first_path = pth.path.segments.first().unwrap();
|
||||
if first_path.ident == "Option" {
|
||||
None
|
||||
} else {
|
||||
let id = &field.ident;
|
||||
Some(quote! {#id})
|
||||
}
|
||||
}
|
||||
t => Some(quote! {#t}),
|
||||
}
|
||||
});
|
||||
let opt_fields = elements.iter().filter_map(|field| {
|
||||
if let Some(id) = field.ident.clone() {
|
||||
if id.to_string() == "version"
|
||||
|| id.to_string() == "_bok_base"
|
||||
|| id.to_string() == "_bok_repo"
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
match &field.ty {
|
||||
syn::Type::Path(pth) => {
|
||||
let first_path = pth.path.segments.first().unwrap();
|
||||
if first_path.ident == "Option" {
|
||||
let id = &field.ident;
|
||||
Some(quote! {#id})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
let non_opt_types = elements.iter().filter_map(|field| {
|
||||
if let Some(id) = field.ident.clone() {
|
||||
if id.to_string() == "version"
|
||||
|| id.to_string() == "_bok_base"
|
||||
|| id.to_string() == "_bok_repo"
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
match &field.ty {
|
||||
syn::Type::Path(pth) => {
|
||||
let first_path = pth.path.segments.first().unwrap();
|
||||
if first_path.ident == "Option" {
|
||||
None
|
||||
} else {
|
||||
let t = &field.ty;
|
||||
Some(quote! {#t})
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
let opt_types = elements.iter().filter_map(|field| {
|
||||
if let Some(id) = field.ident.clone() {
|
||||
if id.to_string() == "version"
|
||||
|| id.to_string() == "_bok_base"
|
||||
|| id.to_string() == "_bok_repo"
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if let ::syn::Type::Path(pth) = &field.ty {
|
||||
let first_path = pth.path.segments.first().unwrap();
|
||||
if first_path.ident == "Option" {
|
||||
if let syn::PathArguments::AngleBracketed(
|
||||
syn::AngleBracketedGenericArguments { args, .. },
|
||||
) = &first_path.arguments
|
||||
{
|
||||
if let Some(syn::GenericArgument::Type(syn::Type::Path(
|
||||
p,
|
||||
))) = args.first()
|
||||
{
|
||||
let id = &p.path.segments.first().unwrap().ident;
|
||||
return Some(quote! {#id});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
let non_opt_fields2 = non_opt_fields.clone();
|
||||
let non_opt_fields3 = non_opt_fields.clone();
|
||||
let non_opt_fields4 = non_opt_fields.clone();
|
||||
let non_opt_fields5 = non_opt_fields.clone();
|
||||
let opt_fields2 = opt_fields.clone();
|
||||
let opt_fields3 = opt_fields.clone();
|
||||
let opt_types2 = opt_types.clone();
|
||||
let non_opt_types2 = non_opt_types.clone();
|
||||
|
||||
{
|
||||
let ::syn::Data::Struct(ref mut ds) = input.data else {
|
||||
@ -941,7 +1124,7 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
||||
maybe_add_fn(&mut pkg_string, "prepare", &self.prepare_code().to_string())?;
|
||||
maybe_add_fn(&mut pkg_string, "configure", &self.configure_code().to_string())?;
|
||||
maybe_add_fn(&mut pkg_string, "build", &self.build_code().to_string())?;
|
||||
maybe_add_fn(&mut pkg_string, "check", &self.check_code().to_string())?;
|
||||
maybe_add_fn(&mut pkg_string, "test", &self.test_code().to_string())?;
|
||||
maybe_add_fn(&mut pkg_string, "install", &self.install_code().to_string())?;
|
||||
write!(&mut pkg_string, "}}\n")?;
|
||||
let re_parsed = ::syn::parse_file(&pkg_string).unwrap();
|
||||
@ -969,97 +1152,6 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
|
||||
&mut self.#all_fields3
|
||||
})*
|
||||
}
|
||||
#[derive(::std::default::Default, ::std::fmt::Debug)]
|
||||
pub struct #name_builder<R>
|
||||
where
|
||||
R: ::bok::Repository + 'static + #trait_deps,
|
||||
{
|
||||
_bok_repo: ::std::marker::PhantomData<R>,
|
||||
#(#non_opt_fields: ::std::option::Option<#non_opt_types>,)*
|
||||
#(#opt_fields: ::std::option::Option<#opt_types>,)*
|
||||
}
|
||||
impl<R> ::bok::PkgBuilder for #name_builder2<R>
|
||||
where
|
||||
R: ::bok::Repository + 'static + #trait_deps,
|
||||
{
|
||||
fn name(&self) -> ::bok::PkgName {
|
||||
use ::bok::Pkg;
|
||||
#name::<R>::default().name()
|
||||
}
|
||||
fn path(&self) -> ::bok::Path<::bok::PkgName> {
|
||||
use ::bok::Pkg;
|
||||
#name::<R>::default().path()
|
||||
}
|
||||
fn version(&self) -> ::bok::Version {
|
||||
use ::bok::Pkg;
|
||||
#name::<R>::default().version()
|
||||
}
|
||||
fn as_any(&self) -> &dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
fn default_unused(&mut self) -> &mut dyn ::bok::PkgBuilder {
|
||||
let def = #name::<R>::default();
|
||||
#(if self.#non_opt_fields5.is_none() {
|
||||
self.#non_opt_fields5 = Some(def.#non_opt_fields5);
|
||||
})*
|
||||
|
||||
self
|
||||
}
|
||||
fn build(&mut self) -> Result<Box<dyn ::bok::Pkg>, ::std::boxed::Box<dyn ::std::error::Error>> {
|
||||
#(if self.#non_opt_fields2.is_none() {
|
||||
return ::std::result::Result::Err("unset field".into());
|
||||
})*
|
||||
Ok(
|
||||
Box::new(#name::<R> {
|
||||
_bok_base: ::std::marker::PhantomData::default(),
|
||||
_bok_repo: ::std::marker::PhantomData::default(),
|
||||
version: #name::<R>::default().version,
|
||||
#(#non_opt_fields3 : self.#non_opt_fields3.clone().unwrap(),)*
|
||||
#(#opt_fields2 : self.#opt_fields2.clone(),)*
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
impl<R> #name_builder3<R>
|
||||
where
|
||||
R: ::bok::Repository +'static + #trait_deps,
|
||||
{
|
||||
pub fn as_any(&self) -> &dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
pub fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
pub fn as_builder(&self) -> &dyn ::bok::PkgBuilder {
|
||||
self
|
||||
}
|
||||
pub fn as_builder_mut(&mut self) -> &mut dyn ::bok::PkgBuilder {
|
||||
self
|
||||
}
|
||||
#(pub fn #non_opt_fields4 (&mut self, val : #non_opt_types2) -> &mut Self {
|
||||
if self.#non_opt_fields4 != None &&
|
||||
self.#non_opt_fields4 != Some(val) {
|
||||
panic!("Package \"{}\": mandatory attribute set multiple times: \"{}\"",
|
||||
::std::stringify!(#name),
|
||||
::std::stringify!(#non_opt_fields4));
|
||||
}
|
||||
self.#non_opt_fields4 = Some(val);
|
||||
self
|
||||
})*
|
||||
#(pub fn #opt_fields3 (&mut self, val : #opt_types2) -> &mut Self {
|
||||
if self.#opt_fields3 != None &&
|
||||
self.#opt_fields3 != Some(val) {
|
||||
panic!("Package \"{}\": optional attribute set multiple times: \"{}\"",
|
||||
::std::stringify!(#name),
|
||||
::std::stringify!(#opt_fields3));
|
||||
}
|
||||
self.#opt_fields3 = Some(val);
|
||||
self
|
||||
})*
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
|
@ -193,8 +193,7 @@ pub(crate) fn derive_repository(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
// holds the list of all package names, snake case
|
||||
let mut all_pkgs = Vec::<::syn::Ident>::with_capacity(items.fields.len());
|
||||
let mut all_deps_builder =
|
||||
Vec::<::syn::Path>::with_capacity(items.fields.len());
|
||||
let mut all_deps_builder = Vec::with_capacity(items.fields.len());
|
||||
|
||||
for it in items.fields.iter() {
|
||||
let Some(id) = &it.ident else { continue };
|
||||
@ -205,12 +204,31 @@ pub(crate) fn derive_repository(input: TokenStream) -> TokenStream {
|
||||
let ::syn::Type::Path(raw_path) = &it.ty else {
|
||||
continue;
|
||||
};
|
||||
let phantom_args = &raw_path.path.segments.last().unwrap().arguments;
|
||||
let ::syn::PathArguments::AngleBracketed(phantom_args) = phantom_args
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let Some(pkg_t) = phantom_args.args.iter().find(|it| {
|
||||
if let ::syn::GenericArgument::Type(_) = it {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}) else {
|
||||
continue;
|
||||
};
|
||||
let ::syn::GenericArgument::Type(::syn::Type::Path(pkg_t)) = pkg_t
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let name = id_str.strip_prefix("_p_").unwrap().to_owned();
|
||||
all_pkgs.push(::quote::format_ident!("{}", name));
|
||||
|
||||
let mut dep_builder_trait = raw_path.path.clone();
|
||||
let mut dep_builder_trait = pkg_t.path.clone();
|
||||
let pkg_t = &mut dep_builder_trait.segments.last_mut().unwrap();
|
||||
pkg_t.ident = ::quote::format_ident!("BokBuilderDeps{}", pkg_t.ident);
|
||||
pkg_t.arguments = ::syn::PathArguments::None;
|
||||
|
||||
all_deps_builder.push(dep_builder_trait);
|
||||
}
|
||||
@ -243,14 +261,9 @@ pub(crate) fn derive_repository(input: TokenStream) -> TokenStream {
|
||||
self
|
||||
}
|
||||
}
|
||||
//#[::bok_macro::collection(#(#all_deps_builder,)*)]
|
||||
struct Collection {
|
||||
repo: ::std::sync::Arc<#name>,
|
||||
pkgs: ::std::sync::RwLock<
|
||||
::std::vec::Vec<
|
||||
::std::sync::Arc<
|
||||
dyn ::bok::PkgBuilder>>>,
|
||||
}
|
||||
use ::bok_macro::collection;
|
||||
#[::bok_macro::collection(#name, #(#all_deps_builder),*)]
|
||||
pub struct Collection {}
|
||||
}.into()
|
||||
}
|
||||
|
||||
@ -526,6 +539,12 @@ pub(crate) fn repo_impl_methods(
|
||||
};
|
||||
t.path.clone()
|
||||
};
|
||||
let t_builder_id = {
|
||||
let mut b_id = t_id.clone();
|
||||
let last = b_id.segments.last_mut().unwrap();
|
||||
last.ident = ::quote::format_ident!("{}Builder", last.ident);
|
||||
b_id
|
||||
};
|
||||
let pkg_name = {
|
||||
let segment = t_id.segments.iter().last().unwrap();
|
||||
|
||||
@ -535,6 +554,7 @@ pub(crate) fn repo_impl_methods(
|
||||
segment.ident.to_string().to_case(Case::Snake)
|
||||
)
|
||||
};
|
||||
let pkgbuilder_name = ::quote::format_ident!("{}_builder", pkg_name);
|
||||
all_pkgs_types.push(t_id.clone());
|
||||
if local
|
||||
.items
|
||||
@ -552,18 +572,30 @@ pub(crate) fn repo_impl_methods(
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut t_id_build = t_id.clone();
|
||||
let mut t_id_generic = t_id.clone();
|
||||
if let ::syn::PathArguments::AngleBracketed(args) =
|
||||
&mut t_id_build.segments.last_mut().unwrap().arguments
|
||||
&mut t_id_generic.segments.last_mut().unwrap().arguments
|
||||
{
|
||||
args.colon2_token = Some(::syn::token::PathSep::default());
|
||||
}
|
||||
let mut t_builder_id_generic = t_builder_id.clone();
|
||||
if let ::syn::PathArguments::AngleBracketed(args) =
|
||||
&mut t_builder_id_generic.segments.last_mut().unwrap().arguments
|
||||
{
|
||||
args.colon2_token = Some(::syn::token::PathSep::default());
|
||||
}
|
||||
let pkg_fn: ::syn::ImplItemFn = ::syn::parse_quote! {
|
||||
pub fn #pkg_name(&self) -> #t_id {
|
||||
#t_id_build::default()
|
||||
#t_id_generic::default()
|
||||
}
|
||||
};
|
||||
let pkgbuilder_fn: ::syn::ImplItemFn = ::syn::parse_quote! {
|
||||
pub fn #pkgbuilder_name(&self) -> #t_builder_id {
|
||||
#t_builder_id_generic::new()
|
||||
}
|
||||
};
|
||||
fn_to_add.push(pkg_fn);
|
||||
fn_to_add.push(pkgbuilder_fn);
|
||||
}
|
||||
|
||||
// keep sorted for easier debugging when expanding macros
|
||||
|
@ -27,17 +27,19 @@ fn main() {
|
||||
use ::bok::Repository;
|
||||
println!("pkgs1: {}", pkgs1.name());
|
||||
println!("pkgs2: {}", pkgs2.name());
|
||||
/*
|
||||
let build_deps = ::bok::deps::Build(::bok::Collection::new());
|
||||
let run_deps = ::bok::deps::Runtime(::bok::Collection::new());
|
||||
|
||||
let one = pkgs1.one();
|
||||
use ::bok::Pkg;
|
||||
let res = one.dependencies_set(pkgs1, &build_deps, &run_deps);
|
||||
println!("{:?}", res);
|
||||
//let res = one.dependencies_set(pkgs1, &build_deps, &run_deps);
|
||||
//println!("{:?}", res);
|
||||
|
||||
let two = pkgs2.two();
|
||||
let res = two.dependencies_set(pkgs2, &build_deps, &run_deps);
|
||||
println!("{:?}", res);
|
||||
//let res = two.dependencies_set(pkgs2, &build_deps, &run_deps);
|
||||
//println!("{:?}", res);
|
||||
*/
|
||||
|
||||
/*
|
||||
let mut pb: pkgs::one::OneBuilder = pkgs1.one();
|
||||
|
@ -46,11 +46,16 @@ impl ::bok::Pkg for One {
|
||||
fn build(&self) -> ::core::result::Result<(), ()> {
|
||||
::core::result::Result::Ok(())
|
||||
}
|
||||
fn dependencies_set(
|
||||
}
|
||||
|
||||
#[::bok::package_impl]
|
||||
impl ::bok::PkgBuilder for One {
|
||||
fn set_dependencies(
|
||||
&self,
|
||||
repo: ::std::sync::Arc<dyn ::bok::Repository>,
|
||||
_build: &::bok::deps::Build,
|
||||
_runtime: &::bok::deps::Runtime,
|
||||
_build: ::bok::deps::Build,
|
||||
_runtime: ::bok::deps::Runtime,
|
||||
_test: ::bok::deps::Test,
|
||||
) -> Result<(), ()> {
|
||||
//TODO: automatically add repo type conversion via macro
|
||||
let repo_any = repo.as_any();
|
||||
|
@ -47,11 +47,15 @@ impl ::bok::Pkg for Three {
|
||||
fn build(&self) -> ::core::result::Result<(), ()> {
|
||||
::core::result::Result::Ok(())
|
||||
}
|
||||
fn dependencies_set(
|
||||
}
|
||||
#[::bok::package_impl]
|
||||
impl ::bok::PkgBuilder for Three {
|
||||
fn set_dependencies(
|
||||
&self,
|
||||
_repo: ::std::sync::Arc<dyn ::bok::Repository>,
|
||||
_build: &::bok::deps::Build,
|
||||
_runtime: &::bok::deps::Runtime,
|
||||
_build: ::bok::deps::Build,
|
||||
_runtime: ::bok::deps::Runtime,
|
||||
_test: ::bok::deps::Test,
|
||||
) -> Result<(), ()> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -42,12 +42,16 @@ impl ::std::default::Default for Two {
|
||||
}
|
||||
|
||||
#[::bok::package_impl]
|
||||
impl ::bok::Pkg for Two {
|
||||
fn dependencies_set(
|
||||
impl ::bok::Pkg for Two {}
|
||||
|
||||
#[::bok::package_impl]
|
||||
impl ::bok::PkgBuilder for Two {
|
||||
fn set_dependencies(
|
||||
&self,
|
||||
repo: ::std::sync::Arc<dyn ::bok::Repository>,
|
||||
build: &::bok::deps::Build,
|
||||
_runtime: &::bok::deps::Runtime,
|
||||
build: ::bok::deps::Build,
|
||||
_runtime: ::bok::deps::Runtime,
|
||||
_test: ::bok::deps::Test,
|
||||
) -> Result<(), ()> {
|
||||
//TODO: automatically add repo type conversion via macro
|
||||
let repo_any = repo.as_any();
|
||||
|
@ -35,81 +35,4 @@ type ArcLock<T> = Arc<RwLock<T>>;
|
||||
type PkgMap =
|
||||
BTreeMap<Path<PkgName>, (Arc<dyn Repository>, ArcLock<dyn PkgBuilder>)>;
|
||||
|
||||
/// Collection of packages, subset of what is present on one repository only
|
||||
pub struct Collection {
|
||||
repos: RwLock<Vec<Arc<dyn Repository>>>,
|
||||
repos_pkgs: RwLock<BTreeMap<Path<RepoName>, PkgMap>>,
|
||||
}
|
||||
|
||||
impl Collection {
|
||||
/// Create a new empty collection of pkgs
|
||||
pub fn new() -> Collection {
|
||||
Collection {
|
||||
repos: RwLock::new(Vec::with_capacity(8)),
|
||||
repos_pkgs: RwLock::new(BTreeMap::new()),
|
||||
}
|
||||
}
|
||||
pub fn add_pkg(
|
||||
&self,
|
||||
r: Arc<dyn Repository>,
|
||||
p: ArcLock<dyn PkgBuilder>,
|
||||
) -> Result<(), Error> {
|
||||
let repo_name = r.path();
|
||||
let mut repos = self.repos.write().unwrap();
|
||||
let mut repos_pkgs = self.repos_pkgs.write().unwrap();
|
||||
if repos
|
||||
.binary_search_by(|x| x.path().cmp(&repo_name))
|
||||
.is_err()
|
||||
{
|
||||
repos.push(r.clone());
|
||||
repos.sort_by(|a, b| a.path().cmp(&b.path()))
|
||||
}
|
||||
let pkg_name = p.read().unwrap().path();
|
||||
match repos_pkgs.get_mut(&repo_name) {
|
||||
Some(pkg_map) => match pkg_map.get(&pkg_name) {
|
||||
Some((r, p)) => {
|
||||
return Err(Error::AlreadyPresent((r.clone(), p.clone())));
|
||||
}
|
||||
None => {
|
||||
pkg_map.insert(pkg_name, (r, p));
|
||||
}
|
||||
},
|
||||
None => {
|
||||
let mut pkg_map: PkgMap = BTreeMap::new();
|
||||
pkg_map.insert(pkg_name, (r, p));
|
||||
repos_pkgs.insert(repo_name, pkg_map);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn find(
|
||||
&self,
|
||||
pkg_path: Path<PkgName>,
|
||||
) -> Result<(Arc<dyn Repository>, ArcLock<dyn PkgBuilder>), Error> {
|
||||
let repos_pkgs = self.repos_pkgs.read().unwrap();
|
||||
for (_, pkg_map) in repos_pkgs.iter() {
|
||||
match pkg_map.get(&pkg_path) {
|
||||
Some((r, p)) => {
|
||||
return Ok((r.clone(), p.clone()));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
Err(Error::NotFound)
|
||||
}
|
||||
pub fn find_in_repo(
|
||||
&self,
|
||||
repo_path: Path<RepoName>,
|
||||
pkg_path: Path<PkgName>,
|
||||
) -> Result<(Arc<dyn Repository>, ArcLock<dyn PkgBuilder>), Error> {
|
||||
let repos_pkgs = self.repos_pkgs.read().unwrap();
|
||||
match repos_pkgs.get(&repo_path) {
|
||||
None => Err(Error::NotFound),
|
||||
Some(pkg_map) => match pkg_map.get(&pkg_path) {
|
||||
Some((r, p)) => Ok((r.clone(), p.clone())),
|
||||
None => Err(Error::NotFound),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
pub trait Collection {}
|
||||
|
@ -22,8 +22,9 @@ mod names;
|
||||
pub use collection::Collection;
|
||||
pub use names::{Path, PkgName, RepoName};
|
||||
pub mod deps {
|
||||
pub struct Build(pub crate::Collection);
|
||||
pub struct Runtime(pub crate::Collection);
|
||||
pub struct Build(pub ::std::sync::Arc<dyn crate::Collection>);
|
||||
pub struct Runtime(pub ::std::sync::Arc<dyn crate::Collection>);
|
||||
pub struct Test(pub ::std::sync::Arc<dyn crate::Collection>);
|
||||
}
|
||||
|
||||
pub use ::bok_macro::{
|
||||
@ -95,27 +96,21 @@ pub trait Pkg:
|
||||
fn version(&self) -> Version;
|
||||
fn as_any(&self) -> &dyn ::std::any::Any;
|
||||
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any;
|
||||
fn dependencies_set(
|
||||
&self,
|
||||
repo: Arc<dyn Repository>,
|
||||
build: &deps::Build,
|
||||
runtime: &deps::Runtime,
|
||||
) -> Result<(), ()>;
|
||||
fn prepare(&self) -> ::core::result::Result<(), ()>;
|
||||
fn prepare_code(&self) -> ::proc_macro2::TokenStream;
|
||||
fn configure(&self) -> ::core::result::Result<(), ()>;
|
||||
fn configure_code(&self) -> ::proc_macro2::TokenStream;
|
||||
fn build(&self) -> ::core::result::Result<(), ()>;
|
||||
fn build_code(&self) -> ::proc_macro2::TokenStream;
|
||||
fn check(&self) -> ::core::result::Result<(), ()>;
|
||||
fn check_code(&self) -> ::proc_macro2::TokenStream;
|
||||
fn test(&self) -> ::core::result::Result<(), ()>;
|
||||
fn test_code(&self) -> ::proc_macro2::TokenStream;
|
||||
fn install(&self) -> ::core::result::Result<(), ()>;
|
||||
fn install_code(&self) -> ::proc_macro2::TokenStream;
|
||||
fn package(&self) -> ::core::result::Result<(), ()> {
|
||||
self.prepare()?;
|
||||
self.configure()?;
|
||||
self.build()?;
|
||||
self.check()?;
|
||||
self.test()?;
|
||||
self.install()
|
||||
}
|
||||
fn hash(&self) -> Hash;
|
||||
@ -123,12 +118,19 @@ pub trait Pkg:
|
||||
}
|
||||
|
||||
pub trait PkgBuilder: ::core::fmt::Debug + ::std::any::Any {
|
||||
fn name(&self) -> crate::PkgName;
|
||||
fn path(&self) -> crate::Path<crate::PkgName>;
|
||||
fn version(&self) -> crate::Version;
|
||||
fn name(&self) -> PkgName;
|
||||
fn path(&self) -> Path<PkgName>;
|
||||
fn version(&self) -> Version;
|
||||
fn as_any(&self) -> &dyn ::std::any::Any;
|
||||
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any;
|
||||
fn default_unused(&mut self) -> &mut dyn crate::PkgBuilder;
|
||||
fn default_unused(&mut self) -> &mut dyn PkgBuilder;
|
||||
fn set_dependencies(
|
||||
&self,
|
||||
repo: Arc<dyn Repository>,
|
||||
build: deps::Build,
|
||||
runtime: deps::Runtime,
|
||||
test: deps::Test,
|
||||
) -> Result<(), ()>;
|
||||
fn build(
|
||||
&mut self,
|
||||
) -> Result<Box<dyn Pkg>, ::std::boxed::Box<dyn ::std::error::Error>>;
|
||||
@ -183,14 +185,6 @@ impl Pkg for PkgEmpty {
|
||||
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
fn dependencies_set(
|
||||
&self,
|
||||
_repo: Arc<dyn Repository>,
|
||||
_build: &deps::Build,
|
||||
_runtime: &deps::Runtime,
|
||||
) -> Result<(), ()> {
|
||||
Ok(())
|
||||
}
|
||||
fn prepare(&self) -> ::core::result::Result<(), ()> {
|
||||
::core::result::Result::Ok(())
|
||||
}
|
||||
@ -215,10 +209,10 @@ impl Pkg for PkgEmpty {
|
||||
::core::result::Result::Ok(());
|
||||
}
|
||||
}
|
||||
fn check(&self) -> ::core::result::Result<(), ()> {
|
||||
fn test(&self) -> ::core::result::Result<(), ()> {
|
||||
::core::result::Result::Ok(())
|
||||
}
|
||||
fn check_code(&self) -> ::proc_macro2::TokenStream {
|
||||
fn test_code(&self) -> ::proc_macro2::TokenStream {
|
||||
::quote::quote! {
|
||||
::core::result::Result::Ok(());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user