|
|
|
@ -9,7 +9,9 @@ use Mojo::File; |
|
|
|
use MJB::Backend::Jekyll::MarkdownFile; |
|
|
|
use MJB::Backend::Jekyll::MarkdownFile; |
|
|
|
use MJB::Backend::Jekyll::ConfigFile; |
|
|
|
use MJB::Backend::Jekyll::ConfigFile; |
|
|
|
|
|
|
|
|
|
|
|
# The root path for the repositories |
|
|
|
#== |
|
|
|
|
|
|
|
# The path to the directory that will be used to hold the git repositories for each blog blogs. |
|
|
|
|
|
|
|
#== |
|
|
|
has root => ( |
|
|
|
has root => ( |
|
|
|
is => 'ro', |
|
|
|
is => 'ro', |
|
|
|
required => 1, |
|
|
|
required => 1, |
|
|
|
@ -19,30 +21,25 @@ has root => ( |
|
|
|
}, |
|
|
|
}, |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
# The domain name for this jekyll blog |
|
|
|
#== |
|
|
|
|
|
|
|
# The domain name for this specific blog. |
|
|
|
|
|
|
|
#== |
|
|
|
has domain => ( |
|
|
|
has domain => ( |
|
|
|
is => 'ro', |
|
|
|
is => 'ro', |
|
|
|
required => 1, |
|
|
|
required => 1, |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
# The full path to the git repo this is backed by. |
|
|
|
#== |
|
|
|
|
|
|
|
# The full remote path ( i.e. git@foo.com:mjb/domain.com.git) to the git repository that we will push to. |
|
|
|
|
|
|
|
#== |
|
|
|
has repo => ( |
|
|
|
has repo => ( |
|
|
|
is => 'ro', |
|
|
|
is => 'ro', |
|
|
|
required => 1, |
|
|
|
required => 1, |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
has config => ( |
|
|
|
#== |
|
|
|
is => 'lazy', |
|
|
|
# The full local path (i.e. /var/repos/domain.com ) to the git repository that we will execute git commands in. |
|
|
|
); |
|
|
|
#== |
|
|
|
|
|
|
|
|
|
|
|
sub _build_config { |
|
|
|
|
|
|
|
my ( $self ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return MJB::Backend::Jekyll::ConfigFile->new( |
|
|
|
|
|
|
|
path => $self->repo_path . "/_config.yml", |
|
|
|
|
|
|
|
)->read; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
has repo_path => ( |
|
|
|
has repo_path => ( |
|
|
|
is => 'lazy', |
|
|
|
is => 'lazy', |
|
|
|
); |
|
|
|
); |
|
|
|
@ -53,13 +50,39 @@ sub _build_repo_path { |
|
|
|
return $self->root . "/" . $self->domain; |
|
|
|
return $self->root . "/" . $self->domain; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
# The full path to the git repo to clone when using |
|
|
|
#== |
|
|
|
# init on a new repository. |
|
|
|
# The full git path (i.e. git@foo.com:mjb/default-site.git) of the repository to use as an initial |
|
|
|
|
|
|
|
# template when using the init() method to create a new blog. |
|
|
|
|
|
|
|
#== |
|
|
|
has init_from => ( |
|
|
|
has init_from => ( |
|
|
|
is => 'ro', |
|
|
|
is => 'ro', |
|
|
|
required => 1, |
|
|
|
required => 1, |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# The configuration file for the Jekyll blog itself. |
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
has config => ( |
|
|
|
|
|
|
|
is => 'lazy', |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub _build_config { |
|
|
|
|
|
|
|
my ( $self ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return MJB::Backend::Jekyll::ConfigFile->new( |
|
|
|
|
|
|
|
path => $self->repo_path . "/_config.yml", |
|
|
|
|
|
|
|
)->read; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method will initialize a new blog. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It will clone the git repo from $self->init_from and set a new remote, then |
|
|
|
|
|
|
|
# push the repository (and expect the git server to create the repo on push). |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It returns $self |
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
|
|
|
|
sub init { |
|
|
|
sub init { |
|
|
|
my ( $self ) = @_; |
|
|
|
my ( $self ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -92,6 +115,16 @@ sub init { |
|
|
|
return $self; |
|
|
|
return $self; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method will list the media files that are in the blog's /assets/media directory, |
|
|
|
|
|
|
|
# where images, pdfs, etc may be stored. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It returns a list of hashrefs containing |
|
|
|
|
|
|
|
# path | The full path to the file |
|
|
|
|
|
|
|
# filename | The basename of the file. |
|
|
|
|
|
|
|
# url | The http url that the image should exist at |
|
|
|
|
|
|
|
# markdown | The markdown code to embedd the asset as an image |
|
|
|
|
|
|
|
#== |
|
|
|
sub list_media { |
|
|
|
sub list_media { |
|
|
|
my ( $self ) = @_; |
|
|
|
my ( $self ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -114,6 +147,15 @@ sub list_media { |
|
|
|
return [ @return ]; |
|
|
|
return [ @return ]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method will list posts for the blog that are in the /_posts |
|
|
|
|
|
|
|
# collection.. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It returns a list of MJB::Backend::Jekyll::MarkdownFile objects. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# For speed read() is NOT called on these objects, so the file will |
|
|
|
|
|
|
|
# not be loaded until you call read() on the object. |
|
|
|
|
|
|
|
#== |
|
|
|
sub list_posts { |
|
|
|
sub list_posts { |
|
|
|
my ( $self ) = @_; |
|
|
|
my ( $self ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -134,6 +176,13 @@ sub list_posts { |
|
|
|
return [ @files ]; |
|
|
|
return [ @files ]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method removes a markdown file from the git repository for this blog. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It accepts a Mojo::File object to remove. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It returns self. |
|
|
|
|
|
|
|
#== |
|
|
|
sub remove_markdown_file { |
|
|
|
sub remove_markdown_file { |
|
|
|
my ( $self, $file ) = @_; |
|
|
|
my ( $self, $file ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -155,6 +204,16 @@ sub remove_markdown_file { |
|
|
|
return $self; |
|
|
|
return $self; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method lists all of the pages that exist in this blog. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It will search for .md and .markdown files and returns an arrayref |
|
|
|
|
|
|
|
# of MJB::Backend::Jekyll::MarkdownFile objects. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# For speed read() is NOT called on these objects, so the file will |
|
|
|
|
|
|
|
# not be loaded until you call read() on the object. |
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
|
|
|
|
sub list_pages { |
|
|
|
sub list_pages { |
|
|
|
my ( $self ) = @_; |
|
|
|
my ( $self ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -175,6 +234,13 @@ sub list_pages { |
|
|
|
return [ @files ]; |
|
|
|
return [ @files ]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method will load a post by its filename. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It returns an MJB::Backend::Jekyll::MarkdownFile object |
|
|
|
|
|
|
|
# if the file exists. Otherwise, it returns undef. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
#== |
|
|
|
sub get_post { |
|
|
|
sub get_post { |
|
|
|
my ( $self, $filename ) = @_; |
|
|
|
my ( $self, $filename ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -190,7 +256,26 @@ sub get_post { |
|
|
|
)->read; |
|
|
|
)->read; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method will create a new post on the blog. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It expects the filename for the collection in YYYY-MM-DD-some-title.markdown format. |
|
|
|
|
|
|
|
# (i.e. 2020-12-25-it-is-christmas.markdown) |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It returns an MJB::Backend::Jekyll::MarkdownFile object that is expected to be |
|
|
|
|
|
|
|
# populated by the caller. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# Once populated, this object should be given to write_post() to commit it. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# TODO: get_post and new_post are the very nearly the same, and should be refactored into |
|
|
|
|
|
|
|
# one function. |
|
|
|
|
|
|
|
# 1. Write a new function load_or_create_post() that will function as get_post, but |
|
|
|
|
|
|
|
# if the post doesn't exist, it will function as new_post and return an object |
|
|
|
|
|
|
|
# anyway. |
|
|
|
|
|
|
|
# 2. Run ack in the controllers and update any use of get_post or new_post to use the |
|
|
|
|
|
|
|
# new function. Confirm it works at each step of the way. |
|
|
|
|
|
|
|
# 3. Remove get_post and new_post from this file. |
|
|
|
|
|
|
|
#== |
|
|
|
sub new_post { |
|
|
|
sub new_post { |
|
|
|
my ( $self, $filename ) = @_; |
|
|
|
my ( $self, $filename ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -203,6 +288,20 @@ sub new_post { |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method will create a new page. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It expects a filepath in the form of my/file/path/and/name.markdown, and will |
|
|
|
|
|
|
|
# return a MJB::Backend::Jekyll::MarkdownFile object. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# That object should be given to write_post. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# TODO: The difference between this and the post is that this can go off the root |
|
|
|
|
|
|
|
# of the repo, where the posts go off the /_post/. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# Think about how this would work with being refactored the same as the new_post bit... |
|
|
|
|
|
|
|
# it could be all three should be one function. |
|
|
|
|
|
|
|
#== |
|
|
|
sub new_page { |
|
|
|
sub new_page { |
|
|
|
my ( $self, $filename ) = @_; |
|
|
|
my ( $self, $filename ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -215,37 +314,14 @@ sub new_page { |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sub get_title_of_post { |
|
|
|
|
|
|
|
my ( $self, $file ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
open my $lf, "<", $file |
|
|
|
|
|
|
|
or die "Failed to open $file for reading: $!"; |
|
|
|
|
|
|
|
while ( defined( my $line = <$lf> ) ) { |
|
|
|
|
|
|
|
if ( $line =~ /^title: (.+)$/ ) { |
|
|
|
|
|
|
|
close $lf; |
|
|
|
|
|
|
|
return $1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
close $lf; |
|
|
|
|
|
|
|
return undef; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Think about this.... |
|
|
|
|
|
|
|
# probably want 'slug: ' as an override for the file path |
|
|
|
|
|
|
|
sub _post_path { |
|
|
|
|
|
|
|
my ( $self, $headers ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
my $title = $headers->{title}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$title = lc($title); |
|
|
|
|
|
|
|
$title =~ s/[^a-zA-Z0-9-_]+/_/g; |
|
|
|
|
|
|
|
$title =~ s/[_]+/_/g; |
|
|
|
|
|
|
|
$title =~ s/_$//g; |
|
|
|
|
|
|
|
$title =~ s/^_//g; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return $self->repo_path . "/_posts/" . $title . ".markdown"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method writes the jekyll blog configuration file. |
|
|
|
|
|
|
|
# You can pass an MJB::Backend::Jekyll::ConfigFile object to write, |
|
|
|
|
|
|
|
# otherwise the one in $self is written. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# The config file is written, commited, and pushed to the git origin server. |
|
|
|
|
|
|
|
#== |
|
|
|
sub write_config { |
|
|
|
sub write_config { |
|
|
|
my ( $self, $config ) = @_; |
|
|
|
my ( $self, $config ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -271,6 +347,12 @@ sub write_config { |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method accepts an MJB::Backend::Jekyll::MarkdownFile object |
|
|
|
|
|
|
|
# and writes it to the blog, then commits and pushes it to the origin. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It is used by the post and page editing/creating functions. |
|
|
|
|
|
|
|
#== |
|
|
|
sub write_post { |
|
|
|
sub write_post { |
|
|
|
my ( $self, $md_file ) = @_; |
|
|
|
my ( $self, $md_file ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -298,6 +380,12 @@ sub write_post { |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method accepts a file path and a comment and will commit the file, |
|
|
|
|
|
|
|
# and push the repo. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# This is used to commit media and non-post files. |
|
|
|
|
|
|
|
#== |
|
|
|
sub commit_file { |
|
|
|
sub commit_file { |
|
|
|
my ( $self, $file, $comment ) = @_; |
|
|
|
my ( $self, $file, $comment ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -323,6 +411,12 @@ sub commit_file { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# This method accepts a file path and a comment and will remove the file, |
|
|
|
|
|
|
|
# and push the repo. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# This is used to delete media and other files. |
|
|
|
|
|
|
|
#== |
|
|
|
sub remove_file { |
|
|
|
sub remove_file { |
|
|
|
my ( $self, $file, $comment ) = @_; |
|
|
|
my ( $self, $file, $comment ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -348,26 +442,9 @@ sub remove_file { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sub revert_commit { |
|
|
|
#== |
|
|
|
my ( $self, $commit ) = @_; |
|
|
|
# Given a commit, restore the repo to that state. |
|
|
|
|
|
|
|
#== |
|
|
|
# Check that the repo exists and is latest. |
|
|
|
|
|
|
|
$self->_ensure_repository_is_latest; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add the file to git |
|
|
|
|
|
|
|
$self->system_command( [ qw( git revert --no-edit ), $commit ], { |
|
|
|
|
|
|
|
chdir => $self->repo_path, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Push the repo to the store server |
|
|
|
|
|
|
|
$self->system_command( [ qw( git push origin master ) ], { |
|
|
|
|
|
|
|
chdir => $self->repo_path, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub restore_commit { |
|
|
|
sub restore_commit { |
|
|
|
my ( $self, $commit ) = @_; |
|
|
|
my ( $self, $commit ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -393,33 +470,14 @@ sub restore_commit { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sub delete_post { |
|
|
|
#== |
|
|
|
my ( $self, $title, $file ) = @_; |
|
|
|
# This method lists the history of the git repo. |
|
|
|
|
|
|
|
# |
|
|
|
# Check if the repo exists and update the repo if needed |
|
|
|
# It returns an arrayref of hashrefs with the following keys: |
|
|
|
$self->_ensure_repository_is_latest; |
|
|
|
# commit | The commit hash |
|
|
|
|
|
|
|
# dateref | The date, expressed relative (i.e. 3 days ago) |
|
|
|
# Ensure the post exists - irony |
|
|
|
# message | The commit message |
|
|
|
die "Error: Cannot delete post that doesn't exists at " . $file |
|
|
|
#== |
|
|
|
if ! -f $file; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# git rm the file |
|
|
|
|
|
|
|
$self->system_command( [ qw( git rm ), $file ], { |
|
|
|
|
|
|
|
chdir => $self->repo_path, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# git commit the file |
|
|
|
|
|
|
|
$self->system_command( [ qw( git commit -m ), "Deleted post $title" ], { |
|
|
|
|
|
|
|
chdir => $self->repo_path, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Push the repo to the store server |
|
|
|
|
|
|
|
$self->system_command( [ qw( git push origin master ) ], { |
|
|
|
|
|
|
|
chdir => $self->repo_path, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub history { |
|
|
|
sub history { |
|
|
|
my ( $self ) = @_; |
|
|
|
my ( $self ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -449,8 +507,11 @@ sub history { |
|
|
|
return [ @return ]; |
|
|
|
return [ @return ]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
# Helper function to ensure the repo exists and has the latest |
|
|
|
#== |
|
|
|
# changes. |
|
|
|
# This method will checkout the repo if it doesn't exist on the filesystem. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# It will update the repo with a git pull. |
|
|
|
|
|
|
|
#== |
|
|
|
sub _ensure_repository_is_latest { |
|
|
|
sub _ensure_repository_is_latest { |
|
|
|
my ( $self ) = @_; |
|
|
|
my ( $self ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
@ -468,6 +529,37 @@ sub _ensure_repository_is_latest { |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#== |
|
|
|
|
|
|
|
# Run a system command. |
|
|
|
|
|
|
|
# $self->system_command( |
|
|
|
|
|
|
|
# [qw( the command here )], |
|
|
|
|
|
|
|
# { options => 'here' }, |
|
|
|
|
|
|
|
# ); |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# This method accepts an arrayref with a command, and a hashref with |
|
|
|
|
|
|
|
# options. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# The command will be executed. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# The following options may be passed: |
|
|
|
|
|
|
|
# chdir | Directory to chdir to before executing the command |
|
|
|
|
|
|
|
# mask | A hash like { My$ecretP@ssword => '--PASSWORD--' } to censor in |
|
|
|
|
|
|
|
# logging STDOUT/STDERR, and logging the command itself. |
|
|
|
|
|
|
|
# fail_on_stderr | An arrayref like [ |
|
|
|
|
|
|
|
# qr/pattern/ => 'die reason', |
|
|
|
|
|
|
|
# qr/other pattern/ => 'another die reason' |
|
|
|
|
|
|
|
# ] where system_command will emmit a die if the pattern matches on stderr. |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# A hashref will be returned that contains the following keys: |
|
|
|
|
|
|
|
# { |
|
|
|
|
|
|
|
# stdout => 'standard output content', |
|
|
|
|
|
|
|
# stderr => 'standard error content', |
|
|
|
|
|
|
|
# exitno => 1, # the exit status of the command |
|
|
|
|
|
|
|
# } |
|
|
|
|
|
|
|
# |
|
|
|
|
|
|
|
# If the environment variable MJB_DEBUG is set true, these return values |
|
|
|
|
|
|
|
# will also be printed to STDOUT. |
|
|
|
|
|
|
|
#== |
|
|
|
sub system_command { |
|
|
|
sub system_command { |
|
|
|
my ( $self, $cmd, $settings ) = @_; |
|
|
|
my ( $self, $cmd, $settings ) = @_; |
|
|
|
|
|
|
|
|
|
|
|
|