Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fud2] update path finding to support multi state input and output #2134

Merged
merged 38 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
59e63b3
generalize op type
jku20 Jun 7, 2024
2641b54
output used output states with operation
jku20 Jun 7, 2024
a3b9db2
generalize find_path for many inputs and outputs
jku20 Jun 10, 2024
66a3f15
cargo fmt
jku20 Jun 11, 2024
d9a3fb3
make op graph use adjacency lists and algo change
jku20 Jun 13, 2024
b1d83b8
fix find_path algorithm
jku20 Jun 18, 2024
7d789ab
remove debug print statements
jku20 Jun 18, 2024
edbafaf
remove extra parenthesis
jku20 Jun 18, 2024
d4b84ce
stop unreachable ops being considered for plans
jku20 Jun 19, 2024
75d6d85
making file naming not depend on stems and paths
jku20 Jun 19, 2024
1bf07a2
generalize emit logic
jku20 Jun 20, 2024
d36f79d
implement requests for multiple inputs and outputs
jku20 Jun 21, 2024
a035a94
cargo fmt
jku20 Jun 24, 2024
4090f6e
use simple enumerative search for find_path
jku20 Jun 25, 2024
252e898
cargo clippy
jku20 Jun 25, 2024
2967705
Merge branch 'main' into fud2-multi-input-output-find-path
jku20 Jun 25, 2024
7a5d63a
fix off by one
jku20 Jun 25, 2024
de0dbb5
modify cli to support multiple inputs and outputs
jku20 Jun 25, 2024
9fcfab7
fix name generation on cyclic plans
jku20 Jun 25, 2024
58b402d
remove intermediate file dedup
jku20 Jun 25, 2024
bd596e0
remove commented out prints
jku20 Jun 25, 2024
acdbf4e
refactors for readability
jku20 Jul 1, 2024
574e2d6
document IO
jku20 Jul 1, 2024
e711f81
fix typo
jku20 Jul 2, 2024
47699b8
clarify iteration using any
jku20 Jul 2, 2024
29820aa
fix documentation
jku20 Jul 2, 2024
20e3fb4
refactor and document gen_name
jku20 Jul 2, 2024
8d557f5
restore relative generated file path
jku20 Jul 2, 2024
afe6194
refactor gen_name and IO
jku20 Jul 2, 2024
d11dd29
factor out path find code and use enumerate search
jku20 Jul 2, 2024
fbfba5e
convert default impl to macro
jku20 Jul 3, 2024
3b5afb7
add option to choose between old and new plan algo
jku20 Jul 3, 2024
4a7fb63
simplify and document enumeration find_path algo
jku20 Jul 3, 2024
cf3526f
documentation improvements
jku20 Jul 3, 2024
386948d
document FindPath
jku20 Jul 3, 2024
3c28fcf
remove new find_path algorithm
jku20 Jul 3, 2024
c71a6b7
rename path to plan and fix typos
jku20 Jul 8, 2024
26b59ae
more typos
jku20 Jul 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 73 additions & 34 deletions fud2/fud-core/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::config;
use crate::exec::{Driver, Request, StateRef};
use crate::exec::{
Driver, EnumeratePlanner, Request, SingleOpOutputPlanner, StateRef,
};
use crate::run::Run;
use anyhow::{anyhow, bail};
use argh::FromArgs;
Expand Down Expand Up @@ -91,19 +93,23 @@ struct FakeArgs {

/// the input file
#[argh(positional)]
input: Option<Utf8PathBuf>,
input: Vec<Utf8PathBuf>,

/// the output file
#[argh(option, short = 'o')]
output: Option<Utf8PathBuf>,
output: Vec<Utf8PathBuf>,

/// the state to start from
/// the states to start from.
/// The ith state is applied to the ith input file.
/// If more states are specified than files, files for these states are read from stdin.
#[argh(option)]
from: Option<String>,
from: Vec<String>,

/// the state to produce
/// The ith state is applied to the ith output file.
/// If more states are specified than files, files for these states are written to stdout
#[argh(option)]
to: Option<String>,
to: Vec<String>,

/// execution mode (run, plan, emit, gen, dot)
#[argh(option, short = 'm', default = "Mode::Run")]
Expand Down Expand Up @@ -132,34 +138,63 @@ struct FakeArgs {
/// log level for debugging fud internal
#[argh(option, long = "log", default = "log::LevelFilter::Warn")]
pub log_level: log::LevelFilter,

/// use new enumeration algorithm for finding operation sequences
#[argh(switch)]
planner: bool,
}

fn from_state(driver: &Driver, args: &FakeArgs) -> anyhow::Result<StateRef> {
match &args.from {
Some(name) => driver
.get_state(name)
.ok_or(anyhow!("unknown --from state")),
None => match args.input {
Some(ref input) => driver
.guess_state(input)
.ok_or(anyhow!("could not infer input state")),
None => bail!("specify an input file or use --from"),
},
fn get_states_with_errors(
driver: &Driver,
explicit_states: &[String],
files: &[Utf8PathBuf],
unknown_state: &str,
uninferable_file: &str,
no_states: &str,
) -> anyhow::Result<Vec<StateRef>> {
let explicit_states = explicit_states.iter().map(|state_str| {
driver
.get_state(state_str)
.ok_or(anyhow!("{unknown_state}"))
});
let inferred_states =
files.iter().skip(explicit_states.len()).map(|input_str| {
driver
.guess_state(input_str)
.ok_or(anyhow!("{uninferable_file}"))
});
let states = explicit_states
.chain(inferred_states)
.collect::<Result<Vec<_>, _>>()?;
if states.is_empty() {
bail!("{no_states}");
}
Ok(states)
}

fn to_state(driver: &Driver, args: &FakeArgs) -> anyhow::Result<StateRef> {
match &args.to {
Some(name) => {
driver.get_state(name).ok_or(anyhow!("unknown --to state"))
}
None => match &args.output {
Some(out) => driver
.guess_state(out)
.ok_or(anyhow!("could not infer output state")),
None => Err(anyhow!("specify an output file or use --to")),
},
}
fn from_states(
driver: &Driver,
args: &FakeArgs,
) -> anyhow::Result<Vec<StateRef>> {
get_states_with_errors(
driver,
&args.from,
&args.input,
"unknown --from state",
"could not infer input state",
"specify and input file or use --from",
)
}

fn to_state(driver: &Driver, args: &FakeArgs) -> anyhow::Result<Vec<StateRef>> {
jku20 marked this conversation as resolved.
Show resolved Hide resolved
get_states_with_errors(
driver,
&args.to,
&args.output,
"unknown --to state",
"could no infer output state",
"specify an output file or use --to",
)
}

fn get_request(driver: &Driver, args: &FakeArgs) -> anyhow::Result<Request> {
Expand All @@ -185,14 +220,18 @@ fn get_request(driver: &Driver, args: &FakeArgs) -> anyhow::Result<Request> {
.ok_or(anyhow!("unknown --through op {}", s))
})
.collect();

Ok(Request {
start_file: args.input.clone(),
start_state: from_state(driver, args)?,
end_file: args.output.clone(),
end_state: to_state(driver, args)?,
start_files: args.input.clone(),
start_states: from_states(driver, args)?,
end_files: args.output.clone(),
end_states: to_state(driver, args)?,
through: through?,
workdir,
planner: if args.planner {
Box::new(EnumeratePlanner {})
} else {
Box::new(SingleOpOutputPlanner {})
},
})
}

Expand Down
6 changes: 3 additions & 3 deletions fud2/fud-core/src/exec/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl State {
self.extensions.iter().any(|e| e == ext)
}

/// Is this a "pseudo-state": doesn't correspond to an actual file, and must be an output state?
/// Is this a "pseudo-state": doesn't correspond to an actual file
pub fn is_pseudo(&self) -> bool {
self.extensions.is_empty()
}
Expand All @@ -38,8 +38,8 @@ entity_impl!(StateRef, "state");
/// An Operation transforms files from one State to another.
pub struct Operation {
pub name: String,
pub input: StateRef,
pub output: StateRef,
pub input: Vec<StateRef>,
pub output: Vec<StateRef>,
pub setups: Vec<SetupRef>,
pub emit: Box<dyn run::EmitBuild>,
/// Describes where this operation was defined.
Expand Down
Loading
Loading