Update gmerge to support deep upgrades.
With --deep mode, gmerge updates all necessary packages. This is useful for
ensuring dependencies are up to date.
Other features added in this CL:
- /usr/local/portage is rm -rf'd at beginning of gmerge as well in case
leftover state is there from a failed merge.
- Improve error message when devserver is not running.
- The --extra flag allows you to specify extra flags to emerge. This is useful
for example to exclude certain packages from the upgrade. E.g
gmerge -Dn chromeos -x '--usepkg-exclude=trousers'
BUG=chromium-os:15606, chromium-os:11332, chromium-os:14748
TEST=Try gmerging a deep upgrade of power manager. If packages that use enewuser
/ enewgroup are excluded, we can upgrade the rest of the packages. If the
latest toolchain is used which includes getent, we can upgrade those
packages.
Change-Id: Id01b35133486ec9448b62c80194d61ff1360e87e
Reviewed-on: http://gerrit.chromium.org/gerrit/1320
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: David James <davidjames@chromium.org>
diff --git a/builder.py b/builder.py
index 2f93141..df93d20 100644
--- a/builder.py
+++ b/builder.py
@@ -86,7 +86,7 @@
xpak.tbz2(out_path).recompose_mem(x)
-def _UpdateGmergeBinhost(board, pkg):
+def _UpdateGmergeBinhost(board, pkg, deep):
"""Add pkg to our gmerge-specific binhost.
Files matching DEFAULT_INSTALL_MASK are not included in the tarball.
@@ -110,10 +110,16 @@
settings=bintree.settings)
gmerge_tree.populate()
- # Create lists of matching packages.
- gmerge_matches = set(gmerge_tree.dbapi.match(pkg))
- bindb_matches = set(bintree.dbapi.match(pkg))
- installed_matches = set(vardb.match(pkg)) & bindb_matches
+ if deep:
+ # If we're in deep mode, fill in the binhost completely.
+ gmerge_matches = set(gmerge_tree.dbapi.cpv_all())
+ bindb_matches = set(bintree.dbapi.cpv_all())
+ installed_matches = set(vardb.cpv_all()) & bindb_matches
+ else:
+ # Otherwise, just fill in the requested package.
+ gmerge_matches = set(gmerge_tree.dbapi.match(pkg))
+ bindb_matches = set(bintree.dbapi.match(pkg))
+ installed_matches = set(vardb.match(pkg)) & bindb_matches
# Remove any stale packages that exist in the local binhost but are not
# installed anymore.
@@ -142,6 +148,7 @@
if old_build_time == build_time:
continue
+ cherrypy.log('Filtering install mask from %s' % pkg, 'BUILD')
_FilterInstallMaskFromPackage(build_path, gmerge_path)
changed = True
@@ -206,7 +213,8 @@
return self.SetError('Could not emerge ' + pkg)
# Sync gmerge binhost.
- if not _UpdateGmergeBinhost(board, pkg):
+ deep = additional_args.get('deep')
+ if not _UpdateGmergeBinhost(board, pkg, deep):
return self.SetError('Package %s is not installed' % pkg)
return 'Success\n'
diff --git a/gmerge b/gmerge
index 16ef174..0a23ef5 100755
--- a/gmerge
+++ b/gmerge
@@ -75,6 +75,7 @@
def GeneratePackageRequest(self, package_name):
"""Build the POST string that conveys our options to the devserver."""
post_data = {'board': self.board_name,
+ 'deep': FLAGS.deep or '',
'pkg': package_name,
'features': os.environ.get('FEATURES'),
'use': os.environ.get('USE'),
@@ -96,6 +97,8 @@
except urllib2.HTTPError, e:
# The exception includes the content, which is the error mesage
sys.exit(e.read())
+ except urllib2.URLError, e:
+ sys.exit('Could not reach devserver. Reason: %s' % e.reason)
def main():
@@ -111,13 +114,25 @@
'(e.g. debug symbols)'))
parser.add_option('-n', '--usepkg',
action='store_true', dest='usepkg', default=False,
- help='Use binary packages.')
+ help='Use currently built binary packages on server.')
+ parser.add_option('-D', '--deep',
+ action='store_true', dest='deep', default=False,
+ help='Update package and all dependencies '
+ '(requires --usepkg).')
+ parser.add_option('-x', '--extra', dest='extra', default='',
+ help='Extra arguments to pass to emerge command.')
(FLAGS, remaining_arguments) = parser.parse_args()
if len(remaining_arguments) != 1:
parser.print_help()
sys.exit('Need exactly one package name')
+ # TODO(davidjames): Should we allow --deep without --usepkg? Not sure what
+ # the desired behavior should be in this case, so disabling the combo for
+ # now.
+ if FLAGS.deep and not FLAGS.usepkg:
+ sys.exit('If using --deep, --usepkg must also be enabled.')
+
package_name = remaining_arguments[0]
try:
@@ -128,10 +143,14 @@
print 'Emerging ', package_name
merger.SetupPortageEnvironment(os.environ)
merger.RemountOrChangeRoot(os.environ)
- subprocess.check_call([
- 'emerge', '--getbinpkgonly', '--usepkgonly', package_name])
- subprocess.check_call([
- 'rm', '-rf', '/usr/local/portage'])
+ subprocess.check_call(['rm', '-rf', '/usr/local/portage'])
+ emerge_args = 'emerge --getbinpkgonly --usepkgonly --verbose'
+ if FLAGS.deep:
+ emerge_args += ' --update --deep'
+ if FLAGS.extra:
+ emerge_args += ' ' + FLAGS.extra
+ emerge_args += ' ' + package_name
+ subprocess.check_call(emerge_args, shell=True)
finally:
subprocess.call(['mount', '-o', 'remount,noexec', '/tmp'])