summaryrefslogtreecommitdiffstats
path: root/web-export
diff options
context:
space:
mode:
Diffstat (limited to 'web-export')
-rw-r--r--web-export/README9
-rw-r--r--web-export/specs.idx91
-rwxr-xr-xweb-export/update.py274
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()