Make blueprint files configurable in and out

Closes #1055.
This commit is contained in:
KtorZ 2024-11-13 18:12:52 +01:00
parent c523b0153d
commit a51f7285c1
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
8 changed files with 120 additions and 34 deletions

View File

@ -9,6 +9,7 @@
### Changed
- **aiken**: Add more flexibility around the management of Plutus blueprint files for `build`, `address`, `policy` and `apply` commands. See [#1055](https://github.com/aiken-lang/aiken/issues/1055). @KtorZ
- **aiken**: Rename `--filter_traces` to `--trace_filter` for more consistency with `--trace_level`. An alias for `--filter_traces` still exists for backward compatibility. @KtorZ
- **aiken-project**: Fix `aiken docs` wrongly formatting list constants as tuples. See [#1048](https://github.com/aiken-lang/aiken/issues/1048). @KtorZ
- **aiken-project**: Fix `aiken docs` source linking crashing when generating docs for config modules. See [#1044](https://github.com/aiken-lang/aiken/issues/1044). @KtorZ

View File

@ -192,16 +192,25 @@ where
self.defined_modules = checkpoint.defined_modules;
}
pub fn blueprint_path(&self, filepath: Option<&Path>) -> PathBuf {
match filepath {
Some(filepath) => filepath.to_path_buf(),
None => self.root.join(Options::default().blueprint_path),
}
}
pub fn build(
&mut self,
uplc: bool,
tracing: Tracing,
blueprint_path: PathBuf,
env: Option<String>,
) -> Result<(), Vec<Error>> {
let options = Options {
code_gen_mode: CodeGenMode::Build(uplc),
tracing,
env,
blueprint_path,
};
self.compile(options)
@ -282,6 +291,7 @@ where
property_max_success,
}
},
blueprint_path: self.blueprint_path(None),
};
self.compile(options)
@ -307,10 +317,6 @@ where
Ok(())
}
pub fn blueprint_path(&self) -> PathBuf {
self.root.join("plutus.json")
}
fn config_definitions(&mut self, env: Option<&str>) -> Option<Vec<UntypedDefinition>> {
if !self.config.config.is_empty() {
let env = env.unwrap_or(ast::DEFAULT_ENV_MODULE);
@ -359,7 +365,7 @@ where
CodeGenMode::Build(uplc_dump) => {
self.event_listener
.handle_event(Event::GeneratingBlueprint {
path: self.blueprint_path(),
path: options.blueprint_path.clone(),
});
self.checked_modules.values_mut().for_each(|m| {
@ -381,10 +387,10 @@ where
let json = serde_json::to_string_pretty(&blueprint).unwrap();
fs::write(self.blueprint_path(), json).map_err(|error| {
fs::write(options.blueprint_path.as_path(), json).map_err(|error| {
Error::FileIo {
error,
path: self.blueprint_path(),
path: options.blueprint_path,
}
.into()
})
@ -444,6 +450,7 @@ where
&self,
title: Option<&String>,
stake_address: Option<&String>,
blueprint_path: &Path,
mainnet: bool,
) -> Result<ShelleyAddress, Error> {
// Parse stake address
@ -465,7 +472,7 @@ where
};
// Read blueprint
let blueprint = File::open(self.blueprint_path())
let blueprint = File::open(blueprint_path)
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
let blueprint: Blueprint = serde_json::from_reader(BufReader::new(blueprint))?;
@ -502,9 +509,9 @@ where
})
}
pub fn policy(&self, title: Option<&String>) -> Result<PolicyId, Error> {
pub fn policy(&self, title: Option<&String>, blueprint_path: &Path) -> Result<PolicyId, Error> {
// Read blueprint
let blueprint = File::open(self.blueprint_path())
let blueprint = File::open(blueprint_path)
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
let blueprint: Blueprint = serde_json::from_reader(BufReader::new(blueprint))?;
@ -565,7 +572,7 @@ where
pub fn construct_parameter_incrementally<F>(
&self,
title: Option<&String>,
blueprint_input: &Option<PathBuf>,
blueprint_path: &Path,
ask: F,
) -> Result<PlutusData, Error>
where
@ -575,11 +582,6 @@ where
) -> Result<PlutusData, blueprint::error::Error>,
{
// Read blueprint
let project_blueprint_path = self.blueprint_path();
let blueprint_path = blueprint_input
.as_ref()
.map(|p| p.as_path())
.unwrap_or_else(|| &project_blueprint_path);
let blueprint = File::open(blueprint_path)
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
let blueprint: Blueprint = serde_json::from_reader(BufReader::new(blueprint))?;
@ -601,10 +603,11 @@ where
pub fn apply_parameter(
&self,
title: Option<&String>,
blueprint_path: &Path,
param: &PlutusData,
) -> Result<Blueprint, Error> {
// Read blueprint
let blueprint = File::open(self.blueprint_path())
let blueprint = File::open(blueprint_path)
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
let mut blueprint: Blueprint = serde_json::from_reader(BufReader::new(blueprint))?;

View File

@ -1,9 +1,11 @@
use aiken_lang::ast::Tracing;
use std::path::PathBuf;
pub struct Options {
pub code_gen_mode: CodeGenMode,
pub tracing: Tracing,
pub env: Option<String>,
pub blueprint_path: PathBuf,
}
impl Default for Options {
@ -12,6 +14,7 @@ impl Default for Options {
code_gen_mode: CodeGenMode::NoOp,
tracing: Tracing::silent(),
env: None,
blueprint_path: PathBuf::from("plutus.json"),
}
}
}

View File

@ -7,6 +7,18 @@ pub struct Args {
/// Path to project
directory: Option<PathBuf>,
/// Optional path to the Plutus blueprint file to be used as input.
///
/// [default: plutus.json]
#[clap(
short,
long = "in",
value_parser,
value_name = "FILEPATH",
verbatim_doc_comment
)]
input: Option<PathBuf>,
/// Name of the validator's module within the project. Optional if there's only one validator
#[clap(short, long)]
module: Option<String>,
@ -27,6 +39,7 @@ pub struct Args {
pub fn exec(
Args {
directory,
input,
module,
validator,
delegated_to,
@ -46,7 +59,12 @@ pub fn exec(
let title = title.as_ref().or(validator.as_ref());
let address = p.address(title, delegated_to.as_ref(), mainnet)?;
let address = p.address(
title,
delegated_to.as_ref(),
p.blueprint_path(input.as_deref()).as_path(),
mainnet,
)?;
println!("{}", address.to_bech32().unwrap());

View File

@ -27,14 +27,22 @@ pub struct Args {
#[clap(value_name = "CBOR")]
parameter: Option<String>,
/// Optional path to the blueprint file to be used as input. Default to 'plutus.json' when
/// omitted.
#[clap(short, long = "in", value_parser, value_name = "FILEPATH")]
/// Optional path to the blueprint file to be used as input.
///
/// [default: plutus.json]
#[clap(
short,
long = "in",
value_parser,
value_name = "FILEPATH",
verbatim_doc_comment
)]
input: Option<PathBuf>,
/// Output file. Optional, print on stdout when omitted.
#[clap(short, long, value_name = "FILEPATH")]
out: Option<PathBuf>,
/// Optional relative filepath to the generated Plutus blueprint. Default to printing to stdout
/// when omitted.
#[clap(short, long("out"), value_parser, value_name = "FILEPATH")]
output: Option<PathBuf>,
/// Name of the validator's module within the project. Optional if there's only one validator.
#[clap(short, long)]
@ -49,7 +57,7 @@ pub fn exec(
Args {
parameter,
input,
out,
output,
module,
validator,
}: Args,
@ -74,6 +82,8 @@ pub fn exec(
.if_supports_color(Stderr, |s| s.bold()),
);
let blueprint_input_path = p.blueprint_path(input.as_deref());
let data: PlutusData = match &parameter {
Some(param) => {
eprintln!(
@ -110,7 +120,9 @@ pub fn exec(
})
}
None => p.construct_parameter_incrementally(title, &input, ask_schema)?,
None => {
p.construct_parameter_incrementally(title, &blueprint_input_path, ask_schema)?
}
};
eprintln!(
@ -124,19 +136,22 @@ pub fn exec(
}
);
let blueprint = p.apply_parameter(title, &data)?;
let blueprint = p.apply_parameter(title, &blueprint_input_path, &data)?;
let json = serde_json::to_string_pretty(&blueprint).unwrap();
match out {
match output {
None => {
println!("\n{}\n", json);
Ok(())
}
Some(ref path) => fs::write(path, json).map_err(|error| Error::FileIo {
error,
path: p.blueprint_path(),
}),
Some(ref path) => {
let blueprint_output_path = p.blueprint_path(Some(path));
fs::write(&blueprint_output_path, json).map_err(|error| Error::FileIo {
error,
path: blueprint_output_path,
})
}
}?;
eprintln!(

View File

@ -7,6 +7,18 @@ pub struct Args {
/// Path to project
directory: Option<PathBuf>,
/// Optional path to the blueprint file to be used as input.
///
/// [default: plutus.json]
#[clap(
short,
long = "in",
value_parser,
value_name = "FILEPATH",
verbatim_doc_comment
)]
input: Option<PathBuf>,
/// Name of the validator's module within the project. Optional if there's only one validator
#[clap(short, long)]
module: Option<String>,
@ -19,6 +31,7 @@ pub struct Args {
pub fn exec(
Args {
directory,
input,
module,
validator,
}: Args,
@ -36,7 +49,12 @@ pub fn exec(
let title = title.as_ref().or(validator.as_ref());
let address = p.address(title, None, false)?;
let address = p.address(
title,
None,
p.blueprint_path(input.as_deref()).as_path(),
false,
)?;
println!("{}", address.payment().to_hex());

View File

@ -7,6 +7,18 @@ pub struct Args {
/// Path to project
directory: Option<PathBuf>,
/// Optional path to the blueprint file to be used as input.
///
/// [default: plutus.json]
#[clap(
short,
long = "in",
value_parser,
value_name = "FILEPATH",
verbatim_doc_comment
)]
input: Option<PathBuf>,
/// Name of the validator's module within the project. Optional if there's only one validator
#[clap(short, long)]
module: Option<String>,
@ -19,6 +31,7 @@ pub struct Args {
pub fn exec(
Args {
directory,
input,
module,
validator,
}: Args,
@ -36,7 +49,7 @@ pub fn exec(
let title = title.as_ref().or(validator.as_ref());
let policy = p.policy(title)?;
let policy = p.policy(title, p.blueprint_path(input.as_deref()).as_path())?;
println!("{}", policy);

View File

@ -25,6 +25,18 @@ pub struct Args {
#[clap(long)]
env: Option<String>,
/// Optional relative filepath to the generated Plutus blueprint.
///
/// [default: plutus.json]
#[clap(
short,
long("out"),
value_parser,
value_name = "FILEPATH",
verbatim_doc_comment
)]
output: Option<PathBuf>,
/// Filter traces to be included in the generated program(s).
///
/// - user-defined:
@ -67,6 +79,7 @@ pub fn exec(
uplc,
trace_filter,
trace_level,
output,
env,
}: Args,
) -> miette::Result<()> {
@ -78,6 +91,7 @@ pub fn exec(
Some(trace_filter) => trace_filter(trace_level),
None => Tracing::All(trace_level),
},
p.blueprint_path(output.as_deref()),
env.clone(),
)
})
@ -89,6 +103,7 @@ pub fn exec(
Some(trace_filter) => trace_filter(trace_level),
None => Tracing::All(trace_level),
},
p.blueprint_path(output.as_deref()),
env.clone(),
)
})