create directory and create file, now with mode setting
Matt S Trout [Fri, 14 Feb 2014 07:28:26 +0000 (07:28 +0000)]
lib/DX/Lib/FS.pm
lib/DX/Lib/FS/Action/CreateDirectory.pm
lib/DX/Lib/FS/Action/CreateFile.pm

index a11622f..220daec 100644 (file)
@@ -8,6 +8,8 @@ use DX::SetOver;
 use Moo;
 
 our @RULES = (
+  [ has_action => [ qw(Thing Action) ],
+    [ prop => 'Thing', \'required_action', 'Action' ] ],
   [ path_status => [ qw(PS) ],
     [ member_of => 'PS', \'path_status' ] ],
   [ path => [ qw(PS P) ],
@@ -72,6 +74,20 @@ our @RULES = (
       [ exists => [ qw(FilePath) ],
         [ catfile => qw(DirPath FileName FilePath) ],
         [ file_at => qw(FileStatus FilePath) ] ] ] ],
+  [ mode => [ qw(PS M) ],
+    [ exists => [ qw(A) ],
+      [ has_action => qw(PS A) ],
+      [ does => 'A', \'DX::Lib::FS::Action::CreateDirectory' ],
+      [ react => [ qw(PS M) ], sub {
+          $_[0]->but(mode => $_[1]);
+        } ] ] ],
+  [ mode => [ qw(PS M) ],
+    [ exists => [ qw(A) ],
+      [ has_action => qw(PS A) ],
+      [ does => 'A', \'DX::Lib::FS::Action::CreateFile' ],
+      [ react => [ qw(PS M) ], sub {
+          $_[0]->but(mode => $_[1]);
+        } ] ] ],
 );
 
 sub load_into {
@@ -95,7 +111,7 @@ sub load_into {
     catfile => [ qw(DirPath FileName FilePath) ],
       [ qw(+ + -) ] => sub {
         my ($vol, $dir) = File::Spec->splitpath($_{DirPath}, 1);
-        my $file_path = File::Spec->catpath($vol, $dir, $_{FilePath});
+        my $file_path = File::Spec->catpath($vol, $dir, $_{FileName});
         +(FilePath => [ value => $file_path ])
       },
       [ qw(- - +) ] => sub {
@@ -104,6 +120,10 @@ sub load_into {
         +(DirPath => [ value => $dir_path ], FileName => [ value => $file ])
       }
   );
+  $solver->add_rule(
+    does => [ qw(Thing RoleName) ],
+      [ constrain => [ qw(Thing RoleName) ], sub { $_[0]->DOES($_[1]) } ]
+  );
   $solver->add_rule(@$_) for @RULES;
 }
 
index ef11a20..5fcdef3 100644 (file)
@@ -8,17 +8,29 @@ with 'DX::Role::Action';
 
 has path => (is => 'ro', required => 1);
 
+has mode => (is => 'ro', predicate => 1);
+
 sub expected_effect {
   my ($self) = @_;
   return +(path_status => PathStatus->new(
     path => $self->path,
-    info => PathStatusInfo->new(is_directory => 1, mode => '')
+    info => PathStatusInfo->new(
+      is_directory => 1,
+      mode => ($self->has_mode ? $self->mode : '')
+    )
   ));
 }
 
 sub _do_run {
   my ($self) = @_;
-  mkdir($self->path) or die "Couldn't mkdir ${\$self->path}: $!";
+  if ($self->has_mode) {
+    my $umask = umask(0000);
+    mkdir($self->path, oct($self->mode))
+      or do { umask($umask); die "Couldn't mkdir ${\$self->path}: $!" };
+    umask($umask);
+  } else {
+    mkdir($self->path) or die "Couldn't mkdir ${\$self->path}: $!";
+  }
   +(path_status => PathStatus->new(path => $self->path));
 }
 
index 80379e3..feed8f7 100644 (file)
@@ -2,23 +2,38 @@ package DX::Lib::FS::Action::CreateFile;
 
 use aliased 'DX::Lib::FS::Fact::PathStatus';
 use aliased 'DX::Lib::FS::Fact::PathStatusInfo';
+use POSIX ();
 use Moo;
 
 with 'DX::Role::Action';
 
 has path => (is => 'ro', required => 1);
 
+has mode => (is => 'ro', predicate => 1);
+
 sub expected_effect {
   my ($self) = @_;
   return +(path_status => PathStatus->new(
     path => $self->path,
-    info => PathStatusInfo->new(is_file => 1, mode => '')
+    info => PathStatusInfo->new(
+      is_file => 1,
+      mode => ($self->has_mode ? $self->mode : '')
+    )
   ));
 }
 
 sub _do_run {
   my ($self) = @_;
-  open my $fh, '>>', $self->path or die "Couldn't create ${\$self->path}: $!";
+  if ($self->has_mode) {
+    my $umask = umask(0000);
+    my $fd = POSIX::open(
+      $self->path, POSIX::O_CREAT | POSIX::O_RDONLY, oct($self->mode)
+    ) or do { umask($umask); die "Couldn't create ${\$self->path}: $!" };
+    POSIX::close($fd);
+    umask($umask);
+  } else {
+    open my $fh, '>>', $self->path or die "Couldn't create ${\$self->path}: $!";
+  }
   +(path_status => PathStatus->new(path => $self->path));
 }