Permalink
Browse files

Fix installation of non-live extension versions

Roles should be installed (added to the database) once per version,
not once per install.
  • Loading branch information...
jensl committed Mar 2, 2014
1 parent e73fc75 commit 80512c5a80b29d269fb6f955e1f757920e63d211
@@ -0,0 +1,72 @@
+# -*- mode: python; encoding: utf-8 -*-
+#
+# Copyright 2014 Jens Lindström, Opera Software ASA
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+import sys
+import psycopg2
+import argparse
+import os
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--uid", type=int)
+parser.add_argument("--gid", type=int)
+
+arguments = parser.parse_args()
+
+os.setgid(arguments.gid)
+os.setuid(arguments.uid)
+
+import configuration
+
+db = psycopg2.connect(**configuration.database.PARAMETERS)
+cursor = db.cursor()
+
+try:
+ # The extensions part of the database schema might not have been loaded at
+ # all; it isn't until extend.py is used to enable extensions support.
+ cursor.execute("SELECT 1 FROM extensions")
+except psycopg2.ProgrammingError:
+ sys.exit(0)
+
+cursor.execute("""SELECT id, version, script, function,
+ extensionpageroles.path,
+ extensioninjectroles.path,
+ extensionprocesscommitsroles.role IS NULL
+ FROM extensionroles
+ LEFT OUTER JOIN extensionpageroles
+ ON (extensionpageroles.role=id)
+ LEFT OUTER JOIN extensioninjectroles
+ ON (extensioninjectroles.role=id)
+ LEFT OUTER JOIN extensionprocesscommitsroles
+ ON (extensionprocesscommitsroles.role=id)""")
+
+roles = set()
+duplicates = []
+
+for row in cursor:
+ role_id = row[0]
+ role_key = row[1:]
+
+ if role_key in roles:
+ duplicates.append(role_id)
+ else:
+ roles.add(role_key)
+
+if duplicates:
+ print "Removing %d duplicate rows from extensionroles." % len(duplicates)
+ cursor.execute("DELETE FROM extensionroles WHERE id=ANY (%s)", (duplicates,))
+
+db.commit()
+db.close()
@@ -98,28 +98,24 @@ def doInstallExtension(db, user, extension, version):
(extension_id, version, sha1))
row = cursor.fetchone()
- if not row:
+ if row:
+ (version_id,) = row
+ else:
cursor.execute("""INSERT INTO extensionversions (extension, name, sha1)
VALUES (%s, %s, %s)
RETURNING id""",
(extension_id, version, sha1))
- row = cursor.fetchone()
+ (version_id,) = cursor.fetchone()
- (version_id,) = row
+ for role in manifest.roles:
+ role.install(db, version_id)
else:
version_id = None
cursor.execute("""INSERT INTO extensioninstalls (uid, extension, version)
- VALUES (%s, %s, %s)
- RETURNING id""",
+ VALUES (%s, %s, %s)""",
(user_id, extension_id, version_id))
- (install_id,) = cursor.fetchone()
-
- if version_id is not None:
- for role in manifest.roles:
- role.install(db, version_id)
-
def doUninstallExtension(db, user, extension):
extension_id = extension.getExtensionID(db)
@@ -87,3 +87,10 @@ def check(actual):
"version",
expected_content_type="text/plain",
expect={ "version": check_version("stable:2") })
+
+with frontend.signin("admin"):
+ frontend.operation(
+ "uninstallextension",
+ data={ "author_name": "alice",
+ "extension_name": "TestExtension",
+ "universal": True })
@@ -0,0 +1,8 @@
+# We don't need to do anything if extension testing is not supported.
+instance.check_extend(repository, pre_upgrade=True)
+
+# We also don't need to do anything if there was no --upgrade-from.
+instance.check_upgrade()
+
+instance.start()
+instance.install(repository)
@@ -0,0 +1 @@
+instance.upgrade()
View
@@ -25,11 +25,13 @@
import testing
-def flag(commit_sha1, name):
- lstree = subprocess.check_output(
- ["git", "ls-tree", commit_sha1, "testing/flags/%s.flag" % name])
+def exists_at(commit_sha1, path):
+ lstree = subprocess.check_output(["git", "ls-tree", commit_sha1, path])
return bool(lstree.strip())
+def flag(commit_sha1, name):
+ return exists_at(commit_sha1, "testing/flags/%s.flag" % name)
+
def flag_pwd_independence(commit_sha1):
return flag(commit_sha1, "pwd-independence")
@@ -88,6 +90,7 @@ def __init__(self, arguments, install_commit=None, upgrade_commit=None,
self.coverage = getattr(arguments, "coverage", False)
self.mailbox = None
self.__started = False
+ self.__installed = False
# Check that the identified VM actually exists:
output = subprocess.check_output(
@@ -210,6 +213,8 @@ def stop(self):
testing.logger.info("Stopped VM: %s" % self.identifier)
+ self.__started = False
+
def retake_snapshot(self, name):
index = 1
@@ -541,6 +546,12 @@ def install(self, repository, override_arguments={}, other_cwd=False,
testing.logger.info("Installed Critic: %s" % self.install_commit_description)
+ self.__installed = True
+
+ def check_upgrade(self):
+ if not self.upgrade_commit:
+ raise testing.NotSupported("--upgrade-from argument not given")
+
def upgrade(self, override_arguments={}, other_cwd=False, quick=False,
interactive=False):
if self.upgrade_commit:
@@ -593,12 +604,17 @@ def upgrade(self, override_arguments={}, other_cwd=False, quick=False,
testing.logger.info("Upgraded Critic: %s" % self.upgrade_commit_description)
- def extend(self, repository):
+ def check_extend(self, repository, pre_upgrade=False):
+ if not exists_at(self.install_commit, "extend.py"):
+ raise testing.NotSupported("installed commit lacks extend.py")
if not self.arguments.test_extensions:
raise testing.NotSupported("--test-extensions argument not given")
if not repository.v8_jsshell_path:
raise testing.NotSupported("v8-jsshell sub-module not initialized")
+ def extend(self, repository):
+ self.check_extend(repository)
+
testing.logger.debug("Extending Critic ...")
def internal(action, extra_argv=None):
@@ -675,9 +691,15 @@ def uninstall(self):
self.execute(["sudo", "deluser", "--remove-home", "howard"])
+ self.__installed = False
+
def finish(self):
- self.execute(["sudo", "service", "critic-main", "stop"])
- self.execute(["sudo", "service", "apache2", "stop"])
+ if not self.__started:
+ return
+
+ if self.__installed:
+ self.execute(["sudo", "service", "critic-main", "stop"])
+ self.execute(["sudo", "service", "apache2", "stop"])
if self.coverage:
sys.stdout.write(self.execute(

0 comments on commit 80512c5

Please sign in to comment.