diff options
Diffstat (limited to 'web-export')
-rw-r--r-- | web-export/README | 9 | ||||
-rw-r--r-- | web-export/specs.idx | 91 | ||||
-rwxr-xr-x | web-export/update.py | 274 |
3 files changed, 374 insertions, 0 deletions
diff --git a/web-export/README b/web-export/README new file mode 100644 index 0000000..94cbdbc --- /dev/null +++ b/web-export/README @@ -0,0 +1,9 @@ +This directory contains the files used to export the specifications on + http://specifications.freedesktop.org/ + +It's mostly two files: + + - specs.idx: information on where to fetch specific versions of different + specifications (usually CVS or git) + + - update.py: hacky script that uses specs.idx and creates html pages diff --git a/web-export/specs.idx b/web-export/specs.idx new file mode 100644 index 0000000..4d0dde1 --- /dev/null +++ b/web-export/specs.idx @@ -0,0 +1,91 @@ +git:xdg/xdg-specs:autostart/autostart-spec.xml master 0.5 autostart-spec + +git:xdg/xdg-specs:basedir/basedir-spec.xml master 0.8 basedir-spec +git:xdg/xdg-specs:basedir/basedir-spec.xml 5c950648d4e3b186bda82c0c27ef089ee6747cbd 0.7 basedir-spec +git:xdg/xdg-specs:basedir/basedir-spec.xml 2c096d0c74244bd573027b217be3a69335a923f4 0.6 basedir-spec +# Invalid docbook: +#git:xdg/xdg-specs:basedir/basedir-spec.xml c8475bef1d1f84afcc89c710b6b5b214f11a670f 0.5 basedir-spec + +icccm-extensions/selections/clipboards.txt 1.2 0.1 clipboards-spec +icccm-extensions/selections/clipboard-extensions.txt 1.1 0.1 clipboard-extensions-spec + +git:dbus/dbus:doc/introspect.dtd 7652304bff969afb3969603149bb385efe861fe8 1.0 dbus + +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml master 1.1 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml e1775a202af19adf9c73e6954293e2e95f8f13a0 1.0 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml 7d249792235d0f3b69f833f89bef545a367f0b6b 0.9.8 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml 3e675b52041139085cc280dcdf2562e38cba8a31 0.9.7 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml af1b346daa90b9cb88ec9e3b6d3ebd05942a73d7 0.9.6 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml 6855384d021d88557f80674798c584c15b547f36 0.9.5 desktop-entry-spec +# Invalid docbook: +#git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.xml b818b36ff0ee3c7f35df7b38db15a18b434f6375 0.9.4 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.sgml e7d2b4770815f8d8dcca934d3520d3fe55f86b09 0.9.3 desktop-entry-spec +git:xdg/xdg-specs:desktop-entry/desktop-entry-spec.sgml 9c493d5fca5fcceca4e1bc0b2b2ba8a13c5eb12e 0.9.2 desktop-entry-spec + +git:xdg/default-icon-theme:spec/icon-naming-spec.xml master 0.8.90 icon-naming-spec +git:xdg/default-icon-theme:spec/icon-naming-spec.xml 77bc8ba641ca24bf2e55292f7d31926d60295e5c 0.8 icon-naming-spec +git:xdg/default-icon-theme:spec/icon-naming-spec.xml aba09c448ecc055f93a959a54497ef02be4ceab2 0.7 icon-naming-spec +git:xdg/default-icon-theme:spec/icon-naming-spec.xml 678139104048733b680c331d28ee09f6f16f386c 0.6 icon-naming-spec +git:xdg/default-icon-theme:spec/icon-naming-spec.xml 1dc55c9db340a7d0a9ac84e1e42735df311cdad5 0.4 icon-naming-spec +# Invalid docbook: +#git:xdg/default-icon-theme:spec/icon-naming-spec.xml db9bb955c0cf20322b149676b908ecd69929d2f1 0.3 icon-naming-spec + +git:xdg/default-icon-theme:spec/icon-theme-spec.xml e54ef4b65ae0eab72ffe23e18a470072e1719471 0.12 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml f09150e444382a18d147ef45afa9310e2e27c713 0.11 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml 37f3118e81954b2171a333614901a0b74c295edc 0.10 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml 400de5cb3e4f8046763ce816fb93a9ec287e6e39 0.9 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml 61ce5bd0f09d5026b32f015f7f8d209524b85cf1 0.8 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml bd6077c5fc235d830d325a977770150bd2d71136 0.7 icon-theme-spec +git:xdg/default-icon-theme:spec/icon-theme-spec.xml b1a891e95eb4f28da4e43fb6cb7a662bc0431529 0.6 icon-theme-spec + +git:xdg/xdg-specs:menu/menu-spec.xml master 1.1 menu-spec +git:xdg/xdg-specs:menu/menu-spec.xml 647153fb87e5f642a7b7a3fdcec90961f36e89ab 1.0 menu-spec +git:xdg/xdg-specs:menu/menu-spec.xml a61b06aa1aee4743f50024b0695795fe9568d929 0.92 menu-spec +git:xdg/xdg-specs:menu/menu-spec.xml 2403355e486ac6bc972fd150d38e3c44d086960a 0.91 menu-spec +git:xdg/xdg-specs:menu/menu-spec.xml e1b6bf680dc4d021e7f2122841f812975a31985c 0.9 menu-spec +# Invalid docbook: +#git:xdg/xdg-specs:menu/menu-spec.xml 7d616706bba168427214848c6fbb77da5a30e04d 0.8 menu-spec +#git:xdg/xdg-specs:menu/menu-spec.xml 28a4c60cb40502c01417bfdbd8a2e093eb4af2d9 0.7 menu-spec +#git:xdg/xdg-specs:menu/menu-spec.xml 9f969d0e6625b2da24fb971ebd3cf7f913a1c5f1 0.6 menu-spec +#git:xdg/xdg-specs:menu/menu-spec.xml c15b9df59efac72ea80fb715bf2a9d7f7afd1bba 0.5 menu-spec +#git:xdg/xdg-specs:menu/menu-spec.xml c8475bef1d1f84afcc89c710b6b5b214f11a670f 0.4 menu-spec +git:xdg/xdg-specs:menu/menu.dtd 2403355e486ac6bc972fd150d38e3c44d086960a 0.91 menu-spec + +recent-files/recent-file-spec/recent-file-spec.xml 1.1 0.2 recent-file-spec + +git:xdg/shared-mime-info:shared-mime-info-spec.xml 2f909cff817a3f08d12321769173cac2de0da1b4 0.20 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 30349a8810143c1f808a74c96bceba87d48e8364 0.19 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 1bac8224c7439452a85693dc1a25f64d3a467e7d 0.18 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 83c091bbb4d32231b308864d227ada6106bc59a5 0.17 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 6c474418318c6c192abfe0f17f85209c65bfa1cf 0.16 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 7fab0df72e558a1d651e2557d52ac37b8d5020e9 0.15 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 0239582644c9edffa7edd4562ccb967d14d63e73 0.14 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml f364fdbba5bb7fe8b69e0294aa353845515b191e 0.13 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml ad3203089d3d029b5c18ebd4baa6f7991dd9bb22 0.12 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 92cca5e4cec157f252fd77b5ce23853974603906 0.11 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml dc2724f1d1b010a80b269ef21a1e613f55170777 0.10 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml e1359233cf0544509854178e8591ed39b5ccbcdf 0.9 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 7b25e407e6dc6cda94c2fb1f83b4ac4956a22fbf 0.8 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml d08ddd99abf32cbf770fecc43f950f4a8c7a4dc0 0.7 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 1dd7f6ce4610378b970674cfef61e1bda2389ba5 0.6 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml 2e3dfe6117ec97da5493669a05459fdcac914e1c 0.5 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml bfd730e142344783603ac4cdf0467ccf2e2ff1fd 0.4 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml f6fa8bf89055da53e9323aca59d5337729178ade 0.3 shared-mime-info-spec +git:xdg/shared-mime-info:shared-mime-info-spec.xml e235408efaeec39b5be22d4f1d4218da64247d74 0.2 shared-mime-info-spec + +git:startup-notification:doc/startup-notification.txt master 0.2 startup-notification-spec +git:startup-notification:doc/startup-notification.txt e1d689b36635ed632cbb91cf3104f84bd0b59bfd 0.1 startup-notification-spec + +git:xdg/xdg-specs:systemtray/systemtray-spec.xml cbe62e957475dba73d9d830dd755c76f8d3abd23 0.3 systemtray-spec +git:xdg/xdg-specs:systemtray/systemtray-spec.xml 87fb46a8631a8b509bb1b8026b88c7059f869ffd 0.2 systemtray-spec +git:xdg/xdg-specs:systemtray/systemtray-spec.xml c8475bef1d1f84afcc89c710b6b5b214f11a670f 0.1 systemtray-spec + +git:xdg/xdg-specs:wm-spec/wm-spec.xml master 1.5 wm-spec +git:xdg/xdg-specs:wm-spec/wm-spec.xml a95af55a102b0814e81095bda46a691068009c3c 1.4 wm-spec +git:xdg/xdg-specs:wm-spec/wm-spec.xml 2eafacb23421d25147533a66a9eb8f0f4650a5e4 1.3 wm-spec +git:xdg/xdg-specs:wm-spec/wm-spec.sgml d10d819f39c4c7e878288192f14248536d9d4b96 1.2 wm-spec +git:xdg/xdg-specs:wm-spec/wm-spec.sgml a6e9a0a88112e5f6ac7099530e5c732c7ec6fb7f 1.1 wm-spec +# Invalid docbook: +#git:xdg/xdg-specs:wm-spec/wm-spec.sgml b58352845cebc1d3b5754215a03ed047d1b28b11 1.0 wm-spec + +xembed/xembed/spec/xembed-spec.xml 1.2 0.5 xembed-spec diff --git a/web-export/update.py b/web-export/update.py new file mode 100755 index 0000000..cd54f28 --- /dev/null +++ b/web-export/update.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python + +# Dependencies to run this: +# - xmlto in $PATH + +# FIXME: +# - correctly handle all exceptions +# - copy dtd files where they should be +# - new structure for website: +# specs.fd.o/index.html -- general index +# specs.fd.o/desktop-entry/index.html -- index of all versions of desktop entry, with all formats +# specs.fd.o/desktop-entry/1.0/desktop-entry-spec.xml -- docbook version of the spec 1.0 +# specs.fd.o/desktop-entry/1.0/index.html -- one-page html version of the spec 1.0 +# specs.fd.o/desktop-entry/1.0/split/ -- multiple-page html version of the spec 1.0 +# specs.fd.o/desktop-entry/latest/ -- link to directory containing latest version of the spec + +import os +import sys + +import errno + +import StringIO +import hashlib +import shutil +import subprocess +import urllib +import urllib2 +import urlparse + +DEVELOPMENT = False + +CVSWEB = 'http://cvs.freedesktop.org' +GITWEB = 'http://cgit.freedesktop.org' +HASH = 'md5' + + +def safe_mkdir(dir): + if not dir: + return + + try: + os.mkdir(dir) + except OSError, e: + if e.errno != errno.EEXIST: + raise e + + +def get_hash_from_fd(fd, algo = HASH, read_blocks = 1024): + if algo not in [ 'md5' ]: + raise Exception('Internal error: hash algorithm \'%s\' not planned in code.' % algo) + + hash = hashlib.new(algo) + while True: + data = fd.read(read_blocks) + if not data: + break + hash.update(data) + return hash.digest() + + +def get_hash_from_url(url, algo = HASH): + fd = urllib2.urlopen(url, None) + digest = get_hash_from_fd(fd, algo) + fd.close() + return digest + + +def get_hash_from_path(path, algo = HASH): + fd = open(path, 'rb') + digest = get_hash_from_fd(fd, algo, read_blocks = 32768) + fd.close() + return digest + + +def get_hash_from_data(data, algo = HASH): + fd = StringIO.StringIO(data) + digest = get_hash_from_fd(fd, algo, read_blocks = 32768) + fd.close() + return digest + + +class VcsObject: + def __init__(self, vcs, repo, file, revision = None): + self.vcs = vcs + self.repo = repo + self.file = file + self.revision = revision + self.data = None + + def get_url(self): + query = {} + if self.vcs == 'git': + baseurl = GITWEB + path = '/'.join((self.repo, 'plain', self.file)) + if self.revision: + query['id'] = self.revision + elif self.vcs == 'cvs': + baseurl = CVSWEB + path = self.file + if self.revision: + query['rev'] = self.revision + else: + raise Exception('Unknown VCS: %s' % self.vcs) + + (scheme, netloc, basepath) = urlparse.urlsplit(baseurl)[0:3] + full_path = '/'.join((basepath, path)) + + query_str = urllib.urlencode(query) + return urlparse.urlunsplit((scheme, netloc, full_path, query_str, '')) + + def fetch(self): + if self.data: + return + + url = self.get_url() + fd = urllib2.urlopen(url, None) + self.data = fd.read() + fd.close() + + def get_hash(self): + self.fetch() + return get_hash_from_data(self.data) + + +class SpecObject(): + def __init__(self, vcs, spec_dir, version): + self.vcs = vcs + self.spec_dir = spec_dir + self.version = version + + basename = os.path.basename(self.vcs.file) + (self.basename_no_ext, self.ext) = os.path.splitext(basename) + + self.filename = '%s-%s%s' % (self.basename_no_ext, self.version, self.ext) + + if self.ext not in ['.xml', '.sgml', '.txt', '.dtd']: + raise Exception('Format \'%s\' not supported for %s' % (self.ext, self.vcs.get_url())) + + self.downloaded = False + self.one_chunk = False + self.multiple_chunks = False + + def download(self): + safe_mkdir(self.spec_dir) + path = os.path.join(self.spec_dir, self.filename) + + if os.path.exists(path): + current_hash = get_hash_from_path(path) + vcs_hash = self.vcs.get_hash() + if current_hash == vcs_hash: + return + + self.vcs.fetch() + fd = open(path, 'wb') + fd.write(self.vcs.data) + fd.close() + + self.downloaded = True + + def htmlize(self, force = False): + if not self.downloaded and not force: + return + + path = os.path.join(self.spec_dir, self.filename) + (path_no_ext, ext) = os.path.splitext(path) + + # One-chunk HTML + html_path = '%s%s' % (path_no_ext, '.html') + if os.path.exists(html_path): + os.unlink(html_path) + + # Multiple chunks + html_dir = os.path.join(self.spec_dir, self.version) + if os.path.exists(html_dir): + shutil.rmtree(html_dir) + + one_chunk_command = None + multiple_chunks_command = None + + if self.ext == '.xml': + one_chunk_command = ['xmlto', '-o', self.spec_dir, 'html-nochunks', path] + multiple_chunks_command = ['xmlto', '-o', html_dir, 'html', path] + elif self.ext == '.sgml': + one_chunk_command = ['docbook2html', '-o', self.spec_dir, '--nochunks', path] + multiple_chunks_command = ['docbook2html', '-o', html_dir, path] + + if one_chunk_command: + retcode = subprocess.call(one_chunk_command) + if retcode != 0: + raise Exception('Cannot convert \'%s\' to HTML.' % path) + self.one_chunk = True + + if multiple_chunks_command: + safe_mkdir(html_dir) + retcode = subprocess.call(multiple_chunks_command) + if retcode != 0: + raise Exception('Cannot convert \'%s\' to multiple-chunks HTML.' % path) + self.multiple_chunks = True + + def latestize(self): + filename_latest = '%s-latest%s' % (self.basename_no_ext, self.ext) + + path_latest = os.path.join(self.spec_dir, filename_latest) + if os.path.exists(path_latest): + os.unlink(path_latest) + os.symlink(self.filename, path_latest) + + if self.ext in ['.xml', '.sgml']: + # One-chunk HTML + html_path_latest = os.path.join(self.spec_dir, '%s-latest%s' % (self.basename_no_ext, '.html')) + if os.path.exists(html_path_latest): + os.unlink(html_path_latest) + + (filename_no_ext, ext) = os.path.splitext(self.filename) + html_filename = '%s%s' % (filename_no_ext, '.html') + html_path = os.path.join(self.spec_dir, html_filename) + if os.path.exists(html_path): + os.symlink(html_filename, html_path_latest) + + # Multiple chunks + html_dir_latest = os.path.join(self.spec_dir, 'latest') + if os.path.exists(html_dir_latest): + os.unlink(html_dir_latest) + + html_dir = os.path.join(self.spec_dir, self.version) + if os.path.exists(html_dir): + os.symlink(self.version, html_dir_latest) + + +SCRIPT = VcsObject('git', 'xdg/xdg-specs', 'web-export/update.py') +SPECS_INDEX = VcsObject('git', 'xdg/xdg-specs', 'web-export/specs.idx') + + +def is_up_to_date(): + current_hash = get_hash_from_path(__file__) + vcs_hash = SCRIPT.get_hash() + + return current_hash == vcs_hash + + +if not DEVELOPMENT: + if not is_up_to_date(): + print >>sys.stderr, 'Script is not up-to-date, please download %s' % SCRIPT.get_url() + sys.exit(1) + + SPECS_INDEX.fetch() + lines = SPECS_INDEX.data.split('\n') +else: + lines = open('specs.idx').readlines() + + +latests = [] + +for line in lines: + line = line.strip() + if not line or line.startswith('#'): + continue + + (data, revision, version, path) = line.split() + if data.startswith("git:"): + git_data = data.split(":") + vcs = VcsObject('git', git_data[1], git_data[2], revision) + else: + vcs = VcsObject('cvs', None, data, revision) + + spec = SpecObject(vcs, path, version) + + spec.download() + spec.htmlize() + + # Create latest links if it's the first time we see this spec + if (spec.spec_dir, spec.basename_no_ext) not in latests: + latests.append((spec.spec_dir, spec.basename_no_ext)) + spec.latestize() |