--- /dev/null
+path_status PS P
+is_directory PS
+is_file PS
+perms PS P
+
+fact_type path_status DX::Lib::FS::Fact::PathStatus path
+
+observe path_status DX::Lib::FS::Observation::PathStatus
+
+constraint is_directory { $_[0]->has_info and $_[0]->info->is_directory }
+constraint is_file { $_[0]->has_info and $_[0]->info->is_file }
--- /dev/null
+ [ path_status => [ qw(PathStatus Path) ],
+ [ member_lookup => qw(PathStatus path_status path Path) ] ],
+ [ path_status => [ qw(PathStatus Path) ],
+ [ observe => qw(PathStatus path_status DX::Lib::FS::Observation::PathStatus path Path) ],
+ [ member_lookup => qw(PathStatus path_status path Path) ] ],
+ [ is_directory => [ 'PS' ],
+ [ constrain => [ 'PS' ], sub { $_[0]->has_info and $_[0]->info->is_directory } ] ],
+ [ is_file => [ 'PS' ],
+ [ constrain => [ 'PS' ], sub { $_[0]->has_info and $_[0]->info->is_file } ] ],
+ [ directory_at => [ qw(D P) ],
+ [ call => path_status => qw(D P) ],
+ [ call => is_directory => 'D' ] ],
+
--- /dev/null
+is_directory D
+ expr { $_{D}->is_directory }
+
+make is_directory D
+ where not exists_path D
+ via Action::MakePath->new(path => $d->path)
+
+make perms PS Mode
+ where creating PS Action
+ via derive Action { mode => $Mode }
--- /dev/null
+rule my_config_dir D {
+ on 'localhost' {
+ directory_at D '.keymangler'
+ }
+}
+
+rule my_config_file F Name {
+ exists D { my_config_dir D; file_in D Name F }
+}
+
+rule known_account A {
+ exists F { my_config_file F 'accounts'; contains-line F A }
+}
+
+rule known_key K {
+ exists F { my_config_file F 'keys'; contains-line F K }
+}
+
+rule known_dead D {
+ exists F { my_config_file F 'keys.dead'; contains-line F D }
+}
+
+rule dot_ssh D {
+ directory_at D '.ssh' {
+ mode '0755'
+ }
+}
+
+rule keys_file_in {D F} {
+ file_in D 'authorized_keys' {
+ mode '0644'
+ }
+}
+
+rule keys_file F { exists D { dot_ssh D; keys_file_in D F } }
+
+rule key_installed K {
+ exists F {
+ keys_file F
+ contains_line F K
+ }
+}
+
+rule key_not_installed K {
+ not exists F { keys_file F }
+}
+
+rule key_not_installed K {
+ given F { keys_file F } {
+ not_contains_line F K
+ }
+}
+
+action sync_account A {
+ on A {
+ forall K { known_key K } { ensure key_installed K }
+ forall D { known_dead D } { ensure key_not_installed D }
+ }
+}
+
+action sync {
+ forall A { known_account A } {
+ sync_account A
+ }
+}
+
+action installed_on A {
+ on A {
+ forall K { key_installed K } { print K }
+ }
+}
+
+action unknown_installed_on A {
+ on A {
+ forall K { key_installed K; not known_key K } { print K }
+ }
+}
--- /dev/null
+command learn {
+ command key K {
+ ensure { known_key K }
+ }
+ command dead D {
+ ensure { known_dead D }
+ }
+ command account A {
+ ensure { known_account A }
+ }
+}
+
+command forget {
+ command key K {
+ ensure { not_known_key K }
+ }
+ command dead D {
+ ensure { not_known_dead D }
+ }
+ command account A {
+ ensure { not_known_account A }
+ }
+}
+
+command list {
+ command keys {} {
+ query* { known_key K } { puts $K }
+ }
+ command dead {} {
+ query* { known_dead D } { puts $D }
+ }
+ command accounts {} {
+ query* { known_account A } { puts $A }
+ }
+}
+
+command sync {} { ensure all_synchronized }
+
+command sync A { ensure { account_synchronized A } }
+
+command status {} {
+ query* {
+ known_account A
+ findall Known K { known_installed_on A K }
+ findall Unknown U { unknown_installed_on A U }
+ findall Dead D { dead_installed_on A D }
+ } {
+ puts "Host: $A"
+ foreach k $Known { puts "Known: $k" }
+ foreach u $Unknown { puts "Unknown: $u" }
+ foreach d $Dead { puts "Dead: $d" }
+ }
+}