Dist-Zilla-Plugin-Git-FilePermissions
view release on metacpan or search on metacpan
#!perl
# vim: ts=4 sts=4 sw=4 et: syntax=perl
#
# Copyright (c) 2017-2022 Sven Kirmess
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
use 5.006;
use strict;
use warnings;
use Carp qw(croak);
use Git::Background 0.003;
use Path::Tiny;
use Test::DZil;
use Test::Fatal;
use Test::More 0.88;
use Cwd ();
use File::Basename ();
use File::Spec ();
use lib File::Spec->catdir( File::Basename::dirname( Cwd::abs_path __FILE__ ), 'lib' );
use Local::Test::TempDir qw(tempdir);
main();
sub main {
SKIP:
{
skip 'Cannot find Git in PATH', 1 if !defined Git::Background->version;
_test_with_defaults();
_test_with_changed_defaults();
_test_with_config_bin();
_test_with_config_bin_scripts();
_test_with_config_scripts_unchanged();
}
done_testing();
exit 0;
}
{
# If you run chmod 0644 on a file and read the permissions back with
# stat what you get back depends on your OS. On Unix you get 0644 back
# but on Windows you will get something else back. This function creates
# a hash that maps "permission we set with chmod" to "permission we read
# back with stat",
my %p;
sub _p {
my ($value) = @_;
return $p{$value} if exists $p{$value};
my $tmp_dir = path( tempdir() );
my $file = $tmp_dir->child('file.txt');
$file->spew("hello world\n");
chmod $value, $file or croak "chmod $value, $file: $!";
my $perm = ( stat $file )[2] & 07777;
note( sprintf q{On this system, 'chmod 0%o' results in 0%o}, $value, $perm );
return $p{$value} = $perm;
}
}
my $dir_perm;
sub _configure_root {
my ($root_dir) = @_;
# Create a git repository in the source
my $git = Git::Background->new($root_dir);
$git->run('init')->get;
# Create some directories
$root_dir->child('bin')->mkpath();
$root_dir->child('scripts')->mkpath();
$root_dir->child('lib')->mkpath();
my @files;
push @files, path($root_dir)->child('bin/a');
$files[-1]->spew();
$git->run( 'add', $files[-1] )->get;
chmod 0755, $files[-1] or croak "chmod 0755, $files[-1]: $!";
push @files, path($root_dir)->child('scripts/b');
$files[-1]->spew();
$git->run( 'add', $files[-1] )->get;
chmod 0600, $files[-1] or croak "chmod 0600, $files[-1]: $!";
push @files, path($root_dir)->child('lib/c.pm');
$files[-1]->spew();
$git->run( 'add', $files[-1] )->get;
chmod 0, $files[-1] or croak "chmod 0, $files[-1]: $!";
push @files, path($root_dir)->child('d');
$files[-1]->spew();
$git->run( 'add', $files[-1] )->get;
chmod 0644, $files[-1] or croak "chmod 0644, $files[-1]: $!";
my $sub_src = _create_submodule();
push @files, path($root_dir)->child('s');
if ( $git->run( 'submodule', 'add', $sub_src, 's' )->await->is_failed ) {
# "protocol.file.allow=always" lets the submodule command clone from
# a local directory. It's necessary as of Git 2.38.1, where the
# default was changed to "user" in response to CVE-2022-39253.
# It isn't a concern here where all repositories involved are
# trusted. For more information, see:
# https://vielmetti.typepad.com/logbook/2022/10/git-security-fixes-lead-to-fatal-transport-file-not-allowed-error-in-ci-systems-cve-2022-39253.html
# https://github.com/microsoft/go-infra/pull/71/files
# https://github.blog/2022-10-18-git-security-vulnerabilities-announced/#cve-2022-39253
# https://bugs.launchpad.net/ubuntu/+source/git/+bug/1993586
# https://git-scm.com/docs/git-config#Documentation/git-config.txt-protocolallow
$git->run( '-c', 'protocol.file.allow=always', 'submodule', 'add', $sub_src, 's' )->get;
}
$dir_perm = ( stat $files[-1] )[2] & 07777;
is( ( stat $files[0] )[2] & 07777, _p(0755), sprintf q{File '%s' created correctly}, $files[0]->relative($root_dir) );
is( ( stat $files[1] )[2] & 07777, _p(0600), sprintf q{File '%s' created correctly}, $files[1]->relative($root_dir) );
is( ( stat $files[2] )[2] & 07777, _p(0), sprintf q{File '%s' created correctly}, $files[2]->relative($root_dir) );
is( ( stat $files[3] )[2] & 07777, _p(0644), sprintf q{File '%s' created correctly}, $files[3]->relative($root_dir) );
is( ( stat $files[4] )[2] & 07777, $dir_perm, sprintf q{Submodule '%s' created correctly}, $files[4]->relative($root_dir) );
return @files;
}
sub _create_submodule {
my $dir = path( tempdir() );
my $git = Git::Background->new($dir);
$git->run('init')->get;
my $file = $dir->child('file.txt');
$file->spew();
$git->run( 'add', 'file.txt' )->get;
$git->run( 'config', 'user.email', 'test@example.com' )->get;
$git->run( 'config', 'user.name', 'Test' )->get;
$git->run( 'commit', '-m', 'initial' )->get;
return $dir;
}
sub _test_with_defaults {
note('test with default configuration');
# Create a new "distribution".
#
# This copies the content of dist_root to a new directory: $tzil->root
my $tzil = Builder->from_config(
{ dist_root => tempdir() },
{
add_files => {
'source/dist.ini' => simple_ini(
'Git::GatherDir',
'Git::FilePermissions',
),
},
( run in 0.897 second using v1.01-cache-2.11-cpan-39bf76dae61 )