1.1 --- a/moinsetup.py Sat May 01 02:54:58 2010 +0200
1.2 +++ b/moinsetup.py Mon May 03 01:21:45 2010 +0200
1.3 @@ -8,13 +8,18 @@
1.4
1.5 # Regular expressions for editing MoinMoin scripts and configuration files.
1.6
1.7 -moin_cgi_prefix = re.compile("^#sys.path.insert\(0, 'PREFIX.*$", re.MULTILINE)
1.8 -moin_cgi_wikiconfig = re.compile("^#sys.path.insert\(0, '/path/to/wikiconfigdir.*$", re.MULTILINE)
1.9 -wikiconfig_py_site_name = re.compile(r"^(\s*sitename =).*$", re.MULTILINE)
1.10 -wikiconfig_py_url_prefix_static = re.compile(r"^(\s*)#(url_prefix_static =).*$", re.MULTILINE)
1.11 -wikiconfig_py_superuser = re.compile(r"^(\s*)#(superuser =).*$", re.MULTILINE)
1.12 -wikiconfig_py_acl_rights_before = re.compile(r"^(\s*)#(acl_rights_before =).*$", re.MULTILINE)
1.13 -wikiconfig_py_page_front_page = re.compile(r"^(\s*)#(page_front_page =).*$", re.MULTILINE)
1.14 +def compile_definition(name):
1.15 + return re.compile(r"^(\s*)#?(%s =).*$" % name, re.MULTILINE)
1.16 +
1.17 +moin_cgi_prefix = re.compile("^#sys.path.insert\(0, 'PREFIX.*$", re.MULTILINE)
1.18 +moin_cgi_wikiconfig = re.compile("^#sys.path.insert\(0, '/path/to/wikiconfigdir.*$", re.MULTILINE)
1.19 +wikiconfig_py_site_name = compile_definition("site_name")
1.20 +wikiconfig_py_url_prefix_static = compile_definition("url_prefix_static")
1.21 +wikiconfig_py_superuser = compile_definition("superuser")
1.22 +wikiconfig_py_acl_rights_before = compile_definition("acl_rights_before")
1.23 +wikiconfig_py_page_front_page = compile_definition("page_front_page")
1.24 +wikiconfig_py_data_dir = compile_definition("data_dir")
1.25 +wikiconfig_py_data_underlay_dir = compile_definition("data_underlay_dir")
1.26
1.27 # Templates for Apache site definitions.
1.28
1.29 @@ -23,7 +28,14 @@
1.30 """
1.31
1.32 apache_site_extra_moin18 = """
1.33 -Alias %(static_path)s "%(prefix)s/share/moin/htdocs/"
1.34 +Alias %(static_url_path)s "%(htdocs_dir)s/"
1.35 +"""
1.36 +
1.37 +apache_site_host_restriction = """
1.38 +<Location "%(url_path)s">
1.39 + Deny from all
1.40 + Allow from %(superuser_client_host)s
1.41 +</Location>
1.42 """
1.43
1.44 # Utility functions.
1.45 @@ -48,122 +60,253 @@
1.46 def note(message):
1.47 print message
1.48
1.49 -# NOTE: Support the detection of the Apache sites directory.
1.50 -
1.51 -def setup(moin_distribution, prefix, web_app_dir, web_site_dir, common_dir, url_path, site_name, front_page_name, superuser):
1.52 -
1.53 - """
1.54 - Set up a Wiki installation using the following:
1.55 -
1.56 - * moin_distribution - the directory containing a MoinMoin source
1.57 - distribution
1.58 - * prefix - the installation prefix (equivalent to /usr)
1.59 - * web_app_dir - the directory where Web applications and scripts
1.60 - reside (such as /home/www-user/cgi-bin)
1.61 - * web_site_dir - the directory where Web site definitions reside
1.62 - (such as /etc/apache2/sites-available)
1.63 - * common_dir - the directory where the Wiki configuration,
1.64 - resources and instance will reside (such as
1.65 - /home/www-user/mywiki)
1.66 - * url_path - the URL path at which the Wiki will be made
1.67 - available (such as / or /mywiki)
1.68 - * site_name - the name of the site (such as "My Wiki")
1.69 - * front_page_name - the front page name for the site (such as
1.70 - "FrontPage" or a specific name for the site)
1.71 - * superuser - the name of the site's superuser (such as
1.72 - "AdminUser")
1.73 - """
1.74 -
1.75 - prefix, web_app_dir, web_site_dir, common_dir = map(abspath, (prefix, web_app_dir, web_site_dir, common_dir))
1.76 -
1.77 - conf_dir = join(common_dir, "conf")
1.78 - instance_dir = join(common_dir, "wikidata")
1.79 -
1.80 - for d in (conf_dir, instance_dir, web_app_dir, web_site_dir):
1.81 - if not exists(d):
1.82 - os.makedirs(d)
1.83 -
1.84 - # Enter the distribution directory and run the setup script.
1.85 -
1.86 - this_dir = os.getcwd()
1.87 - os.chdir(moin_distribution)
1.88 -
1.89 - log_filename = "install-%s.log" % split(common_dir)[-1]
1.90 -
1.91 - status("Installing MoinMoin in %s..." % prefix)
1.92 -
1.93 - os.system("python setup.py --quiet install --force --prefix='%s' --install-data='%s' --record='%s'" % (
1.94 - prefix, instance_dir, log_filename))
1.95 -
1.96 - os.chdir(this_dir)
1.97 -
1.98 - # The default wikiconfig assumes data and underlay in the same directory.
1.99 -
1.100 - status("Installing data and underlay in %s..." % conf_dir)
1.101 +class Installation:
1.102
1.103 - for d in ("data", "underlay"):
1.104 - shutil.copytree(join(moin_distribution, "wiki", d), join(conf_dir, d))
1.105 -
1.106 - # NOTE: Single Wiki only so far.
1.107 - # NOTE: Static URLs seem to be different in MoinMoin 1.9.x.
1.108 -
1.109 - wikiconfig_py = join(moin_distribution, "wiki", "config", "wikiconfig.py")
1.110 -
1.111 - status("Editing configuration from %s..." % wikiconfig_py)
1.112 -
1.113 - s = readfile(wikiconfig_py)
1.114 - s = wikiconfig_py_site_name.sub(r"\1 %r" % site_name, s)
1.115 - s = wikiconfig_py_url_prefix_static.sub(r"\1\2 %r + url_prefix_static" % url_path, s)
1.116 - s = wikiconfig_py_superuser.sub(r"\1\2 %r" % [superuser], s)
1.117 - s = wikiconfig_py_acl_rights_before.sub(r"\1\2 %r" % (u"%s:read,write,delete,revert,admin" % superuser), s)
1.118 - s = wikiconfig_py_page_front_page.sub(r"\1\2 %r" % front_page_name, s, count=1)
1.119 - writefile(join(conf_dir, "wikiconfig.py"), s)
1.120 -
1.121 - # Edit moin script.
1.122 -
1.123 - moin_script = join(prefix, "bin", "moin")
1.124 - prefix_site_packages = join(prefix, "lib", "python%s.%s" % sys.version_info[:2], "site-packages")
1.125 -
1.126 - status("Editing moin script at %s..." % moin_script)
1.127 -
1.128 - s = readfile(moin_script)
1.129 - s = s.replace("#import sys", "import sys\nsys.path.insert(0, %r)" % prefix_site_packages)
1.130 + "A class for installing and initialising MoinMoin."
1.131
1.132 - writefile(moin_script, s)
1.133 -
1.134 - # Edit and install CGI script.
1.135 - # NOTE: CGI only so far.
1.136 - # NOTE: Permissions should be checked.
1.137 -
1.138 - moin_cgi = join(instance_dir, "share", "moin", "server", "moin.cgi")
1.139 - moin_cgi_installed = join(web_app_dir, "moin.cgi")
1.140 -
1.141 - status("Editing moin.cgi script from %s..." % moin_cgi)
1.142 -
1.143 - s = readfile(moin_cgi)
1.144 - s = moin_cgi_prefix.sub("sys.path.insert(0, %r)" % prefix_site_packages, s)
1.145 - s = moin_cgi_wikiconfig.sub("sys.path.insert(0, %r)" % conf_dir, s)
1.146 -
1.147 - writefile(moin_cgi_installed, s)
1.148 - os.system("chmod a+rx '%s'" % moin_cgi_installed)
1.149 -
1.150 - # Configure server.
1.151 - # NOTE: Need to work with older MoinMoin versions.
1.152 - # NOTE: Using local namespace for substitution.
1.153 -
1.154 - site_def = join(web_site_dir, site_name)
1.155 - status("Writing Apache site definition to %s..." % site_def)
1.156 -
1.157 - writefile(site_def, apache_site % locals())
1.158 -
1.159 - # General notes.
1.160 # NOTE: Need to detect Web server user.
1.161
1.162 web_user = "www-data"
1.163 web_group = "www-data"
1.164
1.165 - for d in ("data", "underlay"):
1.166 - note("chown -R %s.%s '%s'" % (web_user, web_group, join(conf_dir, d)))
1.167 + def __init__(self, moin_distribution, prefix, web_app_dir, web_site_dir,
1.168 + common_dir, url_path, site_name, front_page_name, superuser):
1.169 +
1.170 + """
1.171 + Initialise a Wiki installation using the following:
1.172 +
1.173 + * moin_distribution - the directory containing a MoinMoin source
1.174 + distribution
1.175 + * prefix - the installation prefix (equivalent to /usr)
1.176 + * web_app_dir - the directory where Web applications and scripts
1.177 + reside (such as /home/www-user/cgi-bin)
1.178 + * web_site_dir - the directory where Web site definitions reside
1.179 + (such as /etc/apache2/sites-available)
1.180 + * common_dir - the directory where the Wiki configuration,
1.181 + resources and instance will reside (such as
1.182 + /home/www-user/mywiki)
1.183 + * url_path - the URL path at which the Wiki will be made
1.184 + available (such as / or /mywiki)
1.185 + * site_name - the name of the site (such as "My Wiki")
1.186 + * front_page_name - the front page name for the site (such as
1.187 + "FrontPage" or a specific name for the site)
1.188 + * superuser - the name of the site's superuser (such as
1.189 + "AdminUser")
1.190 + """
1.191 +
1.192 + self.moin_distribution = moin_distribution
1.193 + self.site_name = site_name
1.194 + self.front_page_name = front_page_name
1.195 + self.superuser = superuser
1.196 +
1.197 + # NOTE: Support the detection of the Apache sites directory.
1.198 +
1.199 + self.prefix, self.web_app_dir, self.web_site_dir, self.common_dir = \
1.200 + map(abspath, (prefix, web_app_dir, web_site_dir, common_dir))
1.201 +
1.202 + # Strip any trailing "/" from the URL path.
1.203 +
1.204 + if url_path.endswith("/"):
1.205 + self.url_path = url_path[:-1]
1.206 + else:
1.207 + self.url_path = url_path
1.208 +
1.209 + # Define and create specific directories.
1.210 +
1.211 + self.conf_dir = join(self.common_dir, "conf")
1.212 + self.instance_dir = join(self.common_dir, "wikidata")
1.213 +
1.214 + # For MoinMoin 1.8.x and earlier.
1.215 +
1.216 + self.htdocs_dir = join(self.instance_dir, "share", "moin", "htdocs")
1.217 +
1.218 + # Miscellaneous configuration options.
1.219 +
1.220 + self.superuser_client_host = "127.0.0.1"
1.221 +
1.222 + # Find the version.
1.223 +
1.224 + self.moin_version = self.get_moin_version()
1.225 +
1.226 + def get_moin_version(self):
1.227 +
1.228 + "Inspect the MoinMoin package information, returning the version."
1.229 +
1.230 + this_dir = os.getcwd()
1.231 + os.chdir(self.moin_distribution)
1.232 +
1.233 + f = open("PKG-INFO")
1.234 + try:
1.235 + for line in f.xreadlines():
1.236 + columns = line.split()
1.237 + if columns[0] == "Version:":
1.238 + return columns[1]
1.239 +
1.240 + return None
1.241 +
1.242 + finally:
1.243 + f.close()
1.244 + os.chdir(this_dir)
1.245 +
1.246 + def setup(self):
1.247 +
1.248 + "Set up the installation."
1.249 +
1.250 + for d in (self.conf_dir, self.instance_dir, self.web_app_dir, self.web_site_dir):
1.251 + if not exists(d):
1.252 + os.makedirs(d)
1.253 +
1.254 + self.install_moin()
1.255 + self.install_data()
1.256 + self.configure_moin()
1.257 + self.edit_moin_scripts()
1.258 + self.make_site_files()
1.259 + self.make_post_install_script()
1.260 +
1.261 + def install_moin(self):
1.262 +
1.263 + "Enter the distribution directory and run the setup script."
1.264 +
1.265 + # NOTE: Possibly check for an existing installation and skip repeated
1.266 + # NOTE: installation attempts.
1.267 +
1.268 + this_dir = os.getcwd()
1.269 + os.chdir(self.moin_distribution)
1.270 +
1.271 + log_filename = "install-%s.log" % split(self.common_dir)[-1]
1.272 +
1.273 + status("Installing MoinMoin in %s..." % self.prefix)
1.274 +
1.275 + os.system("python setup.py --quiet install --force --prefix='%s' --install-data='%s' --record='%s'" % (
1.276 + self.prefix, self.instance_dir, log_filename))
1.277 +
1.278 + os.chdir(this_dir)
1.279 +
1.280 + def install_data(self):
1.281 +
1.282 + "Install Wiki data."
1.283 +
1.284 + # The default wikiconfig assumes data and underlay in the same directory.
1.285 +
1.286 + status("Installing data and underlay in %s..." % self.conf_dir)
1.287 +
1.288 + for d in ("data", "underlay"):
1.289 + shutil.copytree(join(self.moin_distribution, "wiki", d), join(self.conf_dir, d))
1.290 +
1.291 + def configure_moin(self):
1.292 +
1.293 + "Edit the Wiki configuration file."
1.294 +
1.295 + # NOTE: Single Wiki only so far.
1.296 +
1.297 + # Static URLs seem to be different in MoinMoin 1.9.x.
1.298 + # For earlier versions, reserve URL space alongside the Wiki.
1.299 + # NOTE: MoinMoin usually uses an apparently common URL space associated
1.300 + # NOTE: with the version, but more specific locations are probably
1.301 + # NOTE: acceptable if less efficient.
1.302 +
1.303 + if self.moin_version.startswith("1.9"):
1.304 + self.static_url_path = self.url_path
1.305 + url_prefix_static_sub = r"\1\2 %r + url_prefix_static" % self.static_url_path
1.306 + else:
1.307 + self.static_url_path = self.url_path + "-static"
1.308 + url_prefix_static_sub = r"\1\2 %r" % self.static_url_path
1.309 +
1.310 + # Edit the Wiki configuration file.
1.311 +
1.312 + wikiconfig_py = join(self.moin_distribution, "wiki", "config", "wikiconfig.py")
1.313 +
1.314 + status("Editing configuration from %s..." % wikiconfig_py)
1.315 +
1.316 + s = readfile(wikiconfig_py)
1.317 + s = wikiconfig_py_site_name.sub(r"\1\2 %r" % self.site_name, s)
1.318 + s = wikiconfig_py_url_prefix_static.sub(url_prefix_static_sub, s)
1.319 + s = wikiconfig_py_superuser.sub(r"\1\2 %r" % [self.superuser], s)
1.320 + s = wikiconfig_py_acl_rights_before.sub(r"\1\2 %r" % (u"%s:read,write,delete,revert,admin" % self.superuser), s)
1.321 + s = wikiconfig_py_page_front_page.sub(r"\1\2 %r" % self.front_page_name, s, count=1)
1.322 +
1.323 + if not self.moin_version.startswith("1.9"):
1.324 + data_dir = join(self.conf_dir, "data")
1.325 + data_underlay_dir = join(self.conf_dir, "underlay")
1.326 +
1.327 + s = wikiconfig_py_data_dir.sub(r"\1\2 %r" % data_dir, s)
1.328 + s = wikiconfig_py_data_underlay_dir.sub(r"\1\2 %r" % data_underlay_dir, s)
1.329 +
1.330 + writefile(join(self.conf_dir, "wikiconfig.py"), s)
1.331 +
1.332 + def edit_moin_scripts(self):
1.333 +
1.334 + "Edit the moin script and the CGI script."
1.335 +
1.336 + moin_script = join(self.prefix, "bin", "moin")
1.337 + prefix_site_packages = join(self.prefix, "lib", "python%s.%s" % sys.version_info[:2], "site-packages")
1.338 +
1.339 + status("Editing moin script at %s..." % moin_script)
1.340 +
1.341 + s = readfile(moin_script)
1.342 + s = s.replace("#import sys", "import sys\nsys.path.insert(0, %r)" % prefix_site_packages)
1.343 +
1.344 + writefile(moin_script, s)
1.345 +
1.346 + # Edit and install CGI script.
1.347 + # NOTE: CGI only so far.
1.348 + # NOTE: Permissions should be checked.
1.349 +
1.350 + moin_cgi = join(self.instance_dir, "share", "moin", "server", "moin.cgi")
1.351 + moin_cgi_installed = join(self.web_app_dir, "moin.cgi")
1.352 +
1.353 + status("Editing moin.cgi script from %s..." % moin_cgi)
1.354 +
1.355 + s = readfile(moin_cgi)
1.356 + s = moin_cgi_prefix.sub("sys.path.insert(0, %r)" % prefix_site_packages, s)
1.357 + s = moin_cgi_wikiconfig.sub("sys.path.insert(0, %r)" % self.conf_dir, s)
1.358 +
1.359 + writefile(moin_cgi_installed, s)
1.360 + os.system("chmod a+rx '%s'" % moin_cgi_installed)
1.361 +
1.362 + def make_site_files(self):
1.363 +
1.364 + "Make the Apache site files."
1.365 +
1.366 + # NOTE: Using local namespace for substitution.
1.367 +
1.368 + site_def = join(self.web_site_dir, self.site_name)
1.369 + site_def_private = join(self.web_site_dir, "%s-private" % self.site_name)
1.370 +
1.371 + status("Writing Apache site definitions to %s and %s..." % (site_def, site_def_private))
1.372 +
1.373 + s = apache_site % self.__dict__
1.374 +
1.375 + if not self.moin_version.startswith("1.9"):
1.376 + s += apache_site_extra_moin18 % self.__dict__
1.377 +
1.378 + writefile(site_def, s)
1.379 +
1.380 + # NOTE: By making the superuser in the installed Wiki, this site file
1.381 + # NOTE: would no longer be required.
1.382 +
1.383 + s += apache_site_host_restriction % self.__dict__
1.384 +
1.385 + writefile(site_def_private, s)
1.386 +
1.387 + def make_post_install_script(self):
1.388 +
1.389 + "Write a post-install script with additional actions."
1.390 +
1.391 + this_user = os.environ["USER"]
1.392 + postinst_script = "moinsetup-post.sh"
1.393 +
1.394 + s = ""
1.395 +
1.396 + for d in ("data", "underlay"):
1.397 + s += "chown -R %s.%s '%s'\n" % (this_user, self.web_group, join(self.conf_dir, d))
1.398 + s += "chmod -R g+w '%s'\n" % join(self.conf_dir, d)
1.399 +
1.400 + if not self.moin_version.startswith("1.9"):
1.401 + s += "chown -R %s.%s '%s'\n" % (this_user, self.web_group, self.htdocs_dir)
1.402 +
1.403 + writefile(postinst_script, s)
1.404 + note("Run %s as root to set file ownership and permissions." % postinst_script)
1.405
1.406 # Main program.
1.407
1.408 @@ -172,13 +315,14 @@
1.409 # Obtain as many arguments as needed for the setup function.
1.410
1.411 try:
1.412 - n = 9 # number of setup function arguments
1.413 + n = 9 # number of Installation initialiser arguments
1.414 args = sys.argv[1:n+1]
1.415 args[n-1]
1.416 except (IndexError, ValueError):
1.417 - print setup.__doc__
1.418 + print Installation.__init__.__doc__
1.419 sys.exit(1)
1.420
1.421 - setup(*args)
1.422 + installation = Installation(*args)
1.423 + installation.setup()
1.424
1.425 # vim: tabstop=4 expandtab shiftwidth=4