LedgerSMB-Installer

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

   [Fixed]
       * POD documentation error
       * Install LaTeX dependencies, even when LaTeX::Driver is installed
       * Take version requirement ranges into account when installing from
         CPAN based on 'cpanfile'
       * Invocation of 'grep'; accept return value 1 (no matching lines)
         as successful command completion (instead of as an error)

0.999.9      2025-08-10
   [Fixed]
       * 'gpg' invocation for signature validation

0.999.8      2025-08-09
   [Added]
       * Added GPG signature verification
   [Fixed]
       * Typo preventing installation on Fedora (and derivatives)

0.999.7      2025-08-02
   [Added]
       * Beta releases (untagged releases) are now supported

docs/README.html  view on Meta::CPAN

        apply based on <code>--compute-packages</code>. Installed dependencies are removed
        after installation. This may be prevented using <code>--no-uninstall-env</code></dd>

      <dt><code>--target=&lt;path&gt;</code></dt>
      <dd>Default value: <code>./ledgersmb/</code><br />
        The path to use to unpack the release tarball; used with the
        <code>install</code> <em>and</em> <code>compute</code> commands</dd>

      <dt><code>--[no-]verify-sig</code></dt>
      <dd>Default value: <code>--no-verify-sig</code><br />
        Use <code>gpg</code> to verify the release signature of the downloaded tarball</dd>

      <dt><code>--[no-]uninstall-env</code></dt>
      <dd>Default value: <code>--uninstall-env</code><br />
        Uninstalls packages that were installed to prepare the environment for computation
        of the "Perl distribution to system package" mapping and the installation of
        Perl distributions from CPAN.</dd>

      <dt><code>--yes</code></dt>
      <dd>Automatically answer &quot;yes&quot; to installer questions, allowing
        non-interactive use. (Shorthand: <code>-y</code>)</dd>

lib/LedgerSMB/Installer.pm  view on Meta::CPAN

    my $archive = "ledgersmb-$version.tar.gz";

    if (not -d $installpath ) {
        $log->info( "Creating installation path $installpath" );
        make_path( $installpath ); # croaks on fatal errors
    }

    $log->info( "Downloading release tarball $archive" );
    $class->_download( $installpath, $version );

    $log->info( "Verifying tarball against gpg public key & signature" );
    my $downloaded_tar = File::Spec->catfile( $installpath, $archive );
    $dss->verify_sig( $installpath,
                      $downloaded_tar,
                      "$downloaded_tar.asc",
                      $signing_key_data )
        if $config->verify_sig;

    $log->info( "Extracting release tarball" );
    $dss->untar( $downloaded_tar,
                 $installpath,

lib/LedgerSMB/Installer/OS/linux/debian.pm  view on Meta::CPAN

        system( qw( dpkg-query -W build-essential ) );
    };
    unless (grep { m/build-essential/ } split( /\n/, $have_build_essential )) {
        $config->mark_pkgs_for_cleanup( [ 'build-essential' ] );
        $self->pkg_install( [ 'build-essential' ] );
    }
}

sub prepare_extraction_env($self, $config) {
    my ($have_deps, ) = capture_stdout {
        system( qw( dpkg-query -W tar gzip gpg ) );
    };
    my @pkgs;
    unless (grep { m/tar/ } split(/\n/, $have_deps)) {
        push @pkgs, 'tar';
    }
    unless (grep { m/gzip/ } split(/\n/, $have_deps)) {
        push @pkgs, 'gzip';
    }
    if ($config->verify_sig) {
        unless (grep { m/gpg/ } split(/\n/, $have_deps)) {
            push @pkgs, 'gpg';
        }
    }
    if (@pkgs) {
        $config->mark_pkgs_for_cleanup( \@pkgs );
        $self->pkg_install( \@pkgs );
    }
    $self->SUPER::prepare_extraction_env( $config );
}

sub prepare_installer_env($self, $config) {

lib/LedgerSMB/Installer/OS/unix.pm  view on Meta::CPAN

    return ($^X eq '/usr/bin/perl');
}

sub prepare_builder_env($self, $config) {
    warn $log->warning( 'generic Unix/Linux support does not install required module build tools' );
}

sub prepare_extraction_env($self, $config) {
    $self->have_cmd('gzip');                          # fatal, used by 'tar'
    $self->have_cmd('tar');                           # fatal
    $self->have_cmd('gpg', $config->verify_sig);      # fatal, when verification required
}

sub prepare_installer_env($self, $config) {
    $self->have_cmd('cpanm', 0);
    $self->have_cmd('make');     # fatal
}

sub cpanm_install($self, $installpath, $locallib, $unmapped_mods) {
    unless ($self->{cmd}->{cpanm}) {
        make_path( File::Spec->catdir( $installpath, 'tmp' ) );

lib/LedgerSMB/Installer/OS/unix.pm  view on Meta::CPAN

        if $options{strip_components};
    push @cmd, '--no-same-owner'
        if $options{no_same_owner};
    $log->debug( 'system(): ' . join(' ', map { "'$_'" } @cmd ) );
    system(@cmd) == 0
        or croak $log->fatal( "Failure executing tar - exit code: $?" );
}

sub verify_sig($self, $installpath, $tar, $sig, $key) {
    my $tempdir = File::Spec->catdir( $installpath, 'tmp' );
    my $gpgdir  = File::Spec->catdir( $tempdir, 'gnupg' );
    make_path( $tempdir, $gpgdir );
    chmod( 0700, $gpgdir )
        or warn $log->warning( "Unable to protect $gpgdir: $!" );

    my @cmd = (
        $self->{cmd}->{gpg},
        '--quiet',
        '--homedir', $gpgdir,
        '--no-autostart',
        '--batch',
        '--no-tty',
        '--yes',
        '--trust-model', 'always',
        '--no-default-keyring',
        '--keyring',
        File::Spec->catfile( $tempdir, 'verification-keyring.kbx' ),
        );

    $log->trace( "Importing key:\n$key" );
    $log->debug( 'system(): ' . join( ' ', map { "'$_'" } (@cmd, '--import') ) );
    open(my $fh, '|-', @cmd, '--import')
        or die "Can't open pipe to gpg for download verification: $!";
    print $fh $key;
    close($fh) or warn "Error closing pipe to gpg on key import: $!";

    $log->debug( 'system(): ' . join( ' ', map { "'$_'" } (@cmd, '--verify', $sig, $tar) ) );
    system( @cmd, '--verify', $sig, $tar ) == 0
        or croak $log->fatal( "Failure to verify gpg signature - exit code: $?" );

    remove_tree( $tempdir );

    $log->info( 'gpg signature validated correctly' );
}

sub generate_start_script($self, $installpath, $locallib) {
    ###TODO: capture file open error
    my $script = File::Spec->catfile( $installpath, 'server-start' );
    open( my $fh, '>', $script );
    my $starman = $self->have_cmd( 'starman', 0, [ File::Spec->catdir( $locallib, 'bin' ) ] );
    my $locallib_lib = File::Spec->catdir( $locallib, 'lib', 'perl5' );

    say $fh <<~EOF;



( run in 0.730 second using v1.01-cache-2.11-cpan-df04353d9ac )