1039 circular dependency in packages is detected at install-time
1071 fmri.is_successor() doesn't handle missing versions correctly
1097 fmri precedence order wrong in image.load_optional_dependencies()
1100 .pyc files are not sufficiently advanced (in time)
--- a/src/modules/actions/file.py Thu Apr 10 18:24:14 2008 -0700
+++ b/src/modules/actions/file.py Fri Apr 11 10:45:04 2008 -0700
@@ -137,6 +137,18 @@
# This is safe even if temp == final_path.
portable.rename(temp, final_path)
+ # XXX .pyc files are causing problems because they're not enough
+ # newer than the .py files.... if we just installed a .pyc
+ # file, move its modification time into the future to prevent
+ # python commands running as root from updating these files
+ # because they look out of date... the right fix is to fix
+ # Solaris python to look at the entire timestamp.... pending.
+ # in the mean time, this "accomodation" has to be made to
+ # prevent pkg verify errors.
+ if final_path.endswith(".pyc"):
+ t = os.stat(final_path)[ST_MTIME] + 5 # magic
+ os.utime(final_path, (t, t))
+
def verify(self, img, **args):
""" verify that file is present and if preserve attribute
not present, that hashes match"""
--- a/src/modules/actions/legacy.py Thu Apr 10 18:24:14 2008 -0700
+++ b/src/modules/actions/legacy.py Fri Apr 11 10:45:04 2008 -0700
@@ -86,13 +86,13 @@
pfile.write("%s=%s\n" % (k, v))
pfile.close()
- # create hardlink to pkginfo file for this pkg; may be
- # there already on upgrade
+ # create another hardlink to pkginfo file if
+ # this is not just an upgrade; we use this to make
+ # uninstall easier
- linkfile = os.path.join(pkgdir,
- "pkginfo." + pkgplan.destination_fmri.get_url_path())
-
- if not os.path.isfile(linkfile):
+ if not orig:
+ linkfile = os.path.join(pkgdir,
+ "pkginfo.%d" % (os.stat(pkginfo)[ST_NLINK] + 1))
os.link(pkginfo, linkfile)
# the svr4 pkg commands need contents file to work, but the
@@ -110,7 +110,7 @@
os.chmod(pkginfo, 0644)
- def verify(self, img, **args):
+ def verify(self, img, **args):
pkgdir = os.path.join(img.get_root(), "var/sadm/pkg",
self.attrs["pkg"])
@@ -133,17 +133,20 @@
pkgdir = os.path.join(pkgplan.image.get_root(), "var/sadm/pkg",
self.attrs["pkg"])
- linkfile = os.path.join(pkgdir,
- "pkginfo." + pkgplan.origin_fmri.get_url_path())
-
- if os.stat(linkfile)[ST_NLINK] == 2:
- try:
- os.unlink(os.path.join(pkgdir, "pkginfo"))
- except OSError, e:
- if e.errno not in (errno.EEXIST, errno.ENOENT):
- # can happen if all refs deleted
- raise # in same pkg invocation
- os.unlink(linkfile)
+ pkginfo = os.path.join(pkgdir, "pkginfo")
+
+ if os.path.isfile(pkginfo):
+ link_count = os.stat(pkginfo)[ST_NLINK]
+ linkfile = os.path.join(pkgdir,
+ "pkginfo.%d" % (link_count))
+
+ if os.path.isfile(linkfile):
+ os.unlink(linkfile)
+
+ # do this conditionally to be kinder
+ # to installations done w/ older versions
+ if link_count == 2: # last one
+ os.unlink(pkginfo)
def generate_indices(self):
return {
--- a/src/modules/client/image.py Thu Apr 10 18:24:14 2008 -0700
+++ b/src/modules/client/image.py Fri Apr 11 10:45:04 2008 -0700
@@ -937,7 +937,7 @@
self.fmri_set_default_authority(myfmri)
ofmri = self.optional_dependencies.get(name, None)
- if not ofmri or self.fmri_is_successor(ofmri, myfmri):
+ if not ofmri or self.fmri_is_successor(myfmri, ofmri):
self.optional_dependencies[name] = myfmri
def apply_optional_dependencies(self, myfmri):
@@ -955,7 +955,7 @@
if not minfmri:
return myfmri
- if not myfmri.has_version() or self.fmri_is_successor(minfmri, myfmri):
+ if self.fmri_is_successor(minfmri, myfmri):
return minfmri
return myfmri
--- a/src/modules/client/imageplan.py Thu Apr 10 18:24:14 2008 -0700
+++ b/src/modules/client/imageplan.py Fri Apr 11 10:45:04 2008 -0700
@@ -97,10 +97,7 @@
def is_proposed_fmri(self, fmri):
for pf in self.target_fmris:
if self.image.fmri_is_same_pkg(fmri, pf):
- if not self.image.fmri_is_successor(fmri, pf):
- return True
- else:
- return False
+ return not self.image.fmri_is_successor(fmri, pf)
return False
def is_proposed_rem_fmri(self, fmri):
@@ -123,7 +120,7 @@
#
fmri = self.image.apply_optional_dependencies(fmri)
-
+
# Add fmri to target list only if it (or a successor) isn't
# there already.
for i, p in enumerate(self.target_fmris):
--- a/src/modules/fmri.py Thu Apr 10 18:24:14 2008 -0700
+++ b/src/modules/fmri.py Fri Apr 11 10:45:04 2008 -0700
@@ -287,6 +287,8 @@
return self.pkg_name == fmri.pkg_name
def is_successor(self, fmri):
+ """ returns True if self > fmri """
+
if not self.pkg_name == fmri.pkg_name:
return False
@@ -294,10 +296,10 @@
return False
if fmri.version == None:
- return False
+ return True
if self.version == None:
- return True
+ return False
if self.version < fmri.version:
return False
--- a/src/tests/cli-complete.py Thu Apr 10 18:24:14 2008 -0700
+++ b/src/tests/cli-complete.py Fri Apr 11 10:45:04 2008 -0700
@@ -45,6 +45,7 @@
#
def maketests():
import cli.t_actions
+ import cli.t_circular_dependencies
import cli.t_depot
import cli.t_depotcontroller
import cli.t_image_create
@@ -65,6 +66,7 @@
cli.t_pkg_list.TestPkgList,
cli.t_commandline.TestCommandLine,
cli.t_upgrade.TestUpgrade,
+ cli.t_circular_dependencies.TestCircularDependencies,
cli.t_rename.TestRename ]
for t in tests:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/cli/t_circular_dependencies.py Fri Apr 11 10:45:04 2008 -0700
@@ -0,0 +1,105 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+
+import testutils
+if __name__ == "__main__":
+ testutils.setup_environment("../../../proto")
+
+import os
+import unittest
+
+class TestCircularDependencies(testutils.SingleDepotTestCase):
+
+ pkg10 = """
+ open [email protected],5.11-0
+ add depend type=require fmri=pkg:/pkg2
+ close
+ """
+
+ pkg20 = """
+ open [email protected],5.11-0
+ add depend type=require fmri=pkg:/pkg3
+ close
+ """
+
+ pkg30 = """
+ open [email protected],5.11-0
+ add depend type=require fmri=pkg:/pkg1
+ close
+ """
+
+
+ pkg11 = """
+ open [email protected],5.11-0
+ add depend type=require fmri=pkg:/[email protected]
+ close
+ """
+
+ pkg21 = """
+ open [email protected],5.11-0
+ add depend type=require fmri=pkg:/[email protected]
+ close
+ """
+
+ pkg31 = """
+ open [email protected],5.11-0
+ add depend type=require fmri=pkg:/[email protected]
+ close
+ """
+
+ def test_unanchored_circular_dependencies(self):
+ """ check to make sure we can install
+ circular dependencies w/o versions
+ """
+
+ # Send 1.0 versions of packages.
+ durl = self.dc.get_depot_url()
+ self.pkgsend_bulk(durl, self.pkg10)
+ self.pkgsend_bulk(durl, self.pkg20)
+ self.pkgsend_bulk(durl, self.pkg30)
+
+ self.image_create(durl)
+ self.pkg("install pkg1")
+ self.pkg("list")
+ self.pkg("verify -v")
+
+ def test_anchored_circular_dependencies(self):
+ """ check to make sure we can install
+ circular dependencies w/ versions
+ """
+
+ # Send 1.0 versions of packages.
+ durl = self.dc.get_depot_url()
+ self.pkgsend_bulk(durl, self.pkg11)
+ self.pkgsend_bulk(durl, self.pkg21)
+ self.pkgsend_bulk(durl, self.pkg31)
+
+ self.image_create(durl)
+ self.pkg("install pkg1")
+ self.pkg("list")
+ self.pkg("verify -v")
+
+if __name__ == "__main__":
+ unittest.main()
--- a/src/tests/cli/t_upgrade.py Thu Apr 10 18:24:14 2008 -0700
+++ b/src/tests/cli/t_upgrade.py Fri Apr 11 10:45:04 2008 -0700
@@ -46,6 +46,19 @@
close
"""
+ incorpA = """
+ open [email protected],5.11-0
+ add depend type=incorporate fmri=pkg:/[email protected]
+ add depend type=incorporate fmri=pkg:/[email protected]
+ close
+ """
+
+ incorpB = """
+ open [email protected],5.11-0
+ add depend type=incorporate fmri=pkg:/[email protected]
+ add depend type=incorporate fmri=pkg:/[email protected]
+ close
+ """
amber10 = """
open [email protected],5.11-0
@@ -102,6 +115,7 @@
add file /tmp/bronze2 mode=0444 owner=root group=bin path=/etc/amber2
add license /tmp/copyright3 license=copyright
add file /tmp/bronzeA2 mode=0444 owner=root group=bin path=/A1/B2/C3/D4/E5/F6/bronzeA2
+ add depend fmri=pkg:/[email protected] type=require
close
"""
@@ -182,9 +196,27 @@
self.pkg("verify -v")
# make sure all directories are gone save /var in test image
- print os.listdir(self.get_img_path())
self.assert_(os.listdir(self.get_img_path()) == ["var"])
+ def test_upgrade2(self):
+
+ # Send all pkgs
+
+ durl = self.dc.get_depot_url()
+ self.pkgsend_bulk(durl, self.incorpA)
+ self.pkgsend_bulk(durl, self.amber10)
+ self.pkgsend_bulk(durl, self.bronze10)
+ self.pkgsend_bulk(durl, self.incorpB)
+ self.pkgsend_bulk(durl, self.amber20)
+ self.pkgsend_bulk(durl, self.bronze20)
+
+ self.image_create(durl)
+ self.pkg("install incorpA")
+ self.pkg("install incorpB")
+ self.pkg("install bronze")
+ self.pkg("list [email protected]")
+ self.pkg("verify -v")
+
if __name__ == "__main__":
unittest.main()