Look at each fix on the branch to identify if it is a recorded
cherry-pick from the fixes known for the master branch

If all fixes from master are cherry-picked to the branch, then look at
tags on the branch to identify if a bug fix release has been made
containing all the fixes.

Signed-off-by: Daniel P. Berrangé <[email protected]>
---
 scripts/report-vulnerable-tags.pl | 69 +++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/scripts/report-vulnerable-tags.pl 
b/scripts/report-vulnerable-tags.pl
index 43f344a..6a0f7dc 100644
--- a/scripts/report-vulnerable-tags.pl
+++ b/scripts/report-vulnerable-tags.pl
@@ -99,6 +99,28 @@ sub get_branches {
     return @branches;
 }
 
+sub get_cherry_picks {
+    my $branch = shift @_;
+    my $tag = shift @_;
+
+    open GIT, "-|", "git", "log", "$tag..origin/$branch" or
+       die "cannot query 'git log $tag..origin/$branch': $!\n";
+
+    my $commit;
+    my %cherrypicks;
+    while (<GIT>) {
+       chomp;
+
+       if (/^commit ([a-zA-Z0-9]+)/) {
+           $commit = $1;
+       } elsif (/cherry picked from commit ([a-zA-Z0-9]+)/) {
+           $cherrypicks{$1} = $commit;
+       }
+    }
+
+    return %cherrypicks;
+}
+
 sub add_branch {
     my $name = shift @_;
 
@@ -177,7 +199,54 @@ if (defined $broken) {
     for my $branch (get_branches($broken)) {
        add_branch($branch);
     }
+}
+
+if (defined $fixed) {
+    # Try to match up fixed commit with cherry-picks
+    for my $branch (sort versioncmp keys %branches) {
+       next if $branch eq "master";
+
+       my $basetag = $branch;
+       $basetag =~ s/-maint//;
+       my @bits = split /\./, $basetag;
+
+       if (int(@bits) == 2) {
+           $basetag = $basetag . ".0";
+       }
+
+       my %cherrypicks = get_cherry_picks($branch, $basetag);
+
+       my @missing;
+       for my $commit (@fixed) {
+           if (exists $cherrypicks{$commit}) {
+               my $cherry = $cherrypicks{$commit};
+               add_fixed_commit($branch, $cherry);
+           } else {
+               push @missing, $commit;
+           }
+       }
+
+       # If all fixes on master exist on branch, then
+       # identify any tags holding the last cherry-pick
+       # so the branch gets marked as non-vulnerable.
+       if (int(@missing) == 0) {
+           my $bfixed = 
$branches{$branch}->{fixedchanges}->[$#{$branches{$branch}->{fixedchanges}}];
+           # Mark any tags containing the fix as known so they
+           # get excluded when later finding vulnerable tags
+           for my $tag (get_tags("--contains", $bfixed)) {
+               $tags{$tag} = 0;
+           }
+
+           # Record the first tag in master which has the fix, if any
+           my @fixedtags = sort versioncmp get_tags("--contains", $bfixed, 
"--merged", $branch);
+           if (int(@fixedtags)) {
+               add_fixed_tag($branch, $fixedtags[0]);
+           }
+       }
+    }
+}
 
+if (defined $broken) {
     # Now we need slower work to find branches for
     # few remaining tags
     for my $tag (get_tags("--contains", $broken)) {
-- 
2.21.0

--
libvir-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to