App-DocKnot
view release on metacpan or search on metacpan
lib/App/DocKnot/Update.pm view on Meta::CPAN
# Update package configuration for a DocKnot version upgrade.
#
# Adjusts the DocKnot configuration data for changes in format for newer
# versions of DocKnot.
#
# SPDX-License-Identifier: MIT
##############################################################################
# Modules and declarations
##############################################################################
package App::DocKnot::Update v8.0.1;
use 5.024;
use autodie;
use parent qw(App::DocKnot);
use warnings;
use Carp qw(croak);
use JSON::MaybeXS qw(JSON);
use Kwalify qw(validate);
use Path::Iterator::Rule;
use Path::Tiny qw(path);
use YAML::XS ();
# The older JSON metadata format stored text snippets in separate files in the
# file system. This is the list of additional files to load from the metadata
# directory if they exist. The contents of these files will be added to the
# configuration in a key of the same name. If the key contains a slash, like
# foo/bar, it will be stored as a nested hash, as $data{foo}{bar}.
our @JSON_METADATA_FILES = qw(
bootstrap
build/middle
build/suffix
debian/summary
packaging/extra
support/extra
test/prefix
test/suffix
);
##############################################################################
# JSON helper methods
##############################################################################
# Internal helper routine to return the path of a file or directory from the
# package metadata directory. The resulting file or directory path is not
# checked for existence.
#
# @path - The relative path of the file as a list of components
#
# Returns: Path::Tiny for the metadata file
sub _metadata_path {
my ($self, @path) = @_;
return path($self->{metadata}, @path);
}
# Internal helper routine to read a file from the package metadata directory
# and return the contents. The file is specified as a list of path
# components.
#
# @path - The path of the file to load, as a list of components
#
# Returns: The contents of the file as a string
# Throws: slurp exception on failure to read the file
sub _load_metadata {
my ($self, @path) = @_;
my $path = $self->_metadata_path(@path);
return $path->slurp_utf8();
}
# Like _load_metadata, but interprets the contents of the metadata file as
# JSON and decodes it, returning the resulting object. This uses the relaxed
# parsing mode, so comments and commas after data elements are supported.
#
# @path - The path of the file to load, as a list of components
#
# Returns: Anonymous hash or array resulting from decoding the JSON object
# Throws: slurp or JSON exception on failure to load or decode the object
sub _load_metadata_json {
my ($self, @path) = @_;
lib/App/DocKnot/Update.pm view on Meta::CPAN
# Move bootstrap to build.bootstrap.
if (defined($data_ref->{bootstrap})) {
$data_ref->{build}{bootstrap} = $data_ref->{bootstrap};
delete $data_ref->{bootstrap};
}
# Move build.lancaster to test.lancaster.
if (defined($data_ref->{build}{lancaster})) {
$data_ref->{test}{lancaster} = $data_ref->{build}{lancaster};
delete $data_ref->{build}{lancaster};
}
# Move packaging.debian to packaging.debian.package, move debian to
# packaging.debian, and move packaging to distribution.packaging.
if (defined($data_ref->{packaging})) {
if (defined($data_ref->{packaging}{debian})) {
my $package = $data_ref->{packaging}{debian};
$data_ref->{packaging}{debian} = { package => $package };
}
}
if (defined($data_ref->{debian})) {
$data_ref->{packaging}{debian} //= {};
$data_ref->{packaging}{debian}
= { $data_ref->{debian}->%*, $data_ref->{packaging}{debian}->%* };
delete $data_ref->{debian};
}
if ($data_ref->{packaging}) {
$data_ref->{distribution}{packaging} = $data_ref->{packaging};
delete $data_ref->{packaging};
}
# Move readme.sections to sections. If there was a testing override, move
# it to test.override and delete it from sections.
if (defined($data_ref->{readme})) {
$data_ref->{sections} = $data_ref->{readme}{sections};
delete $data_ref->{readme};
for my $section_ref ($data_ref->{sections}->@*) {
if (lc($section_ref->{title}) eq 'testing') {
$data_ref->{test}{override} = $section_ref->{body};
last;
}
}
$data_ref->{sections}
= [grep { lc($_->{title}) ne 'testing' } $data_ref->{sections}->@*];
}
# support.cpan is obsolete. If vcs.github is set and support.github is
# not, use it as support.github.
if (defined($data_ref->{support}{cpan})) {
if (!defined($data_ref->{support}{github})) {
if (defined($data_ref->{vcs}{github})) {
$data_ref->{support}{github} = $data_ref->{vcs}{github};
}
}
delete $data_ref->{support}{cpan};
}
# Check the schema of the resulting file.
my $schema_path = $self->appdata_path('schema/docknot.yaml');
my $schema_ref = YAML::XS::LoadFile($schema_path);
eval { validate($schema_ref, $data_ref) };
if ($@) {
my $errors = $@;
chomp($errors);
die "schema validation failed:\n$errors\n";
}
# Write the new YAML package configuration.
YAML::XS::DumpFile($self->{output}->stringify(), $data_ref);
return;
}
# Update an input tree for spin to the current format.
#
# $path - Optional path to the spin input tree, defaults to current directory
#
# Raises: Text exception on failure
sub update_spin {
my ($self, $path) = @_;
$path = defined($path) ? path($path) : path(q{.});
my $repo;
if ($path->child('.git')->is_dir()) {
$repo = Git::Repository->new(work_tree => "$path");
}
# Convert all *.faq files to *.spin files.
my $rule = Path::Iterator::Rule->new()->name(qr{ [.] faq \z }xms);
my $iter = $rule->iter($path, { follow_symlinks => 0 });
while (defined(my $file = $iter->())) {
$self->_convert_faq_pointer(path($file), $repo);
}
# Convert all *.rpod files to *.spin files.
$rule = Path::Iterator::Rule->new()->name(qr{ [.] rpod \z }xms);
$iter = $rule->iter($path, { follow_symlinks => 0 });
while (defined(my $file = $iter->())) {
$self->_convert_rpod_pointer(path($file), $repo);
}
return;
}
##############################################################################
# Module return value and documentation
##############################################################################
1;
__END__
=for stopwords
Allbery DocKnot MERCHANTABILITY NONINFRINGEMENT sublicense CPAN XDG
=head1 NAME
App::DocKnot::Update - Update DocKnot input or package configuration
=head1 SYNOPSIS
use App::DocKnot::Update;
my $update = App::DocKnot::Update->new(
{
( run in 0.605 second using v1.01-cache-2.11-cpan-39bf76dae61 )