Skip to content

Commit

Permalink
Adds --stop-on-block/--stop option to solver.
Browse files Browse the repository at this point in the history
This stops the solver when it first reaches a BLOCKED state and would
step back. This is useful when working out missing dependencies,
e.g. when porting a package between OSes or python versions.

Signed-off-by: David Gilligan-Cook <dcook@imageworks.com>
  • Loading branch information
dcookspi committed Apr 30, 2024
1 parent 504f6aa commit 663665b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 6 deletions.
5 changes: 5 additions & 0 deletions crates/spk-cli/common/src/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,10 @@ pub struct DecisionFormatterSettings {
/// comparing them.
#[clap(long)]
compare_solvers: bool,

/// Stop the solver the first time it is BLOCKED.
#[clap(long, alias = "stop")]
stop_on_block: bool,
}

impl DecisionFormatterSettings {
Expand Down Expand Up @@ -1115,6 +1119,7 @@ impl DecisionFormatterSettings {
.with_status_bar(self.status_bar)
.with_solver_to_run(self.solver_to_run.into())
.with_search_space_size(self.show_search_size)
.with_stop_on_block(self.stop_on_block)
.with_compare_solvers(self.compare_solvers);
Ok(builder)
}
Expand Down
52 changes: 46 additions & 6 deletions crates/spk-solve/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,22 @@ pub fn format_note(note: &Note) -> String {
}
}

pub fn change_is_relevant_at_verbosity(change: &Change, verbosity: u8) -> bool {
pub fn change_is_relevant_at_verbosity(
change: &Change,
verbosity: u8,
stop_on_block: bool,
) -> bool {
use Change::*;
let relevant_level = match change {
SetPackage(_) => 1,
StepBack(_) => 1,
StepBack(_) => {
// More relevant when stop-on-block is enabled.
if stop_on_block {
0
} else {
1
}
}
RequestPackage(_) => 2,
RequestVar(_) => 2,
SetOptions(_) => 3,
Expand Down Expand Up @@ -201,12 +212,22 @@ where

pub fn iter(&mut self) -> impl Stream<Item = Result<String>> + '_ {
stream! {
let mut stop_because_blocked = false;
'outer: loop {
if let Some(next) = self.output_queue.pop_front() {
yield Ok(next);
continue 'outer;
}

// Check if the solver should stop because the last
// decision was a step-back (BLOCKED) with stop-on-block set
if stop_because_blocked {
yield(Err(Error::SolverInterrupted(
"hit BLOCKED state with '--stop-on-block' enabled.".to_string(),
)));
continue 'outer;
}

while self.output_queue.is_empty() {
// First, check if the solver has taken too long or the
// user has interrupted the solver
Expand Down Expand Up @@ -309,13 +330,17 @@ where
StepBack(spk_solve_graph::StepBack { destination, .. }) => {
fill = "!";
new_level = destination.state_depth;
// Ensures the solver will stop before the next
// decision because of this (BLOCKED) change, if
// stop-on-block is enabled.
stop_because_blocked = self.settings.stop_on_block;
}
_ => {
fill = ".";
}
}

if !change_is_relevant_at_verbosity(change, self.verbosity) {
if !change_is_relevant_at_verbosity(change, self.verbosity, self.settings.stop_on_block) {
continue;
}

Expand Down Expand Up @@ -429,6 +454,7 @@ pub struct DecisionFormatterBuilder {
solver_to_run: MultiSolverKind,
show_search_space_size: bool,
compare_solvers: bool,
stop_on_block: bool,
}

impl Default for DecisionFormatterBuilder {
Expand All @@ -447,6 +473,7 @@ impl Default for DecisionFormatterBuilder {
solver_to_run: MultiSolverKind::Unchanged,
show_search_space_size: false,
compare_solvers: false,
stop_on_block: false,
}
}
}
Expand Down Expand Up @@ -535,6 +562,11 @@ impl DecisionFormatterBuilder {
self
}

pub fn with_stop_on_block(&mut self, enable: bool) -> &mut Self {
self.stop_on_block = enable;
self
}

pub fn build(&self) -> DecisionFormatter {
let too_long_seconds = if self.verbosity_increase_seconds == 0
|| (self.verbosity_increase_seconds > self.timeout && self.timeout > 0)
Expand Down Expand Up @@ -575,6 +607,7 @@ impl DecisionFormatterBuilder {
solver_to_run: self.solver_to_run.clone(),
show_search_space_size: self.show_search_space_size,
compare_solvers: self.compare_solvers,
stop_on_block: self.stop_on_block,
},
}
}
Expand Down Expand Up @@ -634,6 +667,7 @@ pub(crate) struct DecisionFormatterSettings {
pub(crate) solver_to_run: MultiSolverKind,
pub(crate) show_search_space_size: bool,
pub(crate) compare_solvers: bool,
pub(crate) stop_on_block: bool,
}

enum LoopOutcome {
Expand Down Expand Up @@ -723,6 +757,7 @@ impl DecisionFormatter {
solver_to_run: MultiSolverKind::Unchanged,
show_search_space_size: false,
compare_solvers: false,
stop_on_block: false,
},
}
}
Expand Down Expand Up @@ -1089,16 +1124,21 @@ impl DecisionFormatter {
self.send_sentry_warning_message(
&runtime.solver,
solve_time,
if mesg.contains("by user") {
if mesg.contains("by user") || mesg.contains("--stop-on-block") {
SentryWarning::SolverInterruptedByUser
} else {
SentryWarning::SolverInterruptedByTimeout
},
);

output_location.output_message(format!("{}", mesg.yellow()));
output_location
.output_message(self.format_solve_stats(&runtime.solver, solve_time));
// Show the solver stats after an interruption, unless
// it was due to being BLOCKED with stop-on-block
// being set without report-time also being set.
if !self.settings.stop_on_block || self.settings.report_time {
output_location
.output_message(self.format_solve_stats(&runtime.solver, solve_time));
}

if self.settings.show_search_space_size {
// This solution is likely to be partial, empty,
Expand Down

0 comments on commit 663665b

Please sign in to comment.