From: Matt S Trout Date: Tue, 11 Feb 2014 19:54:12 +0000 (+0000) Subject: move actions to being held by fact objects X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=9c7b21a2890cf03752016d4bd98361c9e9020b86;p=scpubgit%2FDKit.git move actions to being held by fact objects --- diff --git a/lib/DX/Op/ProposeAction.pm b/lib/DX/Op/ProposeAction.pm index 2249496..b1aa7f3 100644 --- a/lib/DX/Op/ProposeAction.pm +++ b/lib/DX/Op/ProposeAction.pm @@ -22,13 +22,9 @@ sub run { my $action = $self->builder->(map $state->resolve_value($_), @vars) ->but(dependencies => \@deps); my ($fact_type, $value) = $action->expected_effect; - my $id = $vars[0]->id; - my $var = $state->by_id->{$id}->with_action($action); - my $fact_set = $state->facts->{$fact_type}->with_value($value); - $state->but( - by_id => { %{$state->by_id}, $id => $var }, - facts => { %{$state->facts}, $fact_type => $fact_set }, - ) + my $final_value = $value->but(required_action => $action); + my $fact_set = $state->facts->{$fact_type}->with_value($final_value); + $state->but(facts => { %{$state->facts}, $fact_type => $fact_set }) ->then($self->next); } diff --git a/lib/DX/RefSet.pm b/lib/DX/RefSet.pm new file mode 100644 index 0000000..58827cb --- /dev/null +++ b/lib/DX/RefSet.pm @@ -0,0 +1,19 @@ +package DX::RefSet; + +use DX::FactRef; +use DX::ArrayStream; +use Moo; + +has target => (is => 'ro', required => 1); + +has names => (is => 'ro', required => 1); + +sub to_stream { + my ($self) = @_; + return DX::ArrayStream->from_array( + map DX::FactRef->new(fact_type => $self->target, fact_id => $_), + @{$self->names} + ); +} + +1; diff --git a/lib/DX/Result.pm b/lib/DX/Result.pm index 85d6774..ddfb626 100644 --- a/lib/DX/Result.pm +++ b/lib/DX/Result.pm @@ -1,5 +1,6 @@ package DX::Result; +use Safe::Isa; use Moo; has _state => (is => 'ro', required => 1, init_arg => 'state'); @@ -10,8 +11,13 @@ sub var_names { sub actions { my ($self) = @_; + my $state = $self->_state; my $by_id = $self->_state->by_id; - return map $_->action, grep $_->has_action, values %$by_id; + return map $_->required_action, + grep $_->has_required_action, + grep $_->$_does('DX::Role::Fact'), + map $state->resolve_value($_), + values %$by_id; } sub independent_actions { diff --git a/lib/DX/Role/Action.pm b/lib/DX/Role/Action.pm new file mode 100644 index 0000000..113dd44 --- /dev/null +++ b/lib/DX/Role/Action.pm @@ -0,0 +1,22 @@ +package DX::Role::Action; + +use Moo::Role; + +has dependencies => (is => 'ro', default => sub { [] }); + +has was_run => (is => 'rw'); + +requires 'expected_effect'; +requires '_do_run'; + +sub but { my ($self, @but) = @_; ref($self)->new(%$self, @but); } + +sub run { + my ($self) = @_; + die "Can't run, was already run" if $self->was_run; + my @res = $self->_do_run; + $self->was_run(1); + return @res; +} + +1; diff --git a/lib/DX/Role/Fact.pm b/lib/DX/Role/Fact.pm new file mode 100644 index 0000000..33a8287 --- /dev/null +++ b/lib/DX/Role/Fact.pm @@ -0,0 +1,9 @@ +package DX::Role::Fact; + +use Moo::Role; + +has required_action => (is => 'ro', predicate => 1); + +sub but { ref($_[0])->new(%{$_[0]}, @_[1..$#_]) } + +1; diff --git a/lib/DX/Role/Ref.pm b/lib/DX/Role/Ref.pm new file mode 100644 index 0000000..3e4f8f2 --- /dev/null +++ b/lib/DX/Role/Ref.pm @@ -0,0 +1,7 @@ +package DX::Role::Ref; + +use Moo::Role; + +requires 'resolve'; + +1; diff --git a/lib/DX/State.pm b/lib/DX/State.pm index 1f84991..2f0e2b0 100644 --- a/lib/DX/State.pm +++ b/lib/DX/State.pm @@ -187,7 +187,9 @@ sub action_dependencies { my @queue = @ids; while (my $id = shift @queue) { $seen{$id}++; - push @found, $id if $by_id->{$id}->has_action; + my $value = $self->resolve_value($by_id->{$id}); + push @found, $id if $value->$_does('DX::Role::Fact') + and $value->has_required_action; push @queue, grep !$seen{$_}, keys %{$deps->{$id}}; } return @found; diff --git a/lib/DX/Var.pm b/lib/DX/Var.pm index f2c11dd..3904186 100644 --- a/lib/DX/Var.pm +++ b/lib/DX/Var.pm @@ -22,8 +22,6 @@ has bound_value => (is => 'lazy', predicate => 1, clearer => 1, builder => sub { return; }); -has action => (is => 'ro', predicate => 1); - sub is_bound { my ($self) = @_; $self->has_bound_value || $self->has_bound_stream || $self->has_root_set; @@ -39,11 +37,6 @@ sub with_value { $self->new(%$self, bound_value => $stream); } -sub with_action { - my ($self, $action) = @_; - $self->new(%$self, action => $action); -} - sub with_root_set { my ($self, $set) = @_; $self->new(%$self, root_set => $set); diff --git a/t/dot_ssh.t b/t/dot_ssh.t index b06771c..1ac8b04 100644 --- a/t/dot_ssh.t +++ b/t/dot_ssh.t @@ -12,6 +12,8 @@ use Test::Exception; use Moo; + with 'DX::Role::Fact'; + has path => (is => 'ro', required => 1); has info => (is => 'ro', predicate => 1); @@ -19,6 +21,8 @@ use Test::Exception; use Moo; + with 'DX::Role::Fact'; + has is_directory => (is => 'ro', default => 0); has is_file => (is => 'ro', default => 0); has mode => (is => 'ro', required => 1);