bluto

Release package and announcement generator
Info | Log | Files | Refs | README | LICENSE

commit 6220adecce6988ea790266459d76d64608388019
parent 917b54591c78d2124befdeb61b34ce6a02cad5d4
Author: lash <dev@holbrook.no>
Date:   Sun, 29 Sep 2024 19:09:14 +0100

Replace with yaml

Diffstat:
MBluto.pm | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
MBluto/Archive.pm | 3++-
MBluto/RSS.pm | 4++--
Acfg/0.0.2-alpha.2.yml | 5+++++
Acfg/CHANGELOG.0.0.2-alpha.2 | 3+++
Acfg/bluto.yml | 40++++++++++++++++++++++++++++++++++++++++
Agen.pl | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apub.pl | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 393 insertions(+), 17 deletions(-)

diff --git a/Bluto.pm b/Bluto.pm @@ -9,7 +9,7 @@ use Bluto::Announce; use Bluto::Tree; use File::Path qw / make_path /; -use Log::Term::Ansi qw/debug/; +use Log::Term::Ansi qw/info debug/; use constant { VCS_TAG_PREFIX => 'v' }; use constant { VERSION => '0.0.1' }; @@ -33,11 +33,13 @@ our %m_main = ( tag_prefix => VCS_TAG_PREFIX, changelog => undef, time => undef, - tech_main => undef, - tech => \@m_tech, + #tech_main => undef, + tech => undef, vcs => \@m_vcs, - url => \@m_url, src => \@m_src, + uri => undef, + url => \@m_url, + _author_maintainer => undef, author_maintainer => undef, author_origin => undef, contributors => \@m_contributors, @@ -50,7 +52,7 @@ sub _set_single { my $main_k = shift; my $need = shift; - my $v = $cfg->param($cfg_k); + my $v = $cfg->{$cfg_k}; if (ref($v) eq 'ARRAY') { if ($#v < 0) { debug('empty value not set: ' . $cfg_k); @@ -95,20 +97,20 @@ sub _set_triple { my $email; my $pgp; - $m_main{'_' . $pfx . '_' . $k} = []; - my $cfg_k = $pfx . ':' . $k; - my $v = $cfg->param($cfg_k . '.name'); + #$m_main{'_' . $pfx . '_' . $k} = []; + #my $cfg_k = $pfx . ':' . $k; + my $v = $cfg->{$k}->{name}; # TODO if if if... if (defined $v) { - $name = $cfg->param($cfg_k . '.name'); + $name = $cfg->{$k}->{name}; if (ref($name) eq 'ARRAY') { $v = undef; } else { - $email = $cfg->param($cfg_k . '.email'); + $email = $cfg->{$k}->{email}; if (ref($email) eq 'ARRAY') { $email = undef; } - $pgp = $cfg->param($cfg_k . '.pgp'); + $pgp = $cfg->{$k}->{pgp}; if (ref($pgp) eq 'ARRAY') { $pgp = undef; } @@ -125,9 +127,7 @@ sub _set_triple { $m_main{'_' . $pfx . '_' . $k}[1] = $name . ' <' . $email . '>'; } $m_main{'_' . $pfx . '_' . $k}[2] = $pgp; - $m_main{$pfx . '_' . $k} = $v; - debug('kkkvvv ' . $pfx . '_' . $k); - + $m_main{$pfx . '_' . $k} = $name; return 0; } @@ -199,6 +199,125 @@ sub check_sanity { return $r; } +sub from_yaml { + my $cfg_m = shift; + my $cfg_v = shift; + my $env = shift; + + my $version; + if (!defined $env->{version}) { + die "version missing"; + } + $version = $env->{version}; + info('using version ' . $version); + $m_main{version} = $version; + + $r += _set_single($cfg_m, 'name', 'name', 1); + $r += _set_single($cfg_m, 'slug', 'slug', 1); + $r += _set_single($cfg_m, 'summary', 'summary', 1); + $r += _set_single($cfg_m, 'license', 'license', 1); + $r += _set_single($cfg_m, 'copyright', 'copyright', 1); + $r += _set_single($cfg_m, 'tech', 'tech', 1); + $r += _set_author($cfg_m, 'maintainer', undef, 1); + if ($r) { + error('invalid configuration'); + return undef; + } + + if (defined $cfg_m->{vcs}->{tag_prefix}) { + $m_main{tag_prefix} = $cfg_m->{vcs}->{tag_prefix}; + } + + foreach my $v (@{$cfg_m->{locate}->{www}}) { + warn('not checking url formatting for ' . $v); + push(@m_url, $v); + } + + foreach my $v (@{$cfg_m->{locate}->{vcs}}) { + warn('not checking git formatting for ' . $v); + push(@m_vcs, $v); + } + + debug("contributor list: " . $cfg_v->{contributors}); + foreach my $v (@{$cfg_v->{contributors}}) { + debug('have contributor: ' . $v); + push(@m_contributors, $v); + } + + foreach my $v(@{$cfg_m->{locate}->{www}}) { + if (!defined $m_main{uri}) { + $m_main{uri} = $v; + } + push(@m_uri, $v); + } + + foreach my $v(@{$cfg_m->{locate}->{rel}}) { + push(@m_uri, $v); + } + + # TODO: simplify now that changelog file is explicitly named + # TODO: if have sha256, check against the contents + push(@changelog_candidates, "CHANGELOG." . $m_main{version}); + for my $fn (@changelog_candidates) { + my $fp = File::Spec->catfile ( $env->{src_dir}, $fn ); + if (open(my $f, '<', $fp)) { + $m_main{changelog} = ''; + my $i = 0; + while (!eof($f)) { + my $v = readline($f); + if ($v =~ /^[a-zA-Z0-9]/) { + chomp($v); + if ($i > 0) { + $m_main{changelog} .= "\n"; + } + $m_main{changelog} .= '* ' . $v; + } + $i++; + } + close($f); + info('read changelog info from ' . $fp); + last; + } else { + debug('changelog candidate ' . $fp . ' not available: ' . $!); + } + } + + $r = _prepare_out(\%m_main, $env); + if ($r > 0) { + error('output location preparations fail'); + return undef; + } + + #my $targz = Bluto::Archive::create($m_main{slug}, $m_main{version}, $m_main{author_maintainer}[2], $m_main{tag_prefix}, $env->{src_dir}, $env->{out_dir}, 0); + my $targz = Bluto::Archive::create(\%m_main, $env, 1); + if (!defined $targz) { + error('failed to generate archive'); + return undef; + } + my @targz_stat = stat ( $targz ); + $m_main{time} = DateTime->from_epoch( epoch => $targz_stat[9] )->stringify(); + foreach my $v ( $cfg->{locate}->{tgzbase}) { + warn('not checking targz base formatting for ' . $v); + my $src = $m_main{slug} . '/' . basename($targz); + push(@m_src, $v . '/' . $src); + } + + if ($#m_src < 0) { + error('no source bundle prefixes defined'); + return undef; + } + + $m_main{engine} = $env->{engine}; + + for $k (keys %m_main) { + if ($k =~ /^[^_].*/) { + debug('release data: ' . $k . ': ' . $m_main{$k}); + } + } + + return $m_main{version}; +} + sub from_config { my $cfg = shift; my $env = shift; diff --git a/Bluto/Archive.pm b/Bluto/Archive.pm @@ -53,7 +53,8 @@ sub create { my $env = shift; my $flags = shift; - my $keygrip = $release->{author_maintainer}[2]; + my $keygrip = $release->{_author_maintainer}->[2]; + debug('using keygrip: ' . $keygrip); my $old_dir = cwd; diff --git a/Bluto/RSS.pm b/Bluto/RSS.pm @@ -50,8 +50,8 @@ sub process { guid => $release->{uri}, dc => { date => DateTime->now()->stringify(), - creator => $release->{author_maintainer}[0], - publisher => $release->{author_maintainer}[0], + creator => $release->{_author_maintainer}[0], + publisher => $release->{_author_maintainer}[0], }, # subject => "Linux Software", # creator => 'scoop@freshmeat.net', diff --git a/cfg/0.0.2-alpha.2.yml b/cfg/0.0.2-alpha.2.yml @@ -0,0 +1,5 @@ +--- +author: 'Louis Holbrook' +changelog: sha256:8333899d4b605d3466193ab5ee0a818d2d7bd5dc9f92401a415446ea0b576070 +contributors: [] +maintainer: 'Louis Holbrook' diff --git a/cfg/CHANGELOG.0.0.2-alpha.2 b/cfg/CHANGELOG.0.0.2-alpha.2 @@ -0,0 +1,3 @@ +Basic targz publish function. +Asciidoc announcement generator. +Asciidoc to RSS 1.0 announcement translator. diff --git a/cfg/bluto.yml b/cfg/bluto.yml @@ -0,0 +1,40 @@ +name: "Bluto" +slug: "bluto" +summary: "A simple-minded software packager" +license: "perl" +copyright: "Louis Holbrook" +tech: "perl" + +vcs: + tag_prefix: "v" + +sign: + rsa: + ed22519: + secp256k1: + +fund: + btc: + eth: + monero: + +locate: + www: + - https://defalsify.org/git/bluto + vcs: + - git+git://git.defalsify.org/bluto.git + tgzbase: + - https://defalsify.org/pub/src + rel: + - https://holbrook.no + - https://defalsify.org + +maintainer: + name: "Louis Holbrook" + email: "dev@holbrook.no" + pgp: "0826EDA1702D1E87C6E2875121D2E7BB88C2A746" + +author: + name: "Louis Holbrook" + email: "dev@holbrook.no" + pgp: "0826EDA1702D1E87C6E2875121D2E7BB88C2A746" diff --git a/gen.pl b/gen.pl @@ -0,0 +1,92 @@ +#!/usr/bin/perl + +use v5.10.1; +use warnings; +use strict; + +use Getopt::Long qw/ :config auto_help /; +use File::Basename qw/ dirname /; +use File::Spec; +use File::Copy; +use Cwd qw/ getcwd abs_path /; +use lib (dirname(abs_path($0))); +use Digest::SHA; + +use SemVer; +use Log::Term::Ansi qw/debug/; +use YAML::Tiny; + +# TODO: export to perl modules + + +sub croak { + die(shift); +} + +sub help() { + print("$0\n\nwould have shown help...\n"); + exit 0; +} + +my $force_version = undef; +my $loglevel = 0; +my $force_help = 0; +my %env = ( + src_dir => File::Spec->catfile(getcwd, '.bluto'), + changelog_file => undef, + version => undef, + loglevel => undef, +); +GetOptions( + 'd:s', \$env{src_dir}, + 'f:s', \$env{changelog_file}, + 'v+', \$loglevel, + 'h+', \$force_help, + 'help+', \$force_help, + 'version=s', \$force_version, +); + +if ($force_help > 0) { + help; +} + +foreach my $k (keys %env ) { + if (defined $env{$k}) { + $env{$k} = abs_path($env{$k}); + } +} + +if (defined $force_version) { + $env{version} = SemVer->new($force_version); +} + +my $fn = File::Spec->catfile($env{src_dir}, 'bluto.yml'); +my $yi = YAML::Tiny->read($fn); + +my @contributors; +my $yd = $yi->[0]; +my $yv = { + changelog => 'sha256:' . process_changelog(\%env, 1), + author => $yd->{author}->{name}, + maintainer => $yd->{maintainer}->{name}, + contributors => \@contributors, +}; +my $yo = YAML::Tiny->new($yv); +$fn = File::Spec->catfile($env{src_dir}, $env{version} . '.yml'); +$yo->write($fn); + + +sub process_changelog { + my $env = shift; + my $copy = shift; + + my $h = Digest::SHA->new('sha256'); + $h->addfile($env->{changelog_file}); + my $z = $h->hexdigest; + debug('calculated sha256 ' . $z . ' for changelog ' . $env->{changelog_file}); + if ($copy) { + my $fp = File::Spec->catfile($env->{src_dir}, 'CHANGELOG.' . $env->{version}); + copy($env->{changelog_file}, $fp); + } + return $z; +} diff --git a/pub.pl b/pub.pl @@ -0,0 +1,116 @@ +#!/usr/bin/perl + +use v5.10.1; +use warnings; +use strict; + +# standard imports +use Getopt::Long qw/ :config auto_help /; +#use File::Temp qw/ tempdir /; +use File::Basename qw/ dirname /; +use File::Spec; +use Cwd qw/ getcwd abs_path /; +use lib (dirname(abs_path($0))); + +# external imports +use Config::Simple; +use YAML::Tiny; + +# bundled external imports +use SemVer; + +# local imports +use Log::Term::Ansi qw/debug/; +use Bluto; +use Bluto::RSS; + +sub croak { + die(shift); +} + +sub help() { + print("$0\n\nwould have shown help...\n"); + exit 0; +} + +# TODO: export to perl modules + +my $force_version = undef; +my $loglevel = 0; +my $force_help = 0; +my %env = ( + src_dir => File::Spec->catfile(getcwd, '.bluto'), + out_dir => File::Spec->catfile(getcwd, 'bluto_build'), + feed_dir => undef, + content_dir => getcwd, + template_path => undef, + engine => undef, + readme => undef, + version => undef, + loglevel => undef, +); +GetOptions( + 'd:s', \$env{src_dir}, + 'o:s', \$env{out_dir}, + 'f:s', \$env{feed_dir}, + 'c:s', \$env{content_dir}, + 'v+', \$loglevel, + 'h+', \$force_help, + 'help+', \$force_help, + 'version=s', \$force_version, +); + +if ($force_help > 0) { + help; +} + +foreach my $k (keys %env ) { + if (defined $env{$k}) { + $env{$k} = abs_path($env{$k}); + } +} + +if (!defined $env{feed_dir}) { + $env{feed_dir} = $env{out_dir}; +} + +if (defined $force_version) { + $env{version} = SemVer->new($force_version); +} + +$env{loglevel} = $loglevel; + +$env{engine} = 'bluto v' . SemVer->new(Bluto::VERSION). " (perl $^V)"; +foreach my $k (keys %env ) { + if (defined $env{$k}) { + debug('environment "' . $k . '": ' . $env{$k}); + } +} + +if (Bluto::check_sanity(\%env)) { + croak('sanity check fail'); +} + +my $fn = File::Spec->catfile($env{src_dir}, 'bluto.yml'); +my $yi = YAML::Tiny->read($fn); +my $ym = $yi->[0]; + +$fn = File::Spec->catfile($env{src_dir}, $env{version} . '.yml'); +$yi = YAML::Tiny->read($fn); +my $yv = $yi->[0]; +debug('have changelog ' . $yv->{changelog} . ' for version ' . $env{version}); + +my $version = Bluto::from_yaml($ym, $yv, \%env); +if (!defined $version) { + die("config processing failed"); +} + +my $announce = Bluto::create_announce(\%env); +if (!defined $announce) { + die("announce processing failed"); +} + +my $rss = Bluto::create_rss(\%env); +if (!defined $rss) { + die("rss processing failed"); +}