#!/usr/bin/env perl
# Copyright (c) 2015-2020 Christian Jaeger, copying@christianjaeger.ch
# This is free software. See the file COPYING.md that came bundled
# with this file.
use strict;
use warnings FATAL => 'uninitialized';
use experimental "signatures";
# find modules from functional-perl working directory (not installed)
use Cwd 'abs_path';
our ($mydir, $myname);
BEGIN {
my $location = (-l $0) ? abs_path($0) : $0;
$location =~ /(.*?)([^\/]+?)_?\z/s or die "?";
($mydir, $myname) = ($1, $2);
}
use lib "$mydir/../lib";
sub usage {
print "usage: rootdir
Print all directories below rootdir that follow the Maildir or
";
exit 1;
}
our $verbose = 0;
GetOptions("verbose" => \$verbose, "help" => sub {usage},) or exit 1;
usage unless @ARGV == 1;
my ($rootdir) = @ARGV;
use FP::IOStream qw(perhaps_directory_paths);
use FP::Stream qw(stream_fold_right);
use FP::List qw(list cons null);
use Chj::xperlfunc qw(xlstat xprintln);
use FP::Ops qw(the_method);
use FP::fix qw(fixn);
# This is a work in progress. Doing things functionally here doesn't
# really make sense until it's at a point where reading the filesystem
# is a functionally combinable "framework".
# ---- failure objects -------------------------------------------------
# XX: provide these kinds of failure objects globally (and return them
# instead of using functions named perhaps_*)?
{
use FP::Struct ["path", "message"];
sub xprintln($self) {
print STDERR $self->path, ": ", $self->message, "\n"
}
_END_
}
{
use FP::Struct ["path"];
sub xprintln($self) {
print STDOUT $self->path, "\n" or die $!;
}
_END_
}
# ---- the tests --------------------------------------------------------
# XX is there a better way to test for a Git directory?
my $is_gitdir_subdirs = list qw(refs branches objects info); # hooks ?
sub is_gitdir($path) {
$path =~ /\.git\z/ and $is_gitdir_subdirs->all(sub { -d "$path/$_[0]" })
}
sub is_maildir($path) { (-d "$path/cur" and -d "$path/new" and -d "$path/tmp") }
sub is_maildir_plusplus_subfolder($path) {
-f "$path/maildirfolder" and is_maildir $path
}
# ---- tree folding -----------------------------------------------------
sub find_below ($path, $pred) {
my ($fold_path, $fold_dirpath) = fixn(
fun($fold_path, $fold_dirpath, $path, $rest)
{
my $s = xlstat $path; # XX: replace with one returning failure
# objects, too (for cases where the
# filesystem is modified between the readdir
# and stat)
if ($s->is_dir) {
if (&$pred($path)) {
cons(find_maildirs::Success->new($path), $rest)
} else {
&$fold_dirpath($path, $rest)
}
} else {
$rest
}
},
fun($fold_path, $fold_dirpath, $path, $rest) {
if (my ($s) = perhaps_directory_paths($path)) {
stream_fold_right($fold_path, $rest, $s)
} else {
cons(find_maildirs::Failure->new($path, "$!"), $rest)
}
}
);
&$fold_dirpath($path, null)
}
#use FP::Repl::Trap; # or Chj::Backtrace
#use FP::Repl;repl;
my $s = find_below($rootdir, \&is_maildir);
$s->for_each(the_method "xprintln");