aboutsummaryrefslogtreecommitdiff
path: root/src/bin/paku.in
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2026-09-02 16:18:23 -0300
committerEuAndreh <eu@euandre.org>2026-09-03 13:26:02 -0300
commit46422e73b86f3c0899345dfdcbbf621771b5f666 (patch)
tree7e27a7563395e76c5db827238ef22cf5b792a60d /src/bin/paku.in
parentsrc/org/euandre/queue.scm: Disable tests for new python-build-system (diff)
downloadpackages-46422e73b86f3c0899345dfdcbbf621771b5f666.tar.gz
packages-46422e73b86f3c0899345dfdcbbf621771b5f666.tar.xz
Depend on pkgs and move code there; drop other distros but guix
Diffstat (limited to '')
-rwxr-xr-xsrc/bin/paku.in1169
1 files changed, 0 insertions, 1169 deletions
diff --git a/src/bin/paku.in b/src/bin/paku.in
deleted file mode 100755
index 71f29c2..0000000
--- a/src/bin/paku.in
+++ /dev/null
@@ -1,1169 +0,0 @@
-#!/usr/bin/env perl
-
-use v5.34;
-use warnings;
-use feature 'signatures';
-no warnings ('experimental::signatures');
-use Scalar::Util qw(looks_like_number);
-use Getopt::Std ();
-
-use JSON ();
-
-use File::Basename ();
-use File::Temp ();
-use File::Fetch ();
-
-use Digest::MD5 ();
-use Digest::SHA ();
-use MIME::Base64 ();
-
-sub usage($fh) {
- print $fh <<~'EOF'
- Usage:
- paku [-f FILE] ACTION
- paku [-f FILE] -C CONFIG_PATH
- paku -h
- EOF
-}
-
-sub help($fh) {
- print $fh <<~'EOF'
-
-
- Options:
- -f FILE use data from FILE (default: paku.lock)
- -C CONFIG get the final value of CONFIG_PATH
- -h, --help show this message
-
- ACTION what to emit, one of:
- - guix
- - debian
- - alpine
- - nix
- - html
- - guix-channel-key
-
-
- Generate package definitions for different package managers.
-
-
- Examples:
-
- Emit Guix package definitions using all defaults:
-
- $ paku guix > packages.scm
- $ guix build -f packages.scm
-
-
- Emit Debian build recipes from "debian.json", and execute
- them as is:
-
- $ paku -f debian.json debian | make -f-
-
-
- Find out what is the final value of "datadir":
-
- $ paku -C 'datadir'
- EOF
-}
-
-
-for (@ARGV) {
- last if $_ eq '--';
- if ($_ eq '--help') {
- usage *STDOUT;
- help *STDOUT;
- exit;
- }
-}
-
-my %opts;
-if (!Getopt::Std::getopts('f:C:h', \%opts)) {
- usage *STDERR;
- exit 2;
-}
-
-if ($opts{h}) {
- usage *STDOUT;
- help *STDOUT;
- exit;
-}
-
-
-my $fname = $opts{f} || 'paku.lock';
-
-
-sub load_json() {
- my $json_str = do {
- open my $fh, $fname or die "Failed opening \"$fname\"";
- local $/;
- <$fh>;
- };
- return JSON::decode_json($json_str);
-}
-
-
-
-sub get_in($j, @l) {
- my ($head, @tail) = @l;
- if (!defined $head) {
- return ref $j ?
- JSON::encode_json $j :
- $j;
- } elsif (looks_like_number($head)) {
- return get_in($j->[$head], @tail);
- } else {
- return get_in($j->{$head}, @tail);
- }
-}
-
-if ($opts{C}) {
- say get_in(load_json(), split(/\./, $opts{C}));
- exit;
-}
-
-
-my $licenses = {
- guix => {
- 'AGPL-3.0-or-later' => 'agpl3+',
- },
- nix => {
- 'AGPL-3.0-or-later' => 'agpl3Plus',
- },
-};
-sub license_for($target, $mappings, $id) {
- return $mappings->{$id} || $licenses->{$target}->{$id} || $id;
-}
-
-sub inputs_for($mappings, @inputs) {
- my @out = ();
- for (@inputs) {
- if (!$mappings->{$_}) {
- push @out, $_;
- } else {
- push @out, @{$mappings->{$_}};
- }
- }
- return @out;
-}
-
-sub emit_packages() {
- for (@ARGV) {
- my $fh;
- my $size = (stat($_))[7];
-
- open ($fh, '<', $_) or die "Can't open \"$_\": $!";
- my $md5 = Digest::MD5->new->addfile($fh)->hexdigest;
- close $fh;
-
- open ($fh, '<', $_) or die "Can't open \"$_\": $!";
- my $sha1 = Digest::SHA->new(1)->addfile($fh)->hexdigest;
- close $fh;
-
- open ($fh, '<', $_) or die "Can't open \"$_\": $!";
- my $sha256 = Digest::SHA->new(256)->addfile($fh)->hexdigest;
- close $fh;
-
- open ($fh, '<', $_) or die "Can't open \"$_\": $!";
- my $sha512 = Digest::SHA->new(512)->addfile($fh)->hexdigest;
- close $fh;
-
- print `ar -p $_ control.tar.xz | tar -xJO ./control`;
- say "Filename: ./$_";
- say "Size: $size";
- say "MD5sum: $md5";
- say "SHA1: $sha1";
- say "SHA256: $sha256";
- print "\n";
- }
-}
-
-sub emit_release() {
- my $f = $ARGV[0] or die 'Missing "Packages" file';
- my $name = File::Basename::basename $f;
- my $size = (stat($f))[7];
-
- my $now = `env LANG=POSIX.UTF-8 date -u '+%a, %d %b %Y %H:%M:%S +0000'`;
- chomp $now;
-
- my $fh;
-
- open ($fh, '<', $f) or die "Can't open \"$f\": $!";
- my $md5 = Digest::MD5->new->addfile($fh)->hexdigest;
- close $fh;
-
- open ($fh, '<', $f) or die "Can't open \"$f\": $!";
- my $sha1 = Digest::SHA->new(1)->addfile($fh)->hexdigest;
- close $fh;
-
- open ($fh, '<', $f) or die "Can't open \"$f\": $!";
- my $sha256 = Digest::SHA->new(256)->addfile($fh)->hexdigest;
- close $fh;
-
- open ($fh, '<', $f) or die "Can't open \"$f\": $!";
- my $sha512 = Digest::SHA->new(512)->addfile($fh)->hexdigest;
- close $fh;
-
- print <<~EOF;
- Date: $now
- MD5Sum:
- $md5 $size $name
- SHA1:
- $sha1 $size $name
- SHA256:
- $sha256 $size $name
- SHA512:
- $sha512 $size $name
- EOF
- exit;
-}
-
-sub emit_build_nix() {
- my $json = load_json();
- my $ns = $json->{namespace};
- $ns =~ s/\./-/g;
- print <<~EOF;
- { pkgs ?
- import <nixpkgs> { overlays = [ (import ./default.nix { inherit pkgs; }) ]; }
- }:
-
- map (name: pkgs.$ns."\${name}")
- (builtins.attrNames pkgs.$ns)
- EOF
-}
-
-sub emit_nix() {
- my $json = load_json();
- my $ns = $json->{namespace};
- $ns =~ s/\./-/g;
- print <<~EOF;
- { pkgs }:
- self: super: {
- $ns = rec {
- EOF
- my $license_mapping = $json->{mappings}{nix}{licenses};
- for my $pkg (@{$json->{pkgs}}) {
- my $long = $pkg->{'long-description'};
- $long =~ s/^(.)/ $1/gm;
- my $license = license_for 'nix', $license_mapping, $pkg->{license};
-
- print <<~EOF;
- $pkg->{'full-name'} = pkgs.stdenv.mkDerivation rec {
- name = "$pkg->{name}";
- version = "$pkg->{vlabel}";
-
- src = fetchTarball {
- url =
- "$pkg->{url}";
- sha256 = "$pkg->{sha256nix}";
- };
-
- nativeBuildInputs = with pkgs; [
- EOF
-
- for my $input (@{$pkg->{'native-inputs'}}) {
- print <<~EOF;
- $input
- EOF
- }
- print <<~EOF;
- ];
-
- buildInputs = with pkgs; [
- EOF
- for my $input (@{$pkg->{inputs}}) {
- print <<~EOF;
- $input
- EOF
- }
- print <<~EOF;
- ];
-
- makeFlags = [ "PREFIX=\$(out)" ];
-
- doCheck = true;
- enableParallelBuilding = true;
-
- meta = with pkgs.lib; {
- description = "$pkg->{description}";
- longDescription = ''
- $long
- '';
- homepage = "$pkg->{homepage}";
- changelog = "$pkg->{changelog}";
- downloadPage = "$pkg->{'downloads-page'}";
- license = licenses.$license;
- platforms = platforms.unix;
- };
- };
- EOF
- }
- print <<~EOF;
- };
- }
- EOF
-}
-
-sub emit_guix() {
- my $json = load_json();
- my $ns = $json->{namespace};
- $ns =~ s/\./ /g;
- print <<~EOF;
- (define-module ($ns packages)
- EOF
- for my $module (@{$json->{guix}{'module-use'}}) {
- print <<~EOF;
- #:use-module (gnu packages $module)
- EOF
- }
- print <<~EOF;
- #:use-module ((guix licenses) #:prefix licenses:)
- #:use-module (guix gexp)
- #:use-module (guix packages)
- #:use-module (guix download)
- #:use-module (guix build-system gnu))
-
- EOF
-
- my $pkg_mapping = $json->{mappings}{guix}{packages};
- my $license_mapping = $json->{mappings}{guix}{licenses};
- my @pkgs = ();
- for my $pkg (@{$json->{pkgs}}) {
- my $long = $pkg->{'long-description'};
- $long =~ s/^(.)/ $1/gm;
- my $license = license_for 'guix', $license_mapping, $pkg->{license};
-
- push @pkgs, $pkg->{'full-name'};
- print <<~EOF;
- (define-public $pkg->{'full-name'}
- (package
- (name "$pkg->{name}")
- (version "$pkg->{vlabel}")
- (source
- (origin
- (method url-fetch)
- (uri "$pkg->{url}")
- (sha256
- (base32 "$pkg->{sha256guix}"))))
- (build-system gnu-build-system)
- (native-inputs
- EOF
-
- print ' (list';
- for (inputs_for $pkg_mapping, @{$pkg->{'native-inputs'}}) {
- print "\n $_";
- }
- print "))\n";
-
- print " (inputs\n";
- print ' (list';
- for (inputs_for $pkg_mapping, @{$pkg->{inputs}}) {
- print "\n $_";
- }
- print "))\n";
-
- print <<~EOF;
- (arguments
- (list
- #:make-flags #~(list (string-append "PREFIX=" #\$output))
- #:phases
- #~(modify-phases %standard-phases
- (delete 'configure))))
- (synopsis "$pkg->{description}")
- (description
- "$pkg->{'long-description'}")
- (home-page "$pkg->{homepage}")
- (license licenses:$license)))
-
- EOF
- }
- print '(list';
- for (@pkgs) {
- print "\n $_";
- }
- print ")\n";
-}
-
-sub emit_guix_channel_key() {
- my $json = load_json();
- my $name = $json->{maintainer}{name};
- my $id = $json->{maintainer}{email};
- print <<~EOF;
- .POSIX:
-
- $name.key:
- gpg --armour --export $id > \$\@
- EOF
-}
-
-sub emit_debian() {
- my $json = load_json();
- my @debs = ();
- my @targets = ();
-
- for my $pkg (@{$json->{pkgs}}) {
- push @targets, <<~EOF;
- \$(DIR)/debian/tarballs/$pkg->{fname}:
- mkdir -p \$(\@D)
- wget -O \$\@ \\
- '$pkg->{url}'
-
- \$(DIR)/debian/builddirs/$pkg->{name}-$pkg->{vversion}: \$(DIR)/debian/tarballs/$pkg->{fname}
- mkdir -p \$(\@D)
- tar -C \$(\@D) -xf \$(DIR)/debian/tarballs/$pkg->{fname}
- touch \$\@
-
- EOF
-
-
- next if $pkg->{architectures} ne 'any';
-
-
- my $deb_name = "$pkg->{name}_" . (
- $pkg->{label} eq 'latest' ? 'latest' : $pkg->{vversion}
- ) . "_all.deb";
- my $deb_path = "\$(DIR)/debian/public/$deb_name";
-
- push @debs, "\t$deb_path \\\n";
-
- my $ver = $pkg->{label} eq 'latest' ? '0.' . $pkg->{vversion} . '.latest' : $pkg->{vversion};
- $ver =~ s/^v//;
-
- push @targets, <<~EOF;
- \$(DIR)/debian/destdirs/$pkg->{name}-$pkg->{vversion}/DEBIAN: \$(DIR)/debian/builddirs/$pkg->{name}-$pkg->{vversion}
- \$(MAKE) \\
- -C \$(DIR)/debian/builddirs/$pkg->{name}-$pkg->{vversion} \\
- install \\
- PREFIX=/usr \\
- DESTDIR="\$\$PWD"/\$(\@D)
- mkdir -p \$\@
- touch \$\@
-
- \$(DIR)/debian/destdirs/$pkg->{name}-$pkg->{vversion}/DEBIAN/control: \$(DIR)/debian/destdirs/$pkg->{name}-$pkg->{vversion}/DEBIAN
- printf '' > \$\@
- printf 'Package: $pkg->{name}\\n' >> \$\@
- printf 'Version: $ver\\n' >> \$\@
- printf 'Section: custom\\n' >> \$\@
- printf 'Depends:\\n' >> \$\@
- printf 'Priority: optional\\n' >> \$\@
- printf 'Architecture: all\\n' >> \$\@
- printf 'Essential: no\\n' >> \$\@
-
- printf 'Maintainer: ' >> \$\@
- printf '$pkg->{"maintainer-b64"}' | base64 -d >> \$\@
- printf '\\n' >> \$\@
-
- printf 'Description: ' >> \$\@
- printf '$pkg->{"description-b64"}' | base64 -d >> \$\@
- printf '\\n' >> \$\@
-
- printf '$pkg->{'long-description-b64'}' | \\
- base64 -d | \\
- sed 's|^\$\$|.|' | \\
- sed 's|^| |' >> \$\@
- printf '\\n' >> \$\@
-
- \$(DIR)/debian/destdirs/$pkg->{name}-$pkg->{vversion}.deb: \$(DIR)/debian/destdirs/$pkg->{name}-$pkg->{vversion}/DEBIAN/control
- dpkg-deb --build \$(DIR)/debian/destdirs/$pkg->{name}-$pkg->{vversion}
-
- $deb_path: \$(DIR)/debian/destdirs/$pkg->{name}-$pkg->{vversion}.deb
- mkdir -p \$(\@D)
- cp \$(DIR)/debian/destdirs/$pkg->{name}-$pkg->{vversion}.deb \$\@
-
-
- EOF
- }
-
-
- print <<~EOF;
- .POSIX:
-
- DIR = $json->{datadir}
-
- debs = \\
- EOF
- print @debs, "\n";
- print <<~EOF;
- GPGKEY = '$json->{maintainer}{name} <$json->{maintainer}{email}>'
-
-
- all: \\
- \$(DIR)/debian/public/InRelease \$(DIR)/debian/public/Release.gpg \\
- \$(DIR)/debian/public/public-key.asc debian.out.txt
-
- debian.out.txt:
- \@printf '\$(DIR)/debian/public/*\\n' > \$\@
-
-
- \$(DIR)/debian/public/Packages: \$(debs)
- cd \$(\@D) && paku debian-packages *.deb > \$(\@F)
-
- \$(DIR)/debian/public/Release: \$(DIR)/debian/public/Packages
- paku debian-release \$(DIR)/debian/public/Packages > \$\@
-
- \$(DIR)/debian/public/Release.gpg: \$(DIR)/debian/public/Release
- gpg -abs -o \$\@ \$(DIR)/debian/public/Release
-
- \$(DIR)/debian/public/InRelease: \$(DIR)/debian/public/Release
- gpg --default-key \$(GPGKEY) -a --clear-sign -o \$\@ \$(DIR)/debian/public/Release
-
- \$(DIR)/debian/public/public-key.asc: \$(debs)
- gpg --armour --export \$(GPGKEY) > \$\@
-
-
- EOF
- print @targets;
-}
-
-sub emit_alpine() {
- my $d = $ARGV[0] or die 'Missing "src/alpine/" directory';
- my $json = load_json();
- for my $pkg (@{$json->{pkgs}}) {
- my @subpackages = ();
- if ($pkg->{manpages}) {
- push @subpackages, "$pkg->{name}-doc";
- }
- if ($pkg->{i18n}) {
- push @subpackages, "$pkg->{name}-lang";
- }
-
- my $date = $pkg->{date} =~ s/-//gr;
- my $ver = $pkg->{label} eq 'latest' ? "0.0.1_git$date" : $pkg->{vversion};
- my $dir = "$d/$pkg->{'full-name'}";
- mkdir "$dir";
- open(my $fh, '>', "$dir/APKBUILD");
- print $fh <<~EOF;
- # Maintainer: $pkg->{maintainer}
- pkgname='$pkg->{name}'
- pkgver='$ver'
- pkgrel='0'
- pkgdesc='$pkg->{description}'
- url='$pkg->{homepage}'
- arch='noarch'
- license='$pkg->{license}'
- depends=''
- makedepends=''
- checkdepends=''
- install=''
- subpackages='@subpackages'
- source='$pkg->{url}'
- pkgbasedir="\$startdir/.abuild/pkg"
- srcdir="\$startdir/.abuild/src"
- builddir="\$srcdir/$pkg->{name}-$pkg->{vversion}"
-
- build() {
- make PREFIX=/usr
- }
-
- check() {
- make check
- }
-
- package() {
- make install DESTDIR="\$pkgdir" PREFIX=/usr
- }
-
- cleanup_srcdir() {
- rm -rf "\$startdir/.abuild"
- }
-
- sha512sums='
- $pkg->{sha512} $pkg->{fname}
- '
- EOF
- close $fh;
- }
- my @apks = ();
- my @targets = ();
-
- for my $pkg (@{$json->{pkgs}}) {
- next if $pkg->{architectures} ne 'any';
-
- my $date = $pkg->{date} =~ s/-//gr;
- my $ver = $pkg->{label} eq 'latest' ? "0.0.1_git$date" : $pkg->{vversion};
-
- my $recipe_dir = "src/alpine/$pkg->{'full-name'}/";
- my $apk_name = "$pkg->{name}-$ver-r0.apk";
- my $apk_path = "\$(DIR)/alpine/REPODEST/alpine/x86_64/$apk_name";
-
- push @apks, "\t$apk_path \\\n";
-
- push @targets, <<~EOF;
- $apk_path: $recipe_dir/APKBUILD
- cd $recipe_dir && abuild \\
- -s \$\$OLDPWD/\$(DIR)/alpine/SRCDEST \\
- -P \$\$OLDPWD/\$(DIR)/alpine/REPODEST \\
- sanitycheck clean fetch verify unpack build check rootpkg index clean
-
- EOF
- }
-
-
- print <<~EOF;
- .POSIX:
-
- DIR = $json->{datadir}
- RSAKEY = $json->{maintainer}{email}
-
-
- apks = \\
- EOF
-
- print @apks, "\n";
- print "\n\n";
- print <<~EOF;
- all: \$(apks) \$(DIR)/alpine/REPODEST/alpine/\$(RSAKEY).rsa.pub alpine.out.txt
-
- alpine.out.txt:
- \@printf '\$(DIR)/alpine/REPODEST/alpine/*\\n' > \$\@
-
- \$(apks): src/secrets/\$(RSAKEY).rsa
-
- \$(DIR)/alpine/REPODEST/alpine/\$(RSAKEY).rsa.pub: src/secrets/\$(RSAKEY).rsa
- mkdir -p \$(\@D)
- cp src/secrets/\$(RSAKEY).rsa.pub \$\@
-
- src/secrets/\$(RSAKEY).rsa: src/secrets/\$(RSAKEY).rsa.gpg
- gpg -d -o \$\@ \$\@.gpg
- chmod 400 \$\@
-
- EOF
- print @targets;
-}
-
-sub pascal_case($s) {
- return join('', map(ucfirst, split '-', $s))
-}
-
-sub emit_homebrew() {
- my $d = $ARGV[0] or die 'Missing "Formula/" directory';
- my $json = load_json();
- for my $pkg (@{$json->{pkgs}}) {
- open(my $fh, '>', "$d/$pkg->{'full-name'}.rb");
- my $class_name = pascal_case $pkg->{'full-name'};
- print $fh <<~EOF;
- class $class_name < Formula
- desc '$pkg->{description}'
- homepage '$pkg->{homepage}'
- url '$pkg->{url}'
- sha256 '$pkg->{sha256}'
- license 'AGPL-3.0-or-later'
-
- def install
- system 'make', "PREFIX=#{prefix}"
- system 'make', 'check', "PREFIX=#{prefix}"
- system 'make', 'install', "PREFIX=#{prefix}"
- end
-
- test do
- system "#{bin}/$pkg->{name}", '-V'
- end
- end
- EOF
- close $fh;
- }
-}
-
-sub emit_html() {
- my $json = load_json();
- print <<~EOF;
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <link rel="icon" type="image/svg+html" href="favicon.svg" />
- <title>$json->{name} package index</title>
-
- <style>
- body {
- max-width: 800px;
- margin: 0 auto;
- }
-
- ul {
- list-style: none;
- }
-
- li {
- margin-top: 2em;
- }
-
- pre {
- overflow: auto;
- white-space: pre;
- margin: 5px;
- padding: 5px;
- border-radius: 5px;
- }
-
- pre, code {
- background-color: #ddd;
- }
-
- \@media(prefers-color-scheme: dark) {
- :root {
- color: white;
- background-color: black;
- }
-
- a {
- color: hsl(211, 100%, 60%);
- }
-
- a:visited {
- color: hsl(242, 100%, 80%);
- }
-
- pre, code {
- background-color: #222;
- }
- }
- </style>
- </head>
- <body>
- <main>
- <h1>
- $json->{name} package index
- </h1>
- <ul>
- EOF
-
- for my $pkg (@{$json->{pkgs}}) {
- my $guix_suffix = $pkg->{label} eq 'latest' ? '' : "\@$pkg->{version}";
- my $apt_suffix = $pkg->{label} eq 'latest' ? '' : "=$pkg->{label}";
- my $id = $pkg->{name} . (
- $pkg->{label} eq 'latest' ? '' : "-$pkg->{vversion}"
- );
- print <<~EOF;
- <li id="$id">
- <details>
- <summary>
- <a href="#$id">$pkg->{name}</a>
- ($pkg->{vname}) - $pkg->{description}
- </summary>
- <p>
- <a href="$pkg->{homepage}">Homepage</a>
- </p>
- <section>
- <h2>Guix</h2>
- <p>
- After following the
- <a href="#guix-instructions">Guix instructions</a>
- to include this channel, you can launch a shell
- that includes this package:
- </p>
- <pre><code>\$ guix shell $pkg->{name}$guix_suffix</code></pre>
- <p>
- Alternatively, you can install it imperatively:
- </p>
- <pre><code>\$ guix install $pkg->{name}$guix_suffix</code></pre>
- </section>
- <section>
- <h2>Debian</h2>
- <p>
- After following the
- <a href="#debian-instructions">Debian instructions</a>
- to include this repository to
- <code>/etc/apt/sources.list</code>, you can
- install it:
- </p>
- <pre><code># apt install $pkg->{name}$apt_suffix</code></pre>
- </section>
- <section>
- <h2>Alpine</h2>
- <p>
- After folowwing the
- <a href="#alpine-instructions">Alpine instructions</a>
- to include this repository to
- <code>/etc/apk/repositories</code>, you can
- install it:
- </p>
- <pre><code># apk add $pkg->{name}</code></pre>
- </section>
- <section>
- <h2>Nix</h2>
- <p>
- After following the
- <a href="#nix-instructions">Nix instructions</a>
- to include this repository as an overlay, you
- can launch a shell that includes this package:
- </p>
- <pre><code>\$ nix-shell -p $pkg->{'full-name'}</code></pre>
- <p>
- Alternatively, you can install it imperatively:
- </p>
- <pre><code>\$ nix-env -i $pkg->{'full-name'}</code></pre>
- </section>
- <section>
- <h2>Homebrew</h2>
- <p>
- After following the
- <a href="#homebrew-instructions">Homebrew instructions</a>
- to include this repository as a <code>tap</code>, you can
- install it with:
- </p>
- <pre><code>\$ brew install $pkg->{'full-name'}</code></pre>
- </section>
- </details>
- </li>
- EOF
- }
-
- my $channel_name = $json->{namespace} =~ s/\./-/gr;
- my $overlay_name = $json->{namespace} =~ s/\./-/gr;
- my $tap_name = $json->{namespace} =~ s/\./\//gr;
- print <<~EOF;
- </ul>
- <article id="guix-instructions">
- <h2>Guix instructions</h2>
- <p>
- Add this channel to your
- <code>~/.config/guix/channels.scm</code>:
- </p>
- <pre><code>(cons*
- (channel
- (name '$channel_name)
- (url "$json->{vcs}->{git}")
- (branch "main")
- (introduction
- (make-channel-introduction
- "d749e053e6db365069cb9b2ef47a78b06f9e7361"
- (openpgp-fingerprint
- "5BDA E9B8 B2F6 C6BC BB0D 6CE5 81F9 0EC3 CD35 6060"))))
- %default-channels)</code></pre>
- <p>
- Afterwards, do a <code>guix pull</code> to make the
- packages in this channel available to your profile.
- </p>
- <p>
- See also the
- <a href="https://guix.gnu.org/manual/en/guix.html#Channels">Guix manual on channels</a>
- for more information.
- </p>
- </article>
- <article id="debian-instructions">
- <h2>Debian instructions</h2>
- <p>
- Include my public key for validating the repository
- signatures:
- </p>
- <pre><code>\$ wget -qO- $json->{'base-url'}/debian/public-key.asc |
- sudo tee /etc/apt/trusted.gpg.d/$json->{namespace}.asc</code></pre>
- <p>
- Afterwards, include this repository to the list of
- repositories that <code>apt(8)</code> uses for sources
- by adding its URL to
- <code>/etc/apt/sources.list</code>:
- </p>
- <pre><code>\$ echo 'deb $json->{'base-url'}/debian ./' |
- sudo tee -a /etc/apt/sources.list
- \$ sudo apt update</code></pre>
- <p>
- After that the packages from this repository will
- be available.
- </p>
- </article>
- <article id="alpine-instructions">
- <h2>Alpine instructions</h2>
- <p>
- Get my public key used to sign the repository:
- </p>
- <pre><code>\$ wget -qO- $json->{'base-url'}/alpine/$json->{maintainer}{email}.rsa.pub |
- doas tee /etc/apk/keys/$json->{maintainer}{email}.rsa.pub</code></pre>
- <p>
- Then include this repository in the
- <code>apk-repositories(5)</code> list that
- <code>apk(8)</code> uses to retrive package files for
- installation:
- </p>
- <pre><code>\$ echo '$json->{'base-url'}/alpine' |
- doas tee -a /etc/apk/repositories</code></pre>
- <p>
- After that the packages frmo this repository will be
- available.
- </p>
- </article>
- <article id="nix-instructions">
- <h2>Nix instructions</h2>
- <p>
- Add this repository as an overlay to your
- <code>/etc/nixos/configuration.nix</code>:
- </p>
- <pre><code> nixpkgs = {
- overlays = [
- (import (fetchTarball {
- url = "$json->{vcs}->{tarball}";
- }) { inherit pkgs; })
- ];
- };</code></pre>
- <p>
- All the packages live under the
- <code>$overlay_name</code> attribute set, like.
- <code>$overlay_name.$json->{pkgs}[0]->{name}</code>,
- so it can be included in the list of packages:
- </p>
- <pre><code> environment.systemPackages = with pkgs; [
- ...
- $overlay_name.$json->{pkgs}[0]->{name}
- ];</pre></code>
- <p>
- To make the overlay available outside the system
- environment of
- <code>/etc/nixos/configuration.nix</code>, you need to
- add this overlay to your
- <code>~/.config/nixpkgs/overlays/</code> directory,
- like a
- <code>~/.config/nixpkgs/overlays/$json->{namespace}.nix</code>
- file containing:
- </p>
- <pre><code>import (fetchTarball {
- url = "$json->{vcs}->{tarball}";
- }) { pkgs = import &lt;nixpkgs&gt; {}; }</pre></code>
- <p>
- Then you'd be able to launch a shell with a package
- from this overlay:
- </p>
- <pre><code>\$ nix-shell -p $overlay_name.$json->{pkgs}[0]->{name}</code></pre>
- </article>
- <article id="homebrew-instructions">
- <h2>Homebrew instructions</h2>
- <p>
- Add this repository as a tap:
- </p>
- <pre><code>\$ brew tap --force-auto-update $tap_name $json->{vcs}->{http}</code></pre>
- <p>
- The explicit <code>--force-auto-update</code> option
- is required, because <code>homebrew(1)</code> will only
- fetch updates automatically for repositories hosted on
- GitHub. With this option, repositories not on GitHub
- are treated equally.
- </p>
- </article>
- </main>
- </body>
- </html>
- EOF
-}
-
-
-sub run_template($name, $version, $template) {
- return ($template =~ s/\@name\@/$name/gr) =~ s/\@version\@/$version/gr;
-}
-
-sub set_difference($s1, $s2) {
- my %idx = ();
- for (@{$s1}) {
- $idx{$_} = 1;
- }
- for (@{$s2}) {
- delete $idx{$_};
- }
- return keys(%idx);
-}
-
-sub emit_refresh() {
- my $json_str = do {
- local $/;
- <STDIN>;
- };
- my $json = JSON::decode_json($json_str);
-
- my $defaults = {
- datadir => '.paku',
- guix => {},
- mappings => {},
- maintainer => {
- name => '',
- email => '',
- },
- namespace => '',
- name => '',
- 'base-url' => '',
- vcs => {
- git => '',
- http => '',
- tarball => '',
- },
- pkgs => [],
- };
- my $out = {
- %$defaults,
- %$json,
- };
-
- my $default_package = {
- maintainer => $out->{defaults}{maintainer} || '',
- 'exclude-tags' => [],
- };
- for my $package_any (@{$out->{packages}{any}}) {
- my $package = ref $package_any ?
- { %$default_package, %$package_any } :
- { %$default_package, name => $package_any };
-
- my $repo_url = run_template($package->{name}, '', $out->{defaults}{templates}{repository});
- my $dir = File::Temp::newdir();
- `git clone '$repo_url' '$dir'`;
- die if $?;
-
- my @versions = ();
- my $tags_any = $package->{tags} || $out->{defaults}{versions}{tags};
- my @tags = ();
- if (ref $tags_any) {
- push @tags, @$tags_any;
- } elsif ($tags_any eq 'all') {
- my @ret = `git -C '$dir' tag`;
- die if $?;
- chomp @ret;
-
- push @tags, set_difference(\@ret, $package->{'exclude-tags'});
- } else {
- die "Unknown value of \"tags\": $tags_any";
- }
-
- for (@tags) {
- my $ver = $_ =~ s/^v//gr;
- my %version = (
- type => 'tag',
- vversion => $_,
- version => $ver,
- vname => $_,
- vlabel => $ver,
- label => $ver =~ s/\./-/gr,
- );
- push @versions, \%version;
- }
-
- my $default_branch =
- $package->{default_branch} ||
- $out->{defaults}{default_branch} ||
- 'main';
- my $branches = $package->{branches} || $out->{defaults}{versions}{branches};
- for (@{$branches}) {
- my $revision = `git -C '$dir' rev-parse '$_'`;
- die if $?;
- chomp $revision;
-
- my $label = $_ eq $default_branch ? 'latest' : $_;
-
- my %version = (
- type => 'branch',
- vversion => $revision,
- version => $_,
- vname => $label,
- vlabel => $revision,
- label => $label,
- );
- push @versions, \%version;
- }
-
- for my $version (@versions) {
- my $pkg = {
- %$version,
- name => $package->{name},
- architectures => 'any',
- };
-
- my $full_name = $pkg->{name} . (
- $pkg->{label} eq 'latest' ? '' : "-$pkg->{label}"
- );
- $pkg->{'full-name'} = $full_name;
-
- my $revision = `git -C '$dir' rev-parse '$pkg->{vversion}'`;
- die if $?;
- chomp $revision;
- $pkg->{revision} = $revision;
-
- `git -C '$dir' checkout '$pkg->{vversion}'`;
- die if $?;
- my $url = run_template($package->{name}, $pkg->{vversion}, $out->{defaults}{templates}{tarball});
- $pkg->{url} = $url;
-
- my $date = `git -C '$dir' log -1 --format=%cs`;
- die if $?;
- chomp $date;
- $pkg->{date} = $date;
-
- $pkg->{manpages} = -d "$dir/doc/" ? JSON::true : JSON::false;
- $pkg->{i18n} = -d "$dir/po/" ? JSON::true : JSON::false;
-
- for (qw(description long-description)) {
- my $s = do { local(@ARGV, $/) = "$dir/$_"; <> };
- chomp $s;
- $pkg->{$_} = $package->{$_} || $s;
- }
-
- my @sha_guix = `guix download '$url'`;
- die if $?;
- chomp @sha_guix;
- $pkg->{sha256guix} = $sha_guix[-1];
-
- my $sha_nix = `nix-prefetch-url --unpack '$url'`;
- die if $?;
- chomp $sha_nix;
- $pkg->{sha256nix} = $sha_nix;
-
-
- my $ff = File::Fetch->new(uri => $url);
- my $where = $ff->fetch(to => '/tmp');
- my $fh;
-
- open ($fh, '<', $where) or die "Can't open \"$where\": $!";
- my $sha256 = Digest::SHA->new(256)->addfile($fh)->hexdigest;
- close $fh;
- $pkg->{sha256} = $sha256;
-
- open ($fh, '<', $where) or die "Can't open \"$where\": $!";
- my $sha512 = Digest::SHA->new(512)->addfile($fh)->hexdigest;
- close $fh;
- $pkg->{sha512} = $sha512;
-
- unlink $where;
-
-
- for (qw(base-url homepage changelog downloads-page fname)) {
- $pkg->{$_} = $package->{$_} ||
- run_template(
- $pkg->{name},
- $pkg->{vversion},
- $out->{defaults}{templates}{$_}
- );
- }
-
- for (qw(inputs native-inputs)) {
- $pkg->{$_} = $package->{$_} || [];
- }
-
- for (qw(maintainer license)) {
- $pkg->{$_} = $package->{$_} || $out->{defaults}{$_};
- }
-
- for (qw(maintainer description long-description)) {
- $pkg->{"$_-b64"} = MIME::Base64::encode_base64($pkg->{$_}, '');
- }
-
- push @{$out->{pkgs}}, $pkg;
- }
- }
- print JSON->new->pretty->canonical->encode($out);
-}
-
-
-my %actions = (
- 'debian-packages' => \&emit_packages,
- 'debian-release' => \&emit_release,
- 'build-nix' => \&emit_build_nix,
- nix => \&emit_nix,
- guix => \&emit_guix,
- 'guix-channel-key' => \&emit_guix_channel_key,
- debian => \&emit_debian,
- alpine => \&emit_alpine,
- homebrew => \&emit_homebrew,
- html => \&emit_html,
- refresh => \&emit_refresh,
-);
-
-my $action = $ARGV[0] or die "Missing ACTION";
-shift;
-my $fn = $actions{$action} or die "Unknown ACTION: \"$action\"";
-&$fn;