This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
library-web/src/modtypes/base.py

244 lines
9.6 KiB
Python

# libgo - script to build library.gnome.org
# Copyright (C) 2007-2009 Frederic Peters
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
import logging
import os
import re
import stat
import tarfile
from utils import version_cmp, is_version_number
class DocModule(object):
'''Base class for documentation shipped in tarballs'''
makefile_am = None
filename = None
dirname = None
modulename = None
related_xsl_files = None
mtime_xslt_files = 0
channel = None
nightly = False
extra_devel_releases = None
def create_from_tar(cls, tar, tarinfo, makefile_am, nightly = False):
self = cls()
if tarinfo.isdir():
self.dirname = tarinfo.name
else:
self.dirname = os.path.dirname(tarinfo.name)
if makefile_am:
self.makefile_am = makefile_am
self.modulename = re.findall(r'(?:DOC_ID|DOC_MODULE|HELP_ID)\s?=\s?(.*)',
makefile_am)[0].strip()
if '@' in self.modulename:
logging.warning('variadic module name: %s' % self.modulename)
# don't go interpreting autotools variables, as in this path
# lays madness, instead simply cut out the variable, such as
# gnome-scan-@API_VERSION@ becomes gnome-scan.
self.modulename = self.modulename.split('@')[0].strip('-')
# remove the version part, so libsoup-2.4 is handled just like
# another version of libsoup
self.modulename = re.sub('-\d+\.\d+$', '', self.modulename)
self.version = os.path.splitext(tar.name)[0].split('-')[-1]
if self.version.endswith('.tar'):
self.version = self.version[:-4]
if nightly or self.version == 'nightly':
self.nightly = True
self.version = 'nightly'
self.one_dot_version = 'nightly'
else:
self.one_dot_version = re.match(r'\d+\.\d+', self.version).group()
if self.related_xsl_files:
self.mtime_xslt_files = max([os.stat(
os.path.join(data_dir, 'xslt', x))[stat.ST_MTIME] \
for x in self.related_xsl_files])
return self
create_from_tar = classmethod(create_from_tar)
def extract(self, force=False):
'''Extract a given module out of a tarball; extraction will not happen
if the output directory already exists, unless @force is given.'''
ext_dirname = os.path.join(app.config.private_dir, 'extracts')
if not os.path.exists(ext_dirname):
os.makedirs(ext_dirname)
base_tarball_name = os.path.basename(self.filename).rsplit('-', 1)[0]
dirname = self.dirname
if dirname.endswith('/'):
dirname = dirname[:-1]
if not os.path.exists(os.path.join(ext_dirname, self.dirname)) or force:
logging.debug('extracting %s' % self.dirname)
tar = tarfile.open(self.filename, 'r')
for tarinfo in tar.getmembers():
if not os.path.split(tarinfo.name)[0].startswith(dirname):
continue
dest = os.path.join(ext_dirname, tarinfo.name)
if tarinfo.isdir() and not os.path.exists(dest):
os.makedirs(dest)
elif tarinfo.isreg():
if not os.path.exists(os.path.dirname(dest)):
os.makedirs(os.path.dirname(dest))
open(dest, 'w').write(tar.extractfile(tarinfo).read())
tar.close()
return True
return False
def get_libgo_document(self, doc_linguas):
try:
doc = [x for x in app.documents if \
x.module == self.modulename and x.channel == self.channel][0]
except IndexError:
doc = app.Document()
doc.filename = self.dirname
doc.module = self.modulename
doc.channel = self.channel
doc.languages = doc_linguas
doc.path = self.path
doc._last_version = self.version
doc.versions = [self.one_dot_version]
app.documents.append(doc)
else:
if doc._last_version == self.version:
# file was already processed in a previous moduleset
return None
if not self.nightly:
# a more recent version may already have been installed; probably
# because the same module is being mentioned as an extra tarball
# with an inferior version number; don't update path in this
# situation. (see bug #530517 for the mention of this problem)
if version_cmp(doc._last_version, self.version) <= 0:
doc._last_version = self.version
if int(self.one_dot_version.split('.')[1]) % 2 == 0:
# update path to point to the latest version (but no
# development versions)
doc.path = self.path
if not self.one_dot_version in doc.versions:
doc.versions.append(self.one_dot_version)
for lang in doc_linguas:
if not lang in doc.languages:
doc.languages.append(lang)
doc.version_mapping[self.one_dot_version] = self.version
# only keep authorised languages
if app.config.languages:
for lang in doc.languages[:]:
if lang not in app.config.languages:
doc.languages.remove(lang)
return doc
def is_development_release(self):
development_release = (int(self.one_dot_version.split('.')[1]) % 2 == 1) or (
int(self.one_dot_version.split('.')[0]) == 0)
if not development_release:
development_release = app.overlay.is_development_release(
self.modulename, self.one_dot_version)
return development_release
def install_version_symlinks(self, doc):
'''Create stable and devel symlinks'''
if self.nightly:
return
if self.channel not in ('users', 'devel', 'admin'):
return
if not self.one_dot_version in doc.versions:
# this version doesn't appear in available versions, probably it
# had been depreciated
return
web_output_dir = app.get_module_web_output_dir(self, versioned=False)
development_release = self.is_development_release()
if development_release:
keyword = 'unstable'
else:
keyword = 'stable'
path = os.path.join(web_output_dir, keyword)
installed = False
if os.path.islink(path):
currently_marked = os.readlink(path)
if currently_marked == 'stable':
currently_marked = os.readlink(os.path.join(web_output_dir, 'stable'))
if version_cmp(self.version, currently_marked) >= 0:
# install new symlink
os.unlink(path)
os.symlink(self.one_dot_version, path)
installed = True
else:
os.symlink(self.one_dot_version, path)
installed = True
if installed:
base_path = app.config.doc_path_template % {
'channel': self.channel,
'module': self.modulename }
if not development_release:
if doc.path == base_path + '%s/' % self.one_dot_version:
# set default path to use the keyword
doc.path = base_path + 'stable/'
# if there is no unstable link, create it even for a stable release
# (or if stable is newer)
path = os.path.join(web_output_dir, 'unstable')
if os.path.islink(path):
currently_unstable = os.readlink(path)
if currently_unstable == 'stable' or \
version_cmp(self.version, currently_unstable) >= 0:
os.unlink(path)
os.symlink('stable', path)
else:
os.symlink('stable', path)
elif not os.path.exists(os.path.join(web_output_dir, 'stable')):
# update default path to have codename if there is no stable
# release
doc.path = base_path + 'unstable/'
for k in doc.version_keywords.keys():
if doc.version_keywords.get(k) == keyword:
del doc.version_keywords[k]
doc.version_keywords[self.one_dot_version] = keyword
def create_tarball_symlink(self, doc):
tarball_dest = '../%s-html-%s.tar.gz' % (self.modulename, self.version)
in_version_path = os.path.join(
app.get_module_web_output_dir(self),
'%s-html.tar.gz' % self.modulename)
if not self.one_dot_version in in_version_path:
return
if os.path.islink(in_version_path):
os.unlink(in_version_path)
os.symlink(tarball_dest, in_version_path)