move the actual doing stuff code for FS lib into a Guts.pm
[scpubgit/DKit.git] / lib / DX / Lib / FS.pm
CommitLineData
4d2ad771 1package DX::Lib::FS;
2
3use DX::Lib::FS::Observation::PathStatus;
4use DX::Lib::FS::Action::CreateDirectory;
5use DX::Lib::FS::Action::CreateFile;
ae75ed8b 6use DX::Lib::FS::Action::SetPathMode;
8c3eab7b 7use DX::Lib::FS::Observation::FileContent;
8use DX::Lib::FS::Action::RewriteFile;
4d2ad771 9use File::Spec;
10use DX::SetOver;
11use Moo;
12
13our @RULES = (
14 [ path_status => [ qw(PS) ],
15 [ member_of => 'PS', \'path_status' ] ],
dd866f63 16
17 [ _path_status_at => [ qw(PS P) ],
4d2ad771 18 [ path_status => 'PS' ],
dd866f63 19 [ prop => PS => \'path' => 'P' ] ],
20
21 [ path_status_at => [ qw(PS P) ],
22 [ _path_status_at => qw(PS P) ],
4d2ad771 23 [ 'cut' ] ],
dd866f63 24
4d2ad771 25 [ path_status_at => [ 'PS', 'P' ],
26 [ observe => [ 'P' ], sub {
27 DX::Lib::FS::Observation::PathStatus->new(
28 path => $_[0]
29 )
30 } ],
dd866f63 31 [ _path_status_at => qw(PS P) ] ],
32
33 [ ps_prop => [ 'P', 'Name', 'Value' ],
1ca2da5e 34 [ path_status_at => qw(PS P) ],
35 [ prop => qw(PS Name Value) ] ],
dd866f63 36
37 [ ps_info_prop => [ 'P', 'Name', 'Value' ],
1ca2da5e 38 [ ps_prop => 'P', \'info', 'PSI' ],
39 [ prop => 'PSI', 'Name', 'Value' ] ],
dd866f63 40
41 [ exists_path => [ qw(P) ],
1ca2da5e 42 [ ps_prop => 'P' => \'info' => 'PSI' ] ],
dd866f63 43
44 [ _is_directory => [ qw(P) ],
45 [ ps_info_prop => 'P' => \'is_directory' => \1 ] ],
46
47 [ is_directory => [ qw(P) ],
48 [ _is_directory => 'P' ] ],
49
50 [ _is_file => [ qw(P) ],
51 [ ps_info_prop => 'P' => \'is_file' => \1 ] ],
52
53 [ is_file => [ qw(P) ],
54 [ _is_file => 'P' ] ],
55
56 [ _mode => [ qw(P M) ],
57 [ ps_info_prop => 'P' => \'mode' => 'M' ] ],
58
59 [ mode => [ qw(P M) ],
60 [ _mode => qw(P M) ] ],
61
62 [ is_directory => [ 'Path' ],
63 [ not => [ _is_directory => 'Path' ] ],
64 [ act => [ 'Path' ], sub {
4d2ad771 65 DX::Lib::FS::Action::CreateDirectory->new(
dd866f63 66 path => $_[0],
4d2ad771 67 )
dd866f63 68 } ],
69 [ _is_directory => 'Path' ] ],
70
71 [ is_file => [ 'Path' ],
72 [ not => [ _is_file => 'Path' ] ],
73 [ act => [ 'Path' ], sub {
4d2ad771 74 DX::Lib::FS::Action::CreateFile->new(
dd866f63 75 path => $_[0],
4d2ad771 76 )
dd866f63 77 } ],
78 [ _is_file => 'Path' ] ],
79
80 [ _action_is_creating => [ qw(A) ],
81 [ does => 'A', \'DX::Lib::FS::Action::CreateDirectory' ] ],
82
83 [ _action_is_creating => [ qw(A) ],
84 [ does => 'A', \'DX::Lib::FS::Action::CreateFile' ] ],
85
86 [ mode => [ qw(P M) ],
1ca2da5e 87 [ path_status_at => qw(PS P) ],
88 [ has_action => qw(PS A) ],
89 [ _action_is_creating => 'A' ],
90 [ react => [ qw(PS M) ], sub {
91 $_[0]->but(mode => $_[1]);
92 } ],
dd866f63 93 [ 'cut' ] ],
94
95 [ mode => [ qw(P M) ],
1ca2da5e 96 [ path_status_at => qw(PS P) ],
97 [ not => [ _mode => qw(P M) ] ],
98 [ act => [ qw(PS M) ], sub {
99 DX::Lib::FS::Action::SetPathMode->new(
100 path_status => $_[0], mode => $_[1]
101 )
102 } ],
dd866f63 103 [ 'cut' ] ],
104
8c3eab7b 105 [ file_content => [ qw(FC) ],
106 [ member_of => 'FC', \'file_content' ] ],
dd866f63 107
108 [ _file_content_at => [ qw(FC P) ],
8c3eab7b 109 [ file_content => 'FC' ],
dd866f63 110 [ prop => 'FC', \'path', 'P' ] ],
111
112 [ file_content_at => [ qw(FC P) ],
113 [ _file_content_at => qw(FC P) ],
8c3eab7b 114 [ 'cut' ] ],
dd866f63 115
8c3eab7b 116 [ file_content_at => [ qw(FC P) ],
dd866f63 117 [ is_file => 'P' ],
8c3eab7b 118 [ observe => [ 'P' ], sub {
119 DX::Lib::FS::Observation::FileContent->new(
120 path => $_[0]
121 )
122 } ],
dd866f63 123 [ _file_content_at => qw(FC P) ] ],
124
125 [ fc_prop => [ qw(P Name Value) ],
1ca2da5e 126 [ file_content_at => qw(FC P) ],
127 [ prop => qw(FC Name Value) ] ],
dd866f63 128
129 [ file_data => [ qw(P D) ], [ fc_prop => 'P', \'data', 'D' ] ],
130
131 [ _contains_line => [ qw(P L) ],
132 [ is_file => 'P' ],
1ca2da5e 133 [ fc_prop => 'P', \'lines', 'Lines' ],
134 [ member_of => qw(L Lines) ] ],
dd866f63 135
136 [ contains_line => [ qw(P L) ],
137 [ _contains_line => qw(P L) ] ],
138
139 [ _action_modifying_fc => [ 'A' ],
140 [ does => 'A' => \'DX::Lib::FS::Action::CreateFile' ] ],
141
142 [ _action_modifying_fc => [ 'A' ],
143 [ does => 'A' => \'DX::Lib::FS::Action::RewriteFile' ] ],
144
145 [ contains_line => [ qw(P L) ],
146 [ not => [ _contains_line => qw(P L) ] ],
1ca2da5e 147 [ file_content_at => qw(FC P) ],
148 [ has_action => qw(FC A) ],
149 [ _action_modifying_fc => 'A' ],
150 [ react => [ qw(FC L) ], sub {
151 $_[0]->but_add($_[1])
152 } ],
8c3eab7b 153 [ 'cut' ] ],
dd866f63 154
155 [ contains_line => [ qw(P L) ],
156 [ not => [ _contains_line => qw(P L) ] ],
1ca2da5e 157 [ file_content_at => qw(FC P) ],
158 [ act => [ qw(FC L) ], sub {
159 DX::Lib::FS::Action::RewriteFile->new(
160 from => $_[0],
161 )->but_add($_[1])
162 } ] ],
dd866f63 163
164 [ not_contains_line => [ qw(P L) ],
165 [ not => [ _contains_line => qw(P L) ] ] ],
166
167 [ _arrange_removal_of => [ qw(FC L) ],
1ca2da5e 168 [ has_action => qw(FC A) ],
169 [ does => 'A' => \'DX::Lib::FS::Action::RewriteFile' ],
dd866f63 170 [ react => [ qw(FC L) ], sub { $_[0]->but_remove($_[1]) } ] ],
171
172 [ _arrange_removal_of => [ qw(FC L) ],
8c3eab7b 173 [ act => [ qw(FC L) ], sub {
174 DX::Lib::FS::Action::RewriteFile->new(
175 from => $_[0],
dd866f63 176 )->but_remove($_[1]);
177 } ] ],
178
179 [ not_contains_line => [ qw(P L) ],
180 [ _contains_line => qw(P L) ],
1ca2da5e 181 [ file_content_at => qw(FC P) ],
182 [ _arrange_removal_of => qw(FC L) ],
8c3eab7b 183 [ 'cut' ] ],
dd866f63 184
185 [ file_in => [ qw(DirPath FileName FilePath) ],
186 [ catfile => qw(DirPath FileName FilePath) ],
187 [ is_directory => 'DirPath' ],
188 [ is_file => 'FilePath' ] ],
4d2ad771 189);
190
191sub load_into {
192 my ($self, $solver) = @_;
193 $solver->facts->{path_status} = DX::SetOver->new(over => 'path');
8c3eab7b 194 $solver->facts->{file_content} = DX::SetOver->new(over => 'path');
4d2ad771 195 $solver->add_predicate(
196 catdir => [ qw(DirPath DirName SubDirPath) ],
197 [ qw(+ + -) ] => sub {
198 +(SubDirPath => [
199 value => File::Spec->catdir($_{DirPath}, $_{DirName})
200 ])
201 },
202 [ qw(- - +) ] => sub {
203 my @split = File::Spec->splitdir($_{SubDirPath});
204 my $last = pop @split;
205 my $rest = File::Spec->catdir(@split);
206 +(DirPath => [ value => $rest ], DirName => [ value => $last ])
207 }
208 );
209 $solver->add_predicate(
210 catfile => [ qw(DirPath FileName FilePath) ],
211 [ qw(+ + -) ] => sub {
212 my ($vol, $dir) = File::Spec->splitpath($_{DirPath}, 1);
640fa37e 213 my $file_path = File::Spec->catpath($vol, $dir, $_{FileName});
4d2ad771 214 +(FilePath => [ value => $file_path ])
215 },
216 [ qw(- - +) ] => sub {
217 my ($vol, $dir, $file) = File::Spec->splitpath($_{FilePath});
218 my $dir_path = File::Spec->catpath($vol, $dir);
219 +(DirPath => [ value => $dir_path ], FileName => [ value => $file ])
220 }
221 );
0d1a41d9 222 $solver->add_predicate(
223 path_on => [ qw(On Path FullPath) ],
224 [ qw(+ + -) ] => sub {
225 (my $path = $_{Path}) =~ s/^(:!\/)/.\//;
226 if ($_{On} eq '' or $_{On} eq 'localhost') {
227 (FullPath => [ value => $path ])
228 } else {
229 (FullPath => [ value => join(':', $_{On}, $path) ])
230 }
231 },
232 [ qw(- - +) ] => sub {
233 if (my ($on, $path) = $_{FullPath} =~ /^([^\/]+):(.*)$/) {
234 (On => [ value => $on ], Path => [ value => $path ]);
235 } else {
236 (On => [ value => 'localhost' ], Path => [ value => $_{FullPath} ]);
237 }
238 }
239 );
640fa37e 240 $solver->add_rule(
241 does => [ qw(Thing RoleName) ],
242 [ constrain => [ qw(Thing RoleName) ], sub { $_[0]->DOES($_[1]) } ]
243 );
4d2ad771 244 $solver->add_rule(@$_) for @RULES;
245}
246
2471;