You are not logged in.

#1 2009-09-03 04:41:13

Xyne
Administrator/PM
Registered: 2008-08-03
Posts: 6,963
Website

A script to help find the cause of recent upgrade breakage

This script accepts package names as arguments and will output both a full dependency tree for each package, including installation dates of each dependency, and a list of all dependencies arranged by installation date in descending order along with a string to show the dependency chain for that dep.

This is useful for determining which package upgrade is responsible for recent breakage as it should enable you to quickly determine which package upgrade coincides with the start of the issue.

This script was inspired by a recent issue with sylpheed which was tracked down to an upgrade of a dep of a dep.

The output is colored. If you don't like it, just change the variables at the top.

I'll probably add this to pacpal sometime soon.

#!/usr/bin/perl
use strict;
use warnings;

use Term::ANSIColor;

my $pkgname_color = 'bold yellow';
my $timestamp_color = 'bold cyan';
my $depchain_color = 'blue';

my $pkgs = {};
my $pkgname = '';
my $type = '';
my @deps = ();
my @provides = ();
my $date = '';
foreach my $line ( split(/\n/, `LC_ALL=C pacman -Qi`) )
{
  if ($line =~ m/^Name\s+:\s+(.*\S)\s*$/)
  {
    if ($pkgname ne '')
    {
      $pkgs->{$pkgname}->{'date'} = $date;
      $pkgs->{$pkgname}->{'deps'} = [grep {$_ ne 'None'} @deps];
      foreach my $prov (@provides)
      {
        if (not defined($pkgs->{$prov}))
        {
          $pkgs->{$prov} = $pkgs->{$pkgname};
        }
      }
    }
    $pkgname = $1;
    $date = '';
    $type = '';
    @deps = ();
  }
  elsif ($line =~ m/^Depends On\s+:\s+(.*\S)\s*$/)
  {
    $type = 'dep';
    push (@deps, split(/\s+/, $1));
  }
  elsif ($type eq 'dep' and $line =~ m/^\s+(.*\S)\s*$/)
  {
    push(@deps, split(/\s+/, $1));
  }
  elsif ($line =~ m/^Provides\s+:\s+(.*\S)\s*$/)
  {
    $type = 'provide';
    push (@provides, split(/\s+/, $1));
  }
  elsif ($type eq 'provide' and $line =~ m/^\s+(.*\S)\s*$/)
  {
    push(@provides, split(/\s+/, $1));
  }
  elsif ($line =~ m/^Install Date\s+:\s+(.*\S)\s*$/)
  {
    $date = &get_timestamp($1);
    $type = '';
  }
  else
  {
    $type = '';
  }
}
if ($pkgname ne '')
{
  $pkgs->{$pkgname}->{'date'} = $date;
  $pkgs->{$pkgname}->{'deps'} = [grep {$_ ne 'None'} @deps];
  foreach my $prov (@provides)
  {
    if (not defined($pkgs->{$prov}))
    {
      $pkgs->{$prov} = $pkgs->{$pkgname};
    }
  }
}

sub display_dep_dates()
{
  my ($pkg, $i, $checked, $deps, $chain) = @_;
  my %copy = %{ $checked };
  $checked = \%copy;
  $pkg =~ s/[=<>].+$//;
  # prevent infinite recursion for cyclic dependencies
  return if defined($checked->{$pkg});
  $checked->{$pkg}++;
  my $indent = '  ' x $i;
  if (defined($pkgs->{$pkg}))
  {
    print $indent, (color $pkgname_color), $pkg, (color 'reset'), ' : ', (color $timestamp_color),  $pkgs->{$pkg}->{'date'}, (color 'reset'), "\n";
    if (not defined($deps->{$pkg}))
    {
      $deps->{$pkg}->{'date'} = $pkgs->{$pkg}->{'date'} ;
      $deps->{$pkg}->{'chain'} = $chain ;
    }
  }
  $i++;
  $chain = ($chain eq '') ? $pkg : $chain .' -> '. $pkg;
  foreach my $dep (@{ $pkgs->{$pkg}->{'deps'} })
  {
    $deps = &display_dep_dates($dep, $i, $checked, $deps, $chain);
  }
  return $deps;
}

foreach my $arg (@ARGV)
{
  print "DEPENDENCY TREE ($arg)\n";
  my $deps = &display_dep_dates($arg, 0, {}, {}, '');
  print "\n\n";
  print "DEPENDENCIES BY INSTALLATION DATE ($arg)\n";
  foreach my $pkg (sort {$deps->{$b}->{'date'} cmp $deps->{$a}->{'date'}} keys(%{$deps}))
  {
    my $timestamp = (color $timestamp_color) . '[' . $deps->{$pkg}->{'date'} . ']';
    my $chain = $deps->{$pkg}->{'chain'};
    $chain = (color $depchain_color) .  '(' . $chain . ')' if $chain ne '';
    $pkg = (color $pkgname_color) . $pkg;
    print "$timestamp $pkg $chain\n", (color 'reset');
  }
  print "\n\n\n\n\n";
}

sub get_timestamp()
{
  my $str = $_[0];
  my %month_hash;
  @month_hash{qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/} = (1..12);
  my ($month,$date,$hms,$year) = $str =~ m/^\S+\s+(\S+)\s+(\d+)\s+(\d+:\d+:\d+)\s+(\S+)\s*$/;
  return sprintf "%s-%02d-%02d %8s",$year,$month_hash{$month},$date,$hms;
}

My Arch Linux StuffForum EtiquetteCommunity Ethos - Arch is not for everyone

Offline

#2 2009-09-03 06:05:43

ugkbunb
Member
Registered: 2009-02-26
Posts: 227

Re: A script to help find the cause of recent upgrade breakage

It seems to work fine... but it spits out this error/warning with the rest of the info....

DEPENDENCIES BY INSTALLATION DATE (nvidia)
Use of uninitialized value in string comparison (cmp) at /home/geota/bin/pkginfo line 113.
Use of uninitialized value in string comparison (cmp) at /home/geota/bin/pkginfo line 113.
Use of uninitialized value in string comparison (cmp) at /home/geota/bin/pkginfo line 113.
Use of uninitialized value in string comparison (cmp) at /home/geota/bin/pkginfo line 113.
Use of uninitialized value in string comparison (cmp) at /home/geota/bin/pkginfo line 113.
Use of uninitialized value in string comparison (cmp) at /home/geota/bin/pkginfo line 113.
Use of uninitialized value in string comparison (cmp) at /home/geota/bin/pkginfo line 113.
Use of uninitialized value in string comparison (cmp) at /home/geota/bin/pkginfo line 113.
Use of uninitialized value in string comparison (cmp) at /home/geota/bin/pkginfo line 113.
[2009-08-26 00:20:46] xf86-input-evdev (nvidia -> nvidia-utils-beta -> xorg-server)
[2009-08-24 14:12:27] coreutils (nvidia -> nvidia-utils-beta -> xorg-server -> openssl -> perl)

Offline

#3 2009-09-03 06:20:03

Xyne
Administrator/PM
Registered: 2008-08-03
Posts: 6,963
Website

Re: A script to help find the cause of recent upgrade breakage

I can't reproduce that for nvidia.

Try inserting this just before the current line at 113

while (my ($k,$v) = each(%{$deps}))
{
  print "$k is missing a date\n" if not defined($v->{'date'});
}

then grep the output for "missing a date" and post it.

You could also pastebin the output of "LC_ALL=C pacman -Qi" and post a link to it so that I can reproduce the error.


My Arch Linux StuffForum EtiquetteCommunity Ethos - Arch is not for everyone

Offline

Board footer

Powered by FluxBB