Update of /cvsroot/fink/fink/perlmod/Fink
In directory sc8-pr-cvs1:/tmp/cvs-serv10155

Modified Files:
      Tag: shlibs
        ChangeLog Shlibs.pm 
Log Message:
changelog says it all -- deduplication voodoo


Index: ChangeLog
===================================================================
RCS file: /cvsroot/fink/fink/perlmod/Fink/ChangeLog,v
retrieving revision 1.305.2.6
retrieving revision 1.305.2.7
diff -u -d -r1.305.2.6 -r1.305.2.7
--- ChangeLog   11 Jul 2003 21:39:06 -0000      1.305.2.6
+++ ChangeLog   15 Jul 2003 01:16:21 -0000      1.305.2.7
@@ -1,3 +1,9 @@
+2003-07-14  Benjamin Reed  <[EMAIL PROTECTED]>
+
+       * Shlibs.pm: Evil, scary voodoo to remove duplicates in dependency
+         specifications.  I tried to document the heck out of it, but it's
+         still pretty freakish.  Handle with care.  :)
+
 2003-07-11  Justin F. Hallett  <[EMAIL PROTECTED]>
 
        * Shlibs.pm: Added new file to deal with all the shlibs functions

Index: Shlibs.pm
===================================================================
RCS file: /cvsroot/fink/fink/perlmod/Fink/Attic/Shlibs.pm,v
retrieving revision 1.1.2.8
retrieving revision 1.1.2.9
diff -u -d -r1.1.2.8 -r1.1.2.9
--- Shlibs.pm   13 Jul 2003 18:04:44 -0000      1.1.2.8
+++ Shlibs.pm   15 Jul 2003 01:16:21 -0000      1.1.2.9
@@ -24,7 +24,7 @@
 
 package Fink::Shlibs;
 use Fink::Base;
-use Fink::Services qw(&print_breaking);
+use Fink::Services qw(&print_breaking &version_cmp);
 use Fink::Config qw($config $basepath);
 use File::Find;
 use Fcntl ':mode'; # for search_comparedb
@@ -108,13 +108,186 @@
     close (OTOOL);
   }
 
-  ### FIXME
-  ### add code to go through the array and split by , then by |
-  ### then seperate by pkg name and versions and then reassemble
-  ### and each pkg may only be listed once, with the highest reported
-  ### version
+  print "DEBUG: before deduplication: ", join(', ', @depends), "\n";
+
+  # this next bit does some really strange voodoo, I will try to
+  # explain how it works.
+
+  # first, there is a hash that contains a list of <package>,<operator>
+  # tuples -- we use this for determining if a package is mentioned
+  # multiple times.  We need to consider <package>,<operator> as a
+  # unique key because of cases like:
+  #
+  #   Depends: macosx (>= 10.1), macosx (<< 10.4)
+
+  my $depvers = {};
+
+  # next, there is an array that keeps a cooked version of the input
+  # dependency list, with "<package> (<operator> <version>)" transformed
+  # into "<package>,<operator>" -- this retains the order, as well as
+  # any combinations of foo|bar|baz and so on, for the purposes of
+  # recreating it later.
+
+  my @newdeps;
+
+  # so, first we go through each depend, turn it into an object that
+  # contains versioning information and such, and then fills in the
+  # $depvers hash and @newdeps array.
+
+  for my $dep (@depends) {
+    my @depobj = get_depobj($dep);
+    my $name;
+
+    # get_depobj() returns multiple entries when the source depend
+    # is a foo|bar|baz style dependency (ie alternates)
+    # for each one of these we want to strip it down to a
+    # @newdeps-style array, and pump each of the individual deps
+    # into the $depvers hash.
+
+    if (@depobj > 1) {
+      my @depnames;
+      for my $obj (@depobj) {
+        push(@depnames, $obj->{tuplename});
+      }
+      $name = join('|', @depnames);
+      undef @depnames;
+      for my $obj (@depobj) {
+        $depvers = update_version_hash($depvers, $obj);
+      }
+    } else {
+      $name = $depobj[0]->{tuplename};
+      $depvers = update_version_hash($depvers, $depobj[0]);
+    }
+    # this will skip putting something into @newdeps if it's
+    # already there (it has to match the <package>,<operator>
+    # tuple exactly, not just the package name, to be
+    # considered a duplicate
+    if (not grep($_ eq $name, @newdeps)) {
+      push(@newdeps, $name);
+    }
+  }
+
+  @depends = ();
+
+  # now, we parse through the cooked data, and generate a new
+  # dependency list, with duplicates removed because of the
+  # skip above, and any matching version comparisons for a given
+  # package should all be in parity
+
+  for my $depspec (@newdeps) {
+    if ($depspec =~ /\|/) {
+
+      # if it's a multiple, we chop it up and transform each
+      # part into it's "real" comparison, and then put it back
+      # together and stick it on the new @depends
+
+      my @splitdeps = split(/\|/, $depspec);
+
+      for my $index (0..$#splitdeps) {
+
+        if (defined $depvers->{$splitdeps[$index]}->{operator}) {
+          # operator is undefined if there was no version comparison
+          $splitdeps[$index] = $depvers->{$splitdeps[$index]}->{name} . ' (' . 
$depvers->{$splitdeps[$index]}->{operator} . ' ' . 
$depvers->{$splitdeps[$index]}->{version} . ')';
+        } else {
+          $splitdeps[$index] = $depvers->{$splitdeps[$index]}->{name};
+        }
+      }
+      push(@depends, join(' | ', @splitdeps));
+    } else {
 
+      # otherwise we just transform the single entry and push
+      # it on the depends array
+
+      if (defined $depvers->{$depspec}->{operator}) {
+        # operator is undefined if there was no version comparison
+        push(@depends, $depvers->{$depspec}->{name} . ' (' . 
$depvers->{$depspec}->{operator} . ' ' . $depvers->{$depspec}->{version} . ')');
+      } else {
+        push(@depends, $depvers->{$depspec}->{name});
+      }
+    }
+  }
+
+  print "DEBUG: after deduplication: ", join(', ', @depends), "\n";
   return @depends;
+}
+
+# this is a scary subroutine to update the name,operator cache
+# for handling duplicates -- it's just plain evil.  EVIL. EEEEVIIIILLLL.
+sub update_version_hash {
+  my $hash   = shift;
+  my $depobj = shift;
+
+  if (exists $hash->{$depobj->{tuplename}}) {
+    # if the name,operator pair exists in the dep cache hash
+    if ($depobj->{operator} =~ /^==?$/ and
+        $depobj->{version} ne $hash->{$depobj->{tuplename}}->{version}) {
+      # can't have 2 different versions in an == comparison for the
+      # same dependency (ie, Depends: macosx = 10.2-1, macosx = 10.3-1)
+      warn "this package depends on ", $depobj->{name}, " = ", $depobj->{version}, " 
*and* ",
+        $depobj->{name}, " = ", $hash->{$depobj->{tuplename}}->{version}, "!!!\n";
+    } elsif (version_cmp($depobj->{version}, $depobj->{operator}, 
$hash->{$depobj->{tuplename}}->{version})) {
+      # according to the operator, this new dependency is more "specific"
+      $hash->{$depobj->{tuplename}} = $depobj;
+    }
+  } elsif ($depobj->{tuplename} eq $depobj->{name}) {
+    my @matches = grep(/^$depobj->{name}\,/, keys %{$hash});
+    if (@matches > 0) {
+      # $depobj has no version dep, but a versioned dependency
+      # already exists in the object cache -- take the first match
+      $hash->{$depobj->{tuplename}} = $hash->{$matches[0]};
+
+      if (@matches > 1) {
+        warn "more than one version comparison exists for ", $depobj->{name}, "!!!\n",
+          "taking ", $hash->{$matches[0]}->{tuplename}, "\n";
+      }
+    } else {
+      # $depobj isn't in the cache (versioned or not)
+      $hash->{$depobj->{tuplename}} = $depobj;
+    }
+  } elsif (grep(/^$depobj->{name}$/, keys %{$hash})) {
+    # $depobj has a versioned dep, but an unversioned dependency
+    # already exists in the object cache -- we need to update the
+    # previous one
+    $hash->{$depobj->{tuplename}} = $depobj;
+    $hash->{$depobj->{name}}      = $depobj;
+  } else {
+    # if the tuple doesn't exist, we add it
+    $hash->{$depobj->{tuplename}} = $depobj;
+  }
+
+  return $hash;
+}
+
+# get a dependency "object" (just a data structure with dep info)
+sub get_depobj {
+  my $depdef = shift;
+  my @return;
+
+  # this seems weird, but splitting when there isn't a "|" will
+  # just give a 1-entry array, so it works even in the case there's
+  # no multiple comparison (ie, "foo|bar")
+
+  for my $dep (split(/\s*\|\s*/, $depdef)) {
+    $dep =~ s/[\r\n\s]+/ /;
+    $dep =~ s/^\s+//;
+    $dep =~ s/\s+$//;
+    my $depobj;
+    if (my ($name, $operator, $version) = $dep =~ 
/^\s*(.+?)\s+\(([\<\>\=]+)\s+(\S+)\)\s*$/) {
+      $depobj->{name}      = $name;
+      $depobj->{operator}  = $operator;
+      $depobj->{version}   = $version;
+      $depobj->{tuplename} = $name . ',' . $operator;
+      #$depobj->{tuplename} = $name;
+    } else {
+      $depobj->{name}      = $dep;
+      $depobj->{operator}  = undef;
+      $depobj->{version}   = '0-0';
+      $depobj->{tuplename} = $dep;
+    }
+    push(@return, $depobj);
+  }
+
+  return @return;
 }
 
 ### get package name




-------------------------------------------------------
This SF.Net email sponsored by: Parasoft
Error proof Web apps, automate testing & more.
Download & eval WebKing and get a free book.
www.parasoft.com/bulletproofapps1
_______________________________________________
Fink-commits mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/fink-commits

Reply via email to