aboutsummaryrefslogblamecommitdiff
path: root/src/bin/paku
blob: d73107ab0946466d0ec86158b8b1eda09a72b35b (plain) (tree)



















                                         
 









                                                                            
 
 





                           

 







                              
 
 



                                           

 



                      

 





























































                                                                                

 






                                       





                                               
                                     


                                                               
 

                                                      
 
                                                                     
 












                                                                      
 


                                                            
                           






                                                   
                                     
                                      
                           
                 






















                                                               





                     

 





















                                                          







                                                   
 

                                                      
 
                                                                     
 





















                                                                             
 






                                                                             
 
















                                                                             
                                     




                                                         

                           







                              

 
 







                                                
 
                 
 


                                                                                       
 




                                             
 



                                                                                        
 
                   
 
 




















































                                                                                                                                        

 
                   
 






































                                                                                       
#!/usr/bin/env perl

# FIXME: add html output

use v5.34;
use warnings;
use feature 'signatures';
no warnings ('experimental::signatures');
use Getopt::Std ();
use JSON ();
use MIME::Base64 ();
use open IN => ':encoding(UTF-8)';

sub usage($fh) {
	print $fh <<~'EOF'
		Usage:
		  paku [-f FILE] FIXME
		  paku -h
		EOF
}

sub help($fh) {
	print $fh <<~'EOF'


		Options:
		  -f FILE       use data from FILE (default: paku.json)
		  -h, --help    show this message


		Generate package definitions for different package managers.


		Examples:

		  FIXME:

		    $ FIXME
		EOF
}


for (@ARGV) {
	last if $_ eq '--';
	if ($_ eq '--help') {
		usage *STDOUT;
		help *STDOUT;
		exit;
	}
}

my %opts;
if (!Getopt::Std::getopts('f:h', \%opts)) {
	usage *STDERR;
	exit 2;
}

if ($opts{h}) {
	usage *STDOUT;
	help *STDOUT;
	exit;
}


my $dir = '.paku'; # FIXME: parameterize
my $fname = $opts{f} || 'paku.lock';
my $json_str = do {
	open my $fh, $fname or die "Failed opening \"$fname\"";
	local $/;
	<$fh>;
};
my $json = JSON::decode_json($json_str);

my $action = $ARGV[0];



use Data::Dumper;
use POSIX qw();
use File::Basename ();
use Digest::MD5 ();
use Digest::SHA ();


# FIXME
my $base_url_prefix = 'https://euandre.org/s';

if ($action eq 'release') {
	my $f = $ARGV[1];
	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;
}

if ($action eq 'nix') {
	my $ns = 'org-euandre'; # FIXME
	print <<~EOF;
		{ pkgs }:
		self: super: {
		  $ns = rec {
		EOF
	for my $pkg (@{$json->{packages}}) {
		my $ver = $pkg->{version};
		$ver =~ s/^v//;
		$ver =~ s/\./-/g;
		if ($pkg->{type} eq 'latest') {
			$ver = 'latest';
			print <<~EOF;
			    $pkg->{name} = $pkg->{name}-latest;
			EOF
		}

		my $long = $pkg->{'long-description'};
		$long =~ s/^(.)/          $1/gm;

		my $base_url = $base_url_prefix . '/' . $pkg->{name};

		print <<~EOF;
		    $pkg->{name}-$ver = pkgs.stdenv.mkDerivation rec {
		      name = "$pkg->{name}";
		      version = "$pkg->{version}";

		      src = fetchTarball {
		        url =
		          "$pkg->{url}";
		        sha256 = "$pkg->{sha256}";
		      };

		      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 = "$base_url/";
		        changelog = "$base_url/CHANGELOG.html";
		        downloadPage = "$base_url/#releases";
		        license = licenses.agpl3;
		        platforms = platforms.unix;
		      };
		    };
		EOF
		# FIXME: escape quotes in description
		# FIXME: parameterize license
	}
	print <<~EOF;
	  };
	}
	EOF
	exit;
}


if ($action eq 'guix') {
	my @pkgs = ();
	my $ns = 'org euandre'; # FIXME
	print <<~EOF;
	(define-module ($ns packages)
	EOF
	for my $module (@{$json->{guix}{'module-use'}}) {
		print <<~EOF;
		  #:use-module (gnu packages $module)
		EOF
	}
	# FIXME: rename to 'licenses:'
	print <<~EOF;
	  #:use-module ((guix licenses) #:prefix license:)
	  #:use-module (guix gexp)
	  #:use-module (guix packages)
	  #:use-module (guix download)
	  #:use-module (guix build-system gnu))

	EOF

	for my $pkg (@{$json->{packages}}) {
		my $ver = $pkg->{version};
		$ver =~ s/^v//;
		$ver =~ s/\./-/g;
		if ($pkg->{type} eq 'latest') {
			push @pkgs, "$pkg->{name}";
			$ver = 'latest';
		}

		my $long = $pkg->{'long-description'};
		$long =~ s/^(.)/          $1/gm;

		my $base_url = $base_url_prefix . '/' . $pkg->{name};

		push @pkgs, "$pkg->{name}-$ver";
		# FIXME: indentation of (source ...)
		print <<~EOF;
		(define-public $pkg->{name}-$ver
		  (package
		    (name "$pkg->{name}-$ver")
		    (version "$pkg->{version}")
		    (source (origin
		              (method url-fetch)
		              (uri "$pkg->{url}")
		              (sha256
		                (base32 "$pkg->{sha256FIXME}"))))
		    (build-system gnu-build-system)
		    (native-inputs
		EOF

		print '      (list';
		for my $input (@{$pkg->{'native-inputs'}}) {
			my $name = $json->{mappings}{$input}{guix} || $input;
			print "\n       $name";
		}
		print "))\n";

		print "    (inputs\n";
		print '      (list';
		for my $input (@{$pkg->{inputs}}) {
			my $name = $json->{mappings}{$input}{guix} || $input;
			print "\n       $name";
		}
		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 "$base_url/")
		    (license license:agpl3+)))

		EOF
		# FIXME: escape quotes in description
		# FIXME: parameterize license
		if ($pkg->{type} eq 'latest') {
			print <<~EOF;
			(define-public $pkg->{name}
			  (package
			    (inherit $pkg->{name}-latest)
			    (name "$pkg->{name}")))


			EOF
		}
	}
	print '(list';
	for (@pkgs) {
		print "\n $_";
	}
	print ")\n";
	exit;
}


my %vars = (
	tarballs  => ["tarballs = \\\n"],
	checkouts => ["checkouts = \\\n"],
	destdirs  => ["debian-destdirs = \\\n"],
	ctrlfiles => ["control-files = \\\n"],
	destdebs  => ["destdir-debs = \\\n"],
	debs      => ["debs = \\\n"],
);

my @targets = ();

for my $pkg (@{$json->{packages}}) {
	push @{$vars{tarballs}},  "\t$dir/tarballs/$pkg->{fname} \\\n";
	push @{$vars{checkouts}}, "\t$dir/checkouts/$pkg->{name}-$pkg->{version} \\\n";

	push @targets, <<~EOF;
		$dir/tarballs/$pkg->{fname}:
			mkdir -p \$(\@D)
			wget -O \$\@ \\
				'$pkg->{url}'

		$dir/checkouts/$pkg->{name}-$pkg->{version}: $dir/tarballs/$pkg->{fname}
			mkdir -p \$(\@D)
			tar -C $dir/checkouts/ -xf $dir/tarballs/$pkg->{fname}
			touch \$\@

		EOF


	next if $pkg->{architectures} ne 'any';

	push @{$vars{destdirs}},  "\t$dir/debian-destdir/$pkg->{name}-$pkg->{version}/DEBIAN \\\n";
	push @{$vars{ctrlfiles}}, "\t$dir/debian-destdir/$pkg->{name}-$pkg->{version}/DEBIAN/control \\\n";
	push @{$vars{destdebs}},  "\t$dir/debian-destdir/$pkg->{name}-$pkg->{version}.deb \\\n";
	push @{$vars{debs}},      "\t$dir/debian/$pkg->{name}_$pkg->{version}_all.deb \\\n";

	my $ver = $pkg->{type} eq 'latest' ? '0.' . $pkg->{version} . '.latest' : $pkg->{version};
	$ver =~ s/^v//;
	my $maintainer_b64 = MIME::Base64::encode_base64 $pkg->{maintainer}, '';
	my $desc_b64       = MIME::Base64::encode_base64 $pkg->{description}, '';
	my $long_desc_b64  = MIME::Base64::encode_base64 $pkg->{'long-description'}, '';

	push @targets, <<~EOF;
		$dir/debian-destdir/$pkg->{name}-$pkg->{version}/DEBIAN: $dir/checkouts/$pkg->{name}-$pkg->{version}
			\$(MAKE) \\
				-C $dir/checkouts/$pkg->{name}-$pkg->{version} \\
				install \\
				PREFIX=/usr \\
				DESTDIR="\$\$PWD"/$dir/debian-destdir/$pkg->{name}-$pkg->{version}
			mkdir -p \$\@
			touch \$\@

		$dir/debian-destdir/$pkg->{name}-$pkg->{version}/DEBIAN/control: $dir/debian-destdir/$pkg->{name}-$pkg->{version}/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 '$maintainer_b64' | base64 -d  >> \$\@
			printf '\\n'                           >> \$\@

			printf 'Description: '                >> \$\@
			printf '$desc_b64' | base64 -d >> \$\@
			printf '\\n'                           >> \$\@

			printf '$long_desc_b64' | \\
				base64 -d |    \\
				sed 's|^\$\$|.|' | \\
				sed 's|^| |'                        >> \$\@
			printf '\\n'                           >> \$\@

		$dir/debian-destdir/$pkg->{name}-$pkg->{version}.deb: $dir/debian-destdir/$pkg->{name}-$pkg->{version}/DEBIAN/control
			dpkg-deb --build $dir/debian-destdir/$pkg->{name}-$pkg->{version}

		$dir/debian/$pkg->{name}_$pkg->{version}_all.deb: $dir/debian-destdir/$pkg->{name}-$pkg->{version}.deb
			mkdir -p \$(\@D)
			cp $dir/debian-destdir/$pkg->{name}-$pkg->{version}.deb \$\@


		EOF
}


print
	@{$vars{tarballs}},  "\n",
	@{$vars{checkouts}}, "\n",
	@{$vars{destdirs}},  "\n",
	@{$vars{ctrlfiles}}, "\n",
	@{$vars{destdebs}},  "\n",
	@{$vars{debs}},      "\n";

print <<~EOF;
	FIXME = eu\@euandre.org


	all: $dir/debian/InRelease $dir/debian/Release.gpg $dir/debian/public-key.asc

	public-dir:
		\@printf '$dir/debian'


	$dir/debian/Packages: \$(debs)
		cd \$(\@D) && dpkg-scanpackages -m . > \$(\@F)

	$dir/debian/Release: $dir/debian/Packages
		perl src/bin/paku release $dir/debian/Packages > \$\@

	$dir/debian/Release.gpg: $dir/debian/Release
		gpg -abs -o \$\@ $dir/debian/Release

	$dir/debian/InRelease: $dir/debian/Release
		gpg --default-key \$(FIXME) -a --clear-sign -o \$\@ $dir/debian/Release

	$dir/debian/public-key.asc: $dir/debian/Release
		gpg --armour --export \$(FIXME) > \$\@


	EOF

print @targets;