diff options
| author | EuAndreh <eu@euandre.org> | 2026-09-02 16:18:23 -0300 |
|---|---|---|
| committer | EuAndreh <eu@euandre.org> | 2026-09-03 13:26:02 -0300 |
| commit | 46422e73b86f3c0899345dfdcbbf621771b5f666 (patch) | |
| tree | 7e27a7563395e76c5db827238ef22cf5b792a60d /src/bin/paku.in | |
| parent | src/org/euandre/queue.scm: Disable tests for new python-build-system (diff) | |
| download | packages-46422e73b86f3c0899345dfdcbbf621771b5f666.tar.gz packages-46422e73b86f3c0899345dfdcbbf621771b5f666.tar.xz | |
Depend on pkgs and move code there; drop other distros but guix
Diffstat (limited to '')
| -rwxr-xr-x | src/bin/paku.in | 1169 |
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 <nixpkgs> {}; }</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; |
