tags 222652 patch thanks Hello,
This patch implements the third solution. It solves some of the Lintian package-has-a-duplicate-relation warnings (http://lintian.debian.org/reports/Tpackage-has-a-duplicate-relation.html). It only simplifies the Depends field, but I think it should be sufficient. (I assumed there is no automatic variables for the other dependency fields; this can be changed easily) It does not simplify the dependencies between different fields (e.g. a package can Pre-Depends on foo and also Depends on foo). It does not simplify the dependencies with archs and ORed lists (e.g. Depends: foo | bar, bar (>= 2) could be simplified in Depends: bar (>= 2)). The simplification is done when the control file is written, after the variables were substituted (in outputclose). I tested the simplify_deps subroutine on an unstable_main_binary-i386_Packages. Kind Regards, -- Nekral
Index: controllib.pl =================================================================== --- controllib.pl (révision 239) +++ controllib.pl (copie de travail) @@ -168,6 +168,7 @@ $v =~ s/\s*,\s*$//; } $v =~ s/\$\{\}/\$/g; + $v = simplify_deps($f, $v); print("$f: $v\n") || &syserr("write error on control data"); } @@ -409,4 +410,157 @@ } } +# Simplify a dependency line by merging the dependencies on the same +# package. +sub simplify_deps { + my $dep_field=shift; + my $dep_line=shift; + + return $dep_line unless ($dep_field eq "Depends"); + + my $dep_list = parsedep($dep_line, 1, 0); + + # %pkg_dep keeps the versionned dependency associated with each package + my %pkg_dep; + # When the dependency can't be merged, it is pushed in @new_dep_list. + # Dependencies with a list of archs or an OR list are also push in + # this array. + my @new_dep_list; + foreach my $dep_and (@$dep_list) { + my $new_dep_and; + if (scalar(@$dep_and) > 1) { + # ORed list + push @new_dep_list, $dep_and; + } else { + my $alternate = [EMAIL PROTECTED]; + my ($package, $relation, $version, $arch_list)= @{$alternate}; + if (scalar(@$arch_list)) { + # Dependency with a list of archs + push @new_dep_list, $dep_and; + } else { + # Merge this dependency with the previous dependency of + # this package + my @versioned_deps = ($relation, $version); + my @new_deps = merge_depends($pkg_dep{$package}, + [EMAIL PROTECTED]); + if ((scalar @new_deps)>1) { + # The dependency could not be merged. Push both + # dependencies in @new_dep_list. + delete $pkg_dep{$package}; + my @arch_list = (); + foreach (@new_deps) { + my @new_alternate = ($package, [EMAIL PROTECTED], + [EMAIL PROTECTED], [EMAIL PROTECTED]); + my @or_list = ([EMAIL PROTECTED]); + push @new_dep_list, [EMAIL PROTECTED]; + } + } else { + $pkg_dep{$package} = $new_deps[0]; + } + } + } + } + # Push the merged dependencies + foreach my $pkg (keys %pkg_dep) { + my @versioned_deps = @{$pkg_dep{$pkg}}; + my @arch_list = (); + my @new_alternate = ($pkg, $versioned_deps[0], + $versioned_deps[1], [EMAIL PROTECTED]); + my @or_list = ([EMAIL PROTECTED]); + push @new_dep_list, [EMAIL PROTECTED]; + } + + return showdep([EMAIL PROTECTED], 1); +} + +# Merge two dependencies on the same package. +# The dependencies are provided as a reference to a (relation, version) +# array. +# +# Return a reference to an array. +# If the dependencies can be merged, this array will have one element: a +# reference to an (relation, version) array. +sub merge_depends { + my $versioned_dep1 = shift; + my $versioned_dep2 = shift; + my ($relation1, $version1) = @$versioned_dep1; + my ($relation2, $version2) = @$versioned_dep2; + + my @result = (); + return $versioned_dep2 if ( not defined $versioned_dep1 + or not defined $relation1); + return $versioned_dep1 if ( not defined $versioned_dep2 + or not defined $relation2); + + my @default = ($versioned_dep1, $versioned_dep2); + + if ($relation1 =~ m/</ and $relation2 =~ m/</) { + if (cmp_version($version1, $version2) < 0) { + @result = ($relation1, $version1); + } elsif ($version1 eq $version2) { + if ($relation1 eq "<<" or $relation2 eq "<<") { + @result = ("<<", $version1); + } else { + @result = ("<=", $version1); + } + } else { + @result = ($relation2, $version2); + } + return ([EMAIL PROTECTED]); + } elsif ($relation1 eq "=" or $relation2 eq "=") { + # Make sure the "=" relation is the first dependency + if ($relation2 eq "=") { + ($relation1, $relation2) = ($relation2, $relation1); + ($version1, $version2) = ($version2, $version1); + } + + my $cmp = cmp_version($version1, $version2); + # Detect unsatifiable conditions + if ($relation2 eq "<<") { + return @default if ($cmp >= 0); + } elsif ($relation2 eq "<=" or $relation2 eq "<") { + return @default if ($cmp > 0); + } elsif ($relation2 eq "=") { + return @default if ($cmp != 0); + } elsif ($relation2 eq ">=" or $relation2 eq ">") { + return @default if ($cmp < 0); + } elsif ($relation2 eq ">>") { + return @default if ($cmp <= 0); + } else { + return @default; + } + # Otherwise, just return the dependency on a fixed version + @result = ($relation1, $version1); + return ([EMAIL PROTECTED]); + } elsif ($relation1 =~ m/>/ and $relation2 =~ m/>/) { + if (cmp_version($version1, $version2) > 0) { + @result = ($relation1, $version1); + } elsif ($version1 eq $version2) { + if ($relation1 eq ">>" or $relation2 eq ">>") { + @result = (">>", $version1); + } else { + @result = (">=", $version1); + } + } else { + @result = ($relation2, $version2); + } + return ([EMAIL PROTECTED]); + } else { + # Either unsatisfiable or a bounded interval + return @default; + } +} + +# Compare two package versions. +# Return an integer less than, equal to, or greater than zero if the first +# version is found, respectively, to be less than, to match, or be greater +# than the second one. +sub cmp_version { + my ($v1, $v2) = (shift, shift); + + return 0 if ($v1 eq $v2); + system("dpkg", "--compare-versions", $v1, "lt", $v2); + return (($? >> 8) != 0)?1:-1; +} + 1;