aboutsummaryrefslogtreecommitdiff
path: root/SBO-Lib/lib/SBO/Lib/Repo.pm
diff options
context:
space:
mode:
Diffstat (limited to 'SBO-Lib/lib/SBO/Lib/Repo.pm')
-rw-r--r--SBO-Lib/lib/SBO/Lib/Repo.pm147
1 files changed, 123 insertions, 24 deletions
diff --git a/SBO-Lib/lib/SBO/Lib/Repo.pm b/SBO-Lib/lib/SBO/Lib/Repo.pm
index 35ed4c9..6c7babb 100644
--- a/SBO-Lib/lib/SBO/Lib/Repo.pm
+++ b/SBO-Lib/lib/SBO/Lib/Repo.pm
@@ -6,13 +6,17 @@ use warnings;
our $VERSION = '2.7.2';
-use SBO::Lib::Util qw/ %config prompt usage_error get_slack_version get_slack_version_url script_error open_fh open_read in _ERR_DOWNLOAD /;
+use SBO::Lib::Util qw/ %config prompt usage_error get_slack_version get_slack_version_key get_slack_version_url script_error open_fh open_read in _ERR_DOWNLOAD /;
+use SBO::Lib::Cryptography qw/ has_valid_gpg_signature verify_gpg_signed_file VALID_SIGNATURE /;
use Cwd;
use File::Copy;
use File::Find;
+use File::Temp "tempdir";
use File::Path qw/ make_path remove_tree /;
+use IPC::Open3;
use Sort::Versions;
+use Symbol "gensym";
use Exporter 'import';
@@ -211,9 +215,26 @@ sub generate_slackbuilds_txt {
return 1;
}
+sub latest_git_tag {
+ my $version = shift;
+ my $tag = '';
+
+ open(my $std_out, "git tag |") or die("dead");
+ while (my $line = <$std_out>) {
+ if ($line =~ /^$version-/) {
+ $tag = $line;
+ }
+ }
+ close($std_out);
+
+ chomp($tag);
+
+ return $tag;
+}
+
=head2 git_sbo_tree
- my $bool = git_sbo_tree($url);
+ my $bool = git_sbo_tree($url, $key_id);
C<git_sbo_tree()> will C<git clone> the repository specified by C<$url> to the
C<$repo_path> if the C<$url> repository isn't already there. If it is, it will
@@ -225,28 +246,62 @@ true value.
=cut
sub git_sbo_tree {
- script_error('git_sbo_tree requires an argument.') unless @_ == 1;
+ script_error('git_sbo_tree requires two arguments.') unless @_ == 2;
my $url = shift;
+ my $key_id = shift;
+
my $cwd = getcwd();
- my $res;
- if (-d "$repo_path/.git" and check_git_remote($repo_path, $url)) {
- _race::cond '$repo_path can be deleted after -d check';
- chdir $repo_path or return 0;
- $res = eval {
- die unless system(qw! git fetch !) == 0; # if system() doesn't return 0, there was an error
- _race::cond 'git repo could be changed or deleted here';
- die unless system(qw! git reset --hard origin !) == 0;
- unlink "$repo_path/SLACKBUILDS.TXT";
- 1;
- };
- } else {
+
+ if ((! -d "$repo_path/.git") || ! check_git_remote($repo_path, $url)) {
chdir $config{SBO_HOME} or return 0;
+
remove_tree($repo_path) if -d $repo_path;
- $res = system(qw/ git clone --no-local /, $url, $repo_path) == 0;
+ if (system(qw/ git clone --no-local /, $url, $repo_path)) {
+ return 0;
+ }
+ }
+
+ _race::cond '$repo_path can be deleted after -d check';
+ chdir($repo_path) or return 0;
+
+ return 0 unless system("git fetch") == 0;
+
+ unlink "$repo_path/SLACKBUILDS.TXT";
+
+ my $git_ref = 'origin';
+ my $verify_cmd = 'verify-commit';
+
+ my $tag = latest_git_tag(get_slack_version());
+ if ($tag ne '') {
+ $git_ref = $tag;
+ $verify_cmd = 'verify-tag';
+ }
+
+ if ($key_id) {
+ my @output;
+
+ print("Verifying $git_ref...\n");
+ open3(undef, undef, my $std_err = gensym, "git", $verify_cmd, "--raw", "$git_ref");
+ while (my $line = <$std_err>) {
+ push(@output, $line);
+ }
+ close($std_err);
+
+ if (! has_valid_gpg_signature(\@output, $key_id)) {
+ print(STDERR "Repository GPG verification failed.\n");
+
+ chdir $cwd;
+ return 0;
+ }
}
+
+ _race::cond 'git repo could be changed or deleted here';
+ return 0 unless system('git', 'reset', '--hard', $git_ref) == 0;
+
_race::cond '$cwd could be deleted here';
- return 1 if chdir $cwd and $res;
- return 0;
+ return 0 unless chdir $cwd;
+
+ return 1;
}
=head2 migrate_repo
@@ -292,14 +347,26 @@ sub pull_sbo_tree {
} else {
unlink($slackbuilds_txt);
}
+
+ my $key_id = '';
+ if ($config{GPG_KEY} ne 'FALSE') {
+ $key_id = $config{GPG_KEY};
+ };
+
my $res = 0;
if ($url =~ m!^rsync://!) {
- $res = rsync_sbo_tree($url);
+ $res = rsync_sbo_tree($url, $key_id);
} else {
- $res = git_sbo_tree($url);
+ $res = git_sbo_tree($url, $key_id);
}
- if ($res == 0) { warn "Could not sync from $url.\n"; exit _ERR_DOWNLOAD; }
+ if ($res == 0) {
+ warn "Could not sync from $url.\n";
+ if ($url eq 'https://github.com/Ponce/slackbuilds.git' && $key_id ne '') {
+ warn "This URL is known not to use GPG verification. You likely want to disable with 'sboconfig --gpg-key FALSE'."
+ }
+ exit _ERR_DOWNLOAD;
+ }
my $wanted = sub { chown 0, 0, $File::Find::name; };
find($wanted, $repo_path) if -d $repo_path;
@@ -310,7 +377,7 @@ sub pull_sbo_tree {
=head2 rsync_sbo_tree
- my $bool = rsync_sbo_tree($url);
+ my $bool = rsync_sbo_tree($url, $key_id);
C<rsync_sbo_tree()> syncs the SlackBuilds.org repository to C<$repo_path> from
the C<$url> provided.
@@ -319,14 +386,46 @@ the C<$url> provided.
# rsync the sbo tree from slackbuilds.org to $repo_path
sub rsync_sbo_tree {
- script_error('rsync_sbo_tree requires an argument.') unless @_ == 1;
+ script_error('rsync_sbo_tree requires two arguments.') unless @_ == 2;
+
my $url = shift;
$url .= '/' unless $url =~ m!/$!; # make sure $url ends with /
+ my $key_id = shift;
+
my @info;
# only slackware versions above 14.1 have an rsync that supports --info=progress2
if (versioncmp(get_slack_version(), '14.1') == 1) { @info = ('--info=progress2'); }
+
my @args = ('rsync', @info, '-a', '--delete', $url);
- return system(@args, $repo_path) == 0;
+ return 0 unless system(@args, $repo_path) == 0;
+
+ my $cwd = getcwd();
+ chdir($repo_path);
+
+ if ($key_id) {
+ if (versioncmp(get_slack_version(), '14.1') == -1) {
+ print("GPG verification is not present for 14.0 and earlier. You should consider disabling GPG verification.")
+ }
+
+ print("Verifying CHECKSUMS.md5...\n");
+ my $res = verify_gpg_signed_file('CHECKSUMS.md5.asc', $key_id);
+ if ($res ne VALID_SIGNATURE) {
+ print(STDERR "Respository CHECKSUMS.md5 GPG verification failed.\n");
+
+ chdir($cwd);
+ return 0;
+ }
+ }
+
+ if ( -e "CHECKSUMS.md5" ) {
+ print("Verifying file integrity using CHECKSUMS.md5...\n");
+ if (system('tail +13 CHECKSUMS.md5 | md5sum -c --quiet -')) {
+ chdir($cwd);
+ return 0;
+ }
+ }
+
+ return chdir($cwd);
}
=head2 slackbuilds_or_fetch