#!/usr/bin/perl =head1 NAME dh_elpa - install emacs lisp packages into package build directories =cut use strict; use Cwd qw{ getcwd }; use File::Temp qw{tempfile}; use IO::Handle; require File::Path; use Debian::Debhelper::Dh_Lib; =head1 SYNOPSIS B [S>] [S>] =head1 DESCRIPTION B is a debhelper program that is responsible for installing elpa style emacs lisp packages into package build directories. =head1 FILES =over 4 =item debian/I.elpa List of files to be installed into I as an elpa package. =back =cut init(options => { "byte-compile!" => \$dh{BYTECOMPILE}, }); =head1 OPTIONS =over 4 =item B<--byte-compile>, B<--no-byte-compile> Enable (default) or disable byte compilation of installed emacs lisp files. Disabling byte compilation changes the destination directory to one that is found by the emacs package system. =back =cut sub doit_quietly { my ($handle,$tmpfile) = tempfile(UNLINK=>1); my $exitcode; verbose_print(escape_shell(@_)); open (CPERR,">&STDERR") or error "$!"; open (CPOUT,">&STDOUT") or error "$!"; STDOUT->fdopen($handle,'w'); STDERR->fdopen($handle,'w'); my $ret=doit_noerror(@_); STDOUT->fdopen(\*CPOUT,'w'); STDERR->fdopen(\*CPERR,'w'); if (!$ret){ $exitcode=$?; seek $handle, 0, 0 or error "$!"; print while (<$handle>); my $command=join(" ",@_); error("$command returned exit code ".($exitcode >> 8)); } } sub read_package_desc { my ($descdir, $package) = @_; my %desc = {}; my $descfile="${descdir}/${package}.desc"; open my $fh,'<', $descfile or error "failed to open $descfile"; while () { if (m/([^:]+):\s*(.*)\s*$/) { $desc{$1} = $2; } } return \%desc; } my $templatedir = "/usr/share/debhelper/dh_elpa/emacsen-common"; sub maybe_install_helper{ my ($package,$piece, $mode, $desc)=@_; my $file=pkgfile($package,"emacsen-$piece"); my $tmp=tmpdir($package); my $ecdest="$tmp/usr/lib/emacsen-common/packages"; my $target="$ecdest/$piece/$package"; # if there is file, leave it for dh_installemacsen if ($file eq '') { if (! -d "$ecdest/$piece") { doit("install","-d","$ecdest/$piece"); } Debian::Debhelper::Dh_Lib::autoscript_sed (sub {s/#ELPAPACKAGE#/$desc->{'ELPA-Package'}/; s/#ELPAVERSION#/$desc->{'ELPA-Version'}/; }, "$templatedir/$piece", $target); chmod $mode, $target; } } $dh{BYTECOMPILE} = 1 unless defined($dh{BYTECOMPILE}); my $elpadir; my $dhelpadir="/usr/share/emacs/site-lisp/elpa"; # TODO: do we really need a seperate elpa-src hierarchy? if ($dh{BYTECOMPILE}) { $elpadir="/usr/share/emacs/site-lisp/elpa-src"; } else { $elpadir=$dhelpadir; } PACKAGE: foreach my $package (@{$dh{DOPACKAGES}}) { my $tmp=tmpdir($package); my $file=pkgfile($package,"elpa"); my $elpapkg=$package; # TODO do this more sanely or at least allow an override $elpapkg =~ s/^elpa-//; verbose_print("Using elpa package name $elpapkg"); my @files; # Call isnative because it sets $dh{VERSION} # as a side effect. isnative($package); if ($file) { @files=filearray($file, "."); scalar(@files) == 1 || grep { m/\b${elpapkg}-pkg.el$/ } @files or error "missing ${elpapkg}-pkg.el"; } if (($package eq $dh{FIRSTPACKAGE} || $dh{PARAMS_ALL}) && @ARGV) { push @files, @ARGV; } next PACKAGE if (scalar(@files) == 0); my $pkg_file; my $cwd = getcwd(); my $tempdir = "${cwd}/debian/.debhelper/elpa"; File::Path::rmtree $tempdir || error "cleaning $tempdir"; File::Path::make_path $tempdir || error "creating $tempdir"; if (scalar(@files) == 1) { my $pkg_file=$files[0]; doit_quietly(qw{emacs -batch -Q -l package}, '--eval',"(add-to-list 'package-directory-list \"$dhelpadir\")", '--eval',"(add-to-list 'package-directory-list \"$elpadir\")", qw{-f package-initialize -l dh-elpa.el}, qw{-f dhelpa-batch-install-file}, "$tmp/$elpadir", $pkg_file, $tempdir); } else { my $stagedir = "$tempdir/$elpapkg"; File::Path::make_path $stagedir || error "creating $stagedir"; # copy files into stagedir, flattening hierarchy # TODO: do this more correctly foreach my $el_file (@files) { doit("cp", "-a", $el_file, "$stagedir"); } doit_quietly(qw{emacs -batch -Q -l package}, '--eval',"(add-to-list 'package-directory-list \"$dhelpadir\")", '--eval',"(add-to-list 'package-directory-list \"$elpadir\")", qw{-f package-initialize -l dh-elpa.el}, qw{-f dhelpa-batch-install-directory}, "$tmp/$elpadir", $stagedir, $tempdir); } if ($dh{BYTECOMPILE}) { my $desc = read_package_desc ($tempdir,$package); addsubstvar($package,'misc:Depends','emacsen-common'); maybe_install_helper($package, 'compat', '0644', $desc); maybe_install_helper($package, 'install', '0755', $desc); maybe_install_helper($package, 'remove', '0755', $desc); if (! $dh{NOSCRIPTS}) { autoscript($package,"postinst","postinst-emacsen", "s/#PACKAGE#/$package/"); autoscript($package,"prerm","prerm-emacsen", "s/#PACKAGE#/$package/"); } } } =head1 EXAMPLES Here is an example of using the helper in a dh(1) style debian/rules =over 4 override_dh_install: dh_install dh_elpa =back =cut