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