Be more selective about what packages we remove so that we can detect conflicts.

Right now, the preflight queue unmerges all changed packages prior to
upgrading them. This is done to ensure that any lingering state from
failed package uprevs is cleaned up.

This change updates cros_mark_as_stable to be more selective. This both improves
speed and allows for more conflicts to be detected.

Change-Id: I3134918eb16b41e8882c8af1f1bdf9052bafd9ad

BUG=chromium-os:10127
TEST=Test uprev. Run unit tests.

Review URL: http://codereview.chromium.org/5513012
This commit is contained in:
David James 2010-12-21 12:46:46 -08:00
parent 6b69ba7121
commit 702f0e31ca
2 changed files with 43 additions and 29 deletions

View File

@ -78,15 +78,15 @@ def _Print(message):
Info(message) Info(message)
def _CleanStalePackages(board, package_array): def _CleanStalePackages(board, package_atoms):
"""Cleans up stale package info from a previous build.""" """Cleans up stale package info from a previous build."""
Info('Cleaning up stale packages %s.' % package_array) Info('Cleaning up stale packages %s.' % package_atoms)
unmerge_board_cmd = ['emerge-%s' % board, '--unmerge'] unmerge_board_cmd = ['emerge-%s' % board, '--unmerge']
unmerge_board_cmd.extend(package_array) unmerge_board_cmd.extend(package_atoms)
RunCommand(unmerge_board_cmd) RunCommand(unmerge_board_cmd)
unmerge_host_cmd = ['sudo', 'emerge', '--unmerge'] unmerge_host_cmd = ['sudo', 'emerge', '--unmerge']
unmerge_host_cmd.extend(package_array) unmerge_host_cmd.extend(package_atoms)
RunCommand(unmerge_host_cmd) RunCommand(unmerge_host_cmd)
RunCommand(['eclean-%s' % board, '-d', 'packages'], redirect_stderr=True) RunCommand(['eclean-%s' % board, '-d', 'packages'], redirect_stderr=True)
@ -319,15 +319,15 @@ class EBuild(object):
"""Sets up data about an ebuild from its path.""" """Sets up data about an ebuild from its path."""
from portage.versions import pkgsplit from portage.versions import pkgsplit
unused_path, self.category, self.pkgname, filename = path.rsplit('/', 3) unused_path, self.category, self.pkgname, filename = path.rsplit('/', 3)
unused_pkgname, version_no_rev, rev = pkgsplit( unused_pkgname, self.version_no_rev, rev = pkgsplit(
filename.replace('.ebuild', '')) filename.replace('.ebuild', ''))
self.ebuild_path_no_version = os.path.join( self.ebuild_path_no_version = os.path.join(
os.path.dirname(path), self.pkgname) os.path.dirname(path), self.pkgname)
self.ebuild_path_no_revision = '%s-%s' % (self.ebuild_path_no_version, self.ebuild_path_no_revision = '%s-%s' % (self.ebuild_path_no_version,
version_no_rev) self.version_no_rev)
self.current_revision = int(rev.replace('r', '')) self.current_revision = int(rev.replace('r', ''))
self.version = '%s-%s' % (version_no_rev, rev) self.version = '%s-%s' % (self.version_no_rev, rev)
self.package = '%s/%s' % (self.category, self.pkgname) self.package = '%s/%s' % (self.category, self.pkgname)
self.ebuild_path = path self.ebuild_path = path
@ -454,17 +454,19 @@ class EBuildStableMarker(object):
OSError: Error occurred while creating a new ebuild. OSError: Error occurred while creating a new ebuild.
IOError: Error occurred while writing to the new revved ebuild file. IOError: Error occurred while writing to the new revved ebuild file.
Returns: Returns:
True if the revved package is different than the old ebuild. If the revved package is different than the old ebuild, return the full
revved package name, including the version number. Otherwise, return None.
""" """
if self._ebuild.is_stable: if self._ebuild.is_stable:
new_stable_ebuild_path = '%s-r%d.ebuild' % ( stable_version_no_rev = self._ebuild.version_no_rev
self._ebuild.ebuild_path_no_revision,
self._ebuild.current_revision + 1)
else: else:
# If given unstable ebuild, use 0.0.1 rather than 9999. # If given unstable ebuild, use 0.0.1 rather than 9999.
new_stable_ebuild_path = '%s-0.0.1-r%d.ebuild' % ( stable_version_no_rev = '0.0.1'
self._ebuild.ebuild_path_no_version,
self._ebuild.current_revision + 1) new_version = '%s-r%d' % (stable_version_no_rev,
self._ebuild.current_revision + 1)
new_stable_ebuild_path = '%s-%s.ebuild' % (
self._ebuild.ebuild_path_no_version, new_version)
_Print('Creating new stable ebuild %s' % new_stable_ebuild_path) _Print('Creating new stable ebuild %s' % new_stable_ebuild_path)
unstable_ebuild_path = ('%s-9999.ebuild' % unstable_ebuild_path = ('%s-9999.ebuild' %
@ -480,7 +482,7 @@ class EBuildStableMarker(object):
if 0 == RunCommand(diff_cmd, exit_code=True, redirect_stdout=True, if 0 == RunCommand(diff_cmd, exit_code=True, redirect_stdout=True,
redirect_stderr=True, print_cmd=gflags.FLAGS.verbose): redirect_stderr=True, print_cmd=gflags.FLAGS.verbose):
os.unlink(new_stable_ebuild_path) os.unlink(new_stable_ebuild_path)
return False return None
else: else:
_Print('Adding new stable ebuild to git') _Print('Adding new stable ebuild to git')
_SimpleRunCommand('git add %s' % new_stable_ebuild_path) _SimpleRunCommand('git add %s' % new_stable_ebuild_path)
@ -489,7 +491,7 @@ class EBuildStableMarker(object):
_Print('Removing old ebuild from git') _Print('Removing old ebuild from git')
_SimpleRunCommand('git rm %s' % old_ebuild_path) _SimpleRunCommand('git rm %s' % old_ebuild_path)
return True return '%s-%s' % (self._ebuild.package, new_version)
@classmethod @classmethod
def CommitChange(cls, message): def CommitChange(cls, message):
@ -556,16 +558,18 @@ def main(argv):
# Contains the array of packages we actually revved. # Contains the array of packages we actually revved.
revved_packages = [] revved_packages = []
new_package_atoms = []
for ebuild in ebuilds: for ebuild in ebuilds:
try: try:
_Print('Working on %s' % ebuild.package) _Print('Working on %s' % ebuild.package)
worker = EBuildStableMarker(ebuild) worker = EBuildStableMarker(ebuild)
commit_id = ebuild.GetCommitId() commit_id = ebuild.GetCommitId()
if worker.RevWorkOnEBuild(commit_id): new_package = worker.RevWorkOnEBuild(commit_id)
if new_package:
message = _GIT_COMMIT_MESSAGE % (ebuild.package, commit_id) message = _GIT_COMMIT_MESSAGE % (ebuild.package, commit_id)
worker.CommitChange(message) worker.CommitChange(message)
revved_packages.append(ebuild.package) revved_packages.append(ebuild.package)
new_package_atoms.append('=%s' % new_package)
except (OSError, IOError): except (OSError, IOError):
Warning('Cannot rev %s\n' % ebuild.package, Warning('Cannot rev %s\n' % ebuild.package,
'Note you will have to go into %s ' 'Note you will have to go into %s '
@ -573,7 +577,7 @@ def main(argv):
raise raise
if revved_packages: if revved_packages:
_CleanStalePackages(gflags.FLAGS.board, revved_packages) _CleanStalePackages(gflags.FLAGS.board, new_package_atoms)
if gflags.FLAGS.drop_file: if gflags.FLAGS.drop_file:
fh = open(gflags.FLAGS.drop_file, 'w') fh = open(gflags.FLAGS.drop_file, 'w')
fh.write(' '.join(revved_packages)) fh.write(' '.join(revved_packages))

View File

@ -129,6 +129,7 @@ class EBuildTest(mox.MoxTestBase):
self.mox.ReplayAll() self.mox.ReplayAll()
fake_ebuild = cros_mark_as_stable.EBuild(fake_ebuild_path) fake_ebuild = cros_mark_as_stable.EBuild(fake_ebuild_path)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEquals(fake_ebuild.version_no_rev, '0.0.1')
self.assertEquals(fake_ebuild.ebuild_path_no_revision, self.assertEquals(fake_ebuild.ebuild_path_no_revision,
'/path/to/test_package/test_package-0.0.1') '/path/to/test_package/test_package-0.0.1')
self.assertEquals(fake_ebuild.ebuild_path_no_version, self.assertEquals(fake_ebuild.ebuild_path_no_version,
@ -144,6 +145,7 @@ class EBuildTest(mox.MoxTestBase):
fake_ebuild = cros_mark_as_stable.EBuild(fake_ebuild_path) fake_ebuild = cros_mark_as_stable.EBuild(fake_ebuild_path)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEquals(fake_ebuild.version_no_rev, '9999')
self.assertEquals(fake_ebuild.ebuild_path_no_revision, self.assertEquals(fake_ebuild.ebuild_path_no_revision,
'/path/to/test_package/test_package-9999') '/path/to/test_package/test_package-9999')
self.assertEquals(fake_ebuild.ebuild_path_no_version, self.assertEquals(fake_ebuild.ebuild_path_no_version,
@ -160,12 +162,14 @@ class EBuildStableMarkerTest(mox.MoxTestBase):
self.mox.StubOutWithMock(os, 'unlink') self.mox.StubOutWithMock(os, 'unlink')
self.m_ebuild = self.mox.CreateMock(cros_mark_as_stable.EBuild) self.m_ebuild = self.mox.CreateMock(cros_mark_as_stable.EBuild)
self.m_ebuild.is_stable = True self.m_ebuild.is_stable = True
self.m_ebuild.package = 'test_package' self.m_ebuild.package = 'test_package/test_package'
self.m_ebuild.version_no_rev = '0.0.1'
self.m_ebuild.current_revision = 1 self.m_ebuild.current_revision = 1
self.m_ebuild.ebuild_path_no_revision = '/path/test_package-0.0.1' self.m_ebuild.ebuild_path_no_revision = '/path/test_package-0.0.1'
self.m_ebuild.ebuild_path_no_version = '/path/test_package' self.m_ebuild.ebuild_path_no_version = '/path/test_package'
self.m_ebuild.ebuild_path = '/path/test_package-0.0.1-r1.ebuild' self.m_ebuild.ebuild_path = '/path/test_package-0.0.1-r1.ebuild'
self.revved_ebuild_path = '/path/test_package-0.0.1-r2.ebuild' self.revved_ebuild_path = '/path/test_package-0.0.1-r2.ebuild'
self.unstable_ebuild_path = '/path/test_package-9999.ebuild'
def testRevWorkOnEBuild(self): def testRevWorkOnEBuild(self):
self.mox.StubOutWithMock(cros_mark_as_stable.fileinput, 'input') self.mox.StubOutWithMock(cros_mark_as_stable.fileinput, 'input')
@ -197,8 +201,9 @@ class EBuildStableMarkerTest(mox.MoxTestBase):
self.mox.ReplayAll() self.mox.ReplayAll()
marker = cros_mark_as_stable.EBuildStableMarker(self.m_ebuild) marker = cros_mark_as_stable.EBuildStableMarker(self.m_ebuild)
marker.RevWorkOnEBuild('my_id', redirect_file=m_file) result = marker.RevWorkOnEBuild('my_id', redirect_file=m_file)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEqual(result, 'test_package/test_package-0.0.1-r2')
def testRevUnchangedEBuild(self): def testRevUnchangedEBuild(self):
self.mox.StubOutWithMock(cros_mark_as_stable.fileinput, 'input') self.mox.StubOutWithMock(cros_mark_as_stable.fileinput, 'input')
@ -229,8 +234,9 @@ class EBuildStableMarkerTest(mox.MoxTestBase):
self.mox.ReplayAll() self.mox.ReplayAll()
marker = cros_mark_as_stable.EBuildStableMarker(self.m_ebuild) marker = cros_mark_as_stable.EBuildStableMarker(self.m_ebuild)
marker.RevWorkOnEBuild('my_id', redirect_file=m_file) result = marker.RevWorkOnEBuild('my_id', redirect_file=m_file)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEqual(result, None)
def testRevMissingEBuild(self): def testRevMissingEBuild(self):
self.mox.StubOutWithMock(cros_mark_as_stable.fileinput, 'input') self.mox.StubOutWithMock(cros_mark_as_stable.fileinput, 'input')
@ -239,6 +245,11 @@ class EBuildStableMarkerTest(mox.MoxTestBase):
self.mox.StubOutWithMock(cros_mark_as_stable, 'Die') self.mox.StubOutWithMock(cros_mark_as_stable, 'Die')
m_file = self.mox.CreateMock(file) m_file = self.mox.CreateMock(file)
revved_ebuild_path = self.m_ebuild.ebuild_path
self.m_ebuild.ebuild_path = self.unstable_ebuild_path
self.m_ebuild.is_stable = False
self.m_ebuild.current_revision = 0
# Prepare mock fileinput. This tests to make sure both the commit id # Prepare mock fileinput. This tests to make sure both the commit id
# and keywords are changed correctly. # and keywords are changed correctly.
mock_file = ['EAPI=2', 'CROS_WORKON_COMMIT=old_id', mock_file = ['EAPI=2', 'CROS_WORKON_COMMIT=old_id',
@ -247,25 +258,24 @@ class EBuildStableMarkerTest(mox.MoxTestBase):
ebuild_9999 = self.m_ebuild.ebuild_path_no_version + '-9999.ebuild' ebuild_9999 = self.m_ebuild.ebuild_path_no_version + '-9999.ebuild'
cros_mark_as_stable.os.path.exists(ebuild_9999).AndReturn(False) cros_mark_as_stable.os.path.exists(ebuild_9999).AndReturn(False)
cros_mark_as_stable.Die("Missing unstable ebuild: %s" % ebuild_9999) cros_mark_as_stable.Die("Missing unstable ebuild: %s" % ebuild_9999)
cros_mark_as_stable.shutil.copyfile(ebuild_9999, self.revved_ebuild_path) cros_mark_as_stable.shutil.copyfile(ebuild_9999, revved_ebuild_path)
cros_mark_as_stable.fileinput.input(self.revved_ebuild_path, cros_mark_as_stable.fileinput.input(revved_ebuild_path,
inplace=1).AndReturn(mock_file) inplace=1).AndReturn(mock_file)
m_file.write('EAPI=2') m_file.write('EAPI=2')
m_file.write('CROS_WORKON_COMMIT="my_id"\n') m_file.write('CROS_WORKON_COMMIT="my_id"\n')
m_file.write('KEYWORDS="x86 arm"') m_file.write('KEYWORDS="x86 arm"')
m_file.write('src_unpack(){}') m_file.write('src_unpack(){}')
diff_cmd = ['diff', '-Bu', self.m_ebuild.ebuild_path, diff_cmd = ['diff', '-Bu', self.unstable_ebuild_path, revved_ebuild_path]
self.revved_ebuild_path]
cros_mark_as_stable.RunCommand(diff_cmd, exit_code=True, cros_mark_as_stable.RunCommand(diff_cmd, exit_code=True,
print_cmd=False, redirect_stderr=True, print_cmd=False, redirect_stderr=True,
redirect_stdout=True).AndReturn(1) redirect_stdout=True).AndReturn(1)
cros_mark_as_stable._SimpleRunCommand('git add ' + self.revved_ebuild_path) cros_mark_as_stable._SimpleRunCommand('git add ' + revved_ebuild_path)
cros_mark_as_stable._SimpleRunCommand('git rm ' + self.m_ebuild.ebuild_path)
self.mox.ReplayAll() self.mox.ReplayAll()
marker = cros_mark_as_stable.EBuildStableMarker(self.m_ebuild) marker = cros_mark_as_stable.EBuildStableMarker(self.m_ebuild)
marker.RevWorkOnEBuild('my_id', redirect_file=m_file) result = marker.RevWorkOnEBuild('my_id', redirect_file=m_file)
self.mox.VerifyAll() self.mox.VerifyAll()
self.assertEqual(result, 'test_package/test_package-0.0.1-r1')
def testCommitChange(self): def testCommitChange(self):