Beagle
view release on metacpan or search on metacpan
lib/Beagle/Util.pm view on Meta::CPAN
coerce 'Bool' => from 'Ref' => via { 1 };
enum 'BeagleBackendType' => [qw/git fs/];
enum 'BeagleFormat' => [qw/plain markdown wiki pod html/];
enum 'BeagleLayout' => [qw/blog plain/];
enum 'BeagleTheme' => [qw/orange blue dark/];
our %ABBREV = map { $_ => 1 } qw/isbn/;
our (
$ROOT, $KENNEL, $CACHE,
$DEVEL, %SHARE_ROOT, @SPREAD_TEMPLATE_ROOTS,
@WEB_TEMPLATE_ROOTS, $RELATION_PATH, $MARKS_PATH,
$CACHE_ROOT, $BACKENDS_ROOT, $WEB_OPTIONS, $WEB_ALL,
@PLUGINS, $SEARCHED_PLUGINS, @PO_ROOTS, $HANDLES,
@WEB_NAMES, $SEARCHED_WEB_NAMES, $WEB_ADMIN, @SYSTEM_ROOTS,
$CURRENT_USER,
);
BEGIN {
# I got error: "Goto undefined subroutine &die" on windows strawberry 5.12.2
# &CORE::die doesn't help
*CORE::GLOBAL::die = sub {
# goto &die unless ( caller() )[0] =~ /^Beagle::/;
return die @_ unless ( caller() )[0] =~ /^Beagle::/;
@_ = map { encode( locale => $_ ) } @_;
return confess @_ if enabled_devel();
# we want to show user the line info if there is nothing to print
push @_, newline() if @_;
@_ = grep { defined } @_;
die @_;
};
*CORE::GLOBAL::warn = sub {
# interesting, I get warn if use goto &warn:
# Goto undefined subroutine &Beagle::Util::warn
# goto &warn unless (caller())[0] =~ /^Beagle::/;
return warn @_ unless ( caller() )[0] =~ /^Beagle::/;
@_ = grep { defined } @_;
# we want to show user the line info if there is nothing to print
push @_, newline() if @_;
@_ = map { encode( locale => $_ ) } @_;
warn @_;
};
}
our @EXPORT = (
@Beagle::Helper::EXPORT, qw/
enabled_devel enable_devel disable_devel enabled_cache enable_cache disable_cache
set_current_root current_root root_name set_current_root_by_name check_root
static_root kennel user_alias roots set_roots
core_config set_core_config set_user_alias relation set_relation
default_format split_id root_name name_root root_type
system_alias create_backend alias aliases resolve_id die_entry_not_found
die_entry_ambiguous current_handle handles resolve_entry
is_in_range parse_wiki parse_markdown parse_pod
whitelist set_whitelist
detect_roots backends_root cache_root
share_root marks set_marks
spread_template_roots web_template_roots
entry_type_info entry_types
relation_path marks_path
web_options tweak_name plugins po_roots
web_all web_names web_admin
system_roots current_user
/
);
$DEVEL =
defined $ENV{BEAGLE_DEVEL} && length $ENV{BEAGLE_DEVEL}
? ( $ENV{BEAGLE_DEVEL} ? 1 : 0 )
: ( exists core_config()->{devel} ? core_config()->{devel} : 1 );
sub enabled_devel {
return $DEVEL ? 1 : 0;
}
sub enable_devel {
$DEVEL = 1;
}
sub disable_devel {
undef $DEVEL;
return 1;
}
$CACHE =
defined $ENV{BEAGLE_CACHE} && length $ENV{BEAGLE_CACHE}
? ( $ENV{BEAGLE_CACHE} ? 1 : 0 )
: ( exists core_config()->{cache} ? core_config()->{cache} : 1 );
sub enabled_cache {
return $CACHE ? 1 : 0;
}
sub enable_cache {
$CACHE = 1;
}
sub disable_cache {
undef $CACHE;
return 1;
}
sub spread_template_roots {
return @SPREAD_TEMPLATE_ROOTS if @SPREAD_TEMPLATE_ROOTS;
@SPREAD_TEMPLATE_ROOTS = ();
if ( $ENV{BEAGLE_SPREAD_TEMPLATE_ROOTS} ) {
push @SPREAD_TEMPLATE_ROOTS, split /\s*,\s*/,
decode( locale => $ENV{BEAGLE_SPREAD_TEMPLATE_ROOTS} );
}
if ( core_config()->{spread_template_roots} ) {
lib/Beagle/Util.pm view on Meta::CPAN
}
}
}
if ( core_config()->{po_roots} ) {
push @PO_ROOTS, split /\s*,\s*/,
core_config()->{po_roots};
}
if ( $ENV{BEAGLE_PO_ROOTS} ) {
push @PO_ROOTS, split /\s*,\s*/,
decode( locale(), $ENV{BEAGLE_PO_ROOTS} );
}
@PO_ROOTS = uniq @PO_ROOTS;
return @PO_ROOTS;
}
sub set_current_root {
my $dir;
if (@_) {
$dir = shift;
die "set_current_root is called with an undef value"
unless defined $dir;
}
else {
$dir = decode( locale => $ENV{BEAGLE_ROOT} || '' );
if ( !$dir && length $ENV{BEAGLE_NAME} ) {
my $roots = roots();
my $b = $roots->{ decode( locale => $ENV{BEAGLE_NAME} ) };
$dir = $b->{local} if $b && $b->{local};
}
$dir ||= core_config()->{default_root};
if ( !$dir && length core_config()->{default_name} ) {
my $roots = roots();
my $b = $roots->{ core_config()->{default_name} };
$dir = $b->{local} if $b && $b->{local};
}
}
die
"couldn't find backend root, please specify env BEAGLE_NAME or BEAGLE_ROOT"
unless $dir;
$dir = rel2abs($dir);
if ( check_root($dir) ) {
return $ROOT = $dir;
}
else {
die "$dir is invalid backend root";
}
}
sub current_root {
return $ROOT if defined $ROOT;
my $not_die = shift;
eval { set_current_root() };
if ( $@ && !$not_die ) {
die $@;
}
return $ROOT if $ROOT;
return;
}
sub set_current_root_by_name {
my $name = shift or die 'need name';
return set_current_root( name_root($name) );
}
sub check_root {
my $dir = encode( locale_fs => $_[-1] );
return unless $dir && -d $dir;
my $info = catfile( $dir, 'info' );
if ( -e $info ) {
open my $fh, '<', $info or die $!;
local $/;
my $content = <$fh>;
if ( $content && $content =~ /id:/ ) {
return 1;
}
}
return;
}
sub static_root {
my $handle = shift;
return catdir( ( $handle ? $handle->root : current_root() ),
'attachments' );
}
sub kennel {
return $KENNEL if $KENNEL;
if ( $ENV{BEAGLE_KENNEL} ) {
$KENNEL = decode( locale => $ENV{BEAGLE_KENNEL} );
}
else {
$KENNEL = catdir( user_home, '.beagle' );
}
return $KENNEL;
}
sub cache_root {
return $CACHE_ROOT if $CACHE_ROOT;
if ( $ENV{BEAGLE_CACHE_ROOT} ) {
$CACHE_ROOT = decode( locale => $ENV{BEAGLE_CACHE_ROOT} );
}
else {
$CACHE_ROOT = core_config()->{cache_root}
|| catfile( kennel(), 'cache' );
}
return $CACHE_ROOT;
}
sub backends_root {
return $BACKENDS_ROOT if $BACKENDS_ROOT;
if ( $ENV{BEAGLE_BACKENDS_ROOT} ) {
$BACKENDS_ROOT = decode( locale => $ENV{BEAGLE_BACKENDS_ROOT} );
lib/Beagle/Util.pm view on Meta::CPAN
my $name = $opt{'name'};
my $email = $opt{'email'};
if ($name) {
$git->config( '--add', 'user.name', $name );
}
if ($email) {
$git->config( '--add', 'user.email', $email );
}
_create_backend_fs( %opt, root => $git->root );
$git->add('.');
$git->commit( '-m' => "init beagle $name" );
if ( $opt{bare} ) {
$git->push( 'origin', 'master' );
}
return 1;
}
sub alias {
return { %{ system_alias() }, %{ user_alias() } };
}
sub aliases {
return keys %{ alias() };
}
sub resolve_entry {
my $str = shift or return;
return resolve_id( $str, @_ ) if $str =~ /^[a-z0-9]+$/;
return unless $str =~ s/^://;
my %opt = ( handle => undef, @_ );
require Beagle::Handle;
my @bh;
if ( $opt{handle} ) {
push @bh, $opt{handle};
}
else {
my $all = roots();
@bh = map { Beagle::Handle->new( root => $all->{$_}{local} ) }
keys %{$all};
}
my @found;
for my $bh (@bh) {
for my $entry ( @{ $bh->entries } ) {
if ( $entry->serialize( id => 1 ) =~ qr/$str/im ) {
push @found,
{ id => $entry->id, entry => $entry, handle => $bh };
}
}
}
return @found;
}
sub die_not_found {
my $str = shift;
die "no such entry match $str";
}
sub resolve_id {
my $i = shift or return;
my %opt = ( handle => undef, @_ );
my $bh = $opt{'handle'};
require Beagle::Handle;
if ($bh) {
my @ids = grep { /^$i/ } keys %{ $bh->map };
return
map { { id => $_, entry => $bh->map->{$_}, handle => $bh } } @ids;
}
else {
my $relation = relation;
my @ids = grep { /^$i/ } keys %$relation;
my @ret;
for my $i (@ids) {
my $root = name_root( $relation->{$i} );
my $bh = Beagle::Handle->new( root => $root );
push @ret, { id => $i, entry => $bh->map->{$i}, handle => $bh };
}
return @ret;
}
}
sub die_entry_not_found {
my $i = shift;
die "no such entry matching $i";
}
sub die_entry_ambiguous {
my $i = shift;
my @items = @_;
my @out = "ambiguous '$i':";
for my $item (@items) {
push @out, join( ' ', $item->{id}, $item->{entry}->summary(10) );
}
die join newline(), @out;
}
sub current_handle {
my $root = current_root('not die');
require Beagle::Handle;
if ($root) {
return Beagle::Handle->new( root => $root, @_ );
}
return;
}
sub handles {
return $HANDLES if $HANDLES;
my $all = roots();
require Beagle::Handle;
$HANDLES = {
map { $_ => Beagle::Handle->new( root => $all->{$_}{local} ) }
keys %$all
};
return $HANDLES;
}
sub is_in_range {
my ( $entry, %limit ) = @_;
my $created = $entry->created;
my $updated = $entry->updated;
# if on the exact epoch, before doesn't include the point, after does
return if $limit{'created_before'} && $created >= $limit{'created_before'};
return if $limit{'created_after'} && $created < $limit{'created_after'};
return if $limit{'updated_before'} && $updated >= $limit{'updated_before'};
return if $limit{'updated_after'} && $updated < $limit{'updated_after'};
return 1;
}
my $whitelist = whitelist() || [];
use HTML::Defang;
my $defang = HTML::Defang->new(
fix_mismatched_tags => 1,
url_callback => sub {
my ( $self, $defang, $tag, $key, $val ) = @_;
if ( $tag eq 'a' && $key eq 'href' && $$val && $$val =~ /^http/ ) {
require URI;
my $uri = URI->new($$val);
my $host = $uri->host;
( run in 1.155 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )