# Copyright (c) 2023 Yuki Kimoto
# MIT License
class File::Path {
version "0.015";
use Hash;
use StringList;
use Sys::IO;
use File::Basename;
use File::Spec;
static method mkpath : int ($path : string, $options : object[] = undef) {
unless ($path) {
die "The \$path must be defined";
}
unless (length $path >= 0) {
die "The length of \$path must be greater than or equal to 0";
}
my $options_h = Hash->new($options);
my $mode = $options_h->get_or_default("mode", -1)->(int);
if ($mode < 0) {
$mode = 0777;
}
my $created = 0;
&_mkpath_recursive($path, \$created, $mode);
return $created;
}
private static method _mkpath_recursive : void ($path : string, $created_ref : int*, $mode : int) {
unless (Sys->d($path)) {
my $parent = File::Basename->dirname($path);
unless (Sys->d($parent) || $path eq $parent ) {
&_mkpath_recursive($parent, $created_ref, $mode);
}
Sys::IO->mkdir($path, $mode);
$$created_ref++;
}
}
static method make_path : int ($path : string, $options : object[] = undef) {
return &mkpath($path, $options);
}
static method rmtree : int ($path : string, $options : object[] = undef) {
unless ($path) {
die "The \$path must be defined";
}
unless (length $path >= 0) {
die "The length of \$path must be greater than or equal to 0";
}
my $options_h = Hash->new($options);
my $keep_root = $options_h->get_or_default("keep_root", 0)->(int);
my $removed_count = 0;
&_rmtree_recursive($path, $path, \$removed_count, $keep_root);
return $removed_count;
}
private static method _rmtree_recursive : void ($root : string, $path : string, $removed_count_ref : int*, $keep_root : int) {
my $curdir = File::Spec->curdir;
my $updir = File::Spec->updir;
if (Sys->d($path)) {
my $dh = Sys::IO->opendir($path);
my $file_base_names_list = StringList->new;
while (my $dir_ent = Sys::IO->readdir($dh)) {
my $file_base_name = $dir_ent->d_name;
if ($file_base_name eq $updir) {
next;
}
if ($file_base_name eq $curdir) {
next;
}
$file_base_names_list->push($file_base_name);
}
if ($file_base_names_list->length > 0) {
my $file_base_names = $file_base_names_list->to_array;
for my $file_base_name (@$file_base_names) {
my $child_dir = "$path/$file_base_name";
&_rmtree_recursive($root, $child_dir, $removed_count_ref, $keep_root);
}
}
my $not_remove = 0;
if ($keep_root && $path eq $root) {
$not_remove = 1;
}
unless ($not_remove) {
Sys::IO->rmdir($path);
$$removed_count_ref++;
}
}
else {
Sys::IO->unlink($path);
$$removed_count_ref++;
}
}
static method remove_tree : int ($path : string, $options : object[] = undef) {
return &rmtree($path, $options);
}
}