diff options
author | Dieter Verfaillie <dieterv@optionexplicit.be> | 2015-06-09 21:09:27 +0200 |
---|---|---|
committer | Dieter Verfaillie <dieterv@optionexplicit.be> | 2015-06-20 00:32:19 +0200 |
commit | ec91f9d11b40de198b2faf8a80b49dbd71107750 (patch) | |
tree | b1a1c1d14800bac46da2ed3f7994f0426f71453a | |
parent | 047244537c8ad5725cc3f8e4f9ea0d5e226fe7e0 (diff) | |
download | gobject-introspection-ec91f9d11b40de198b2faf8a80b49dbd71107750.tar.gz |
scanner: add "XDG Base Directory" functions
Extract cache and data dir lookup code into documented
get_user_cache_dir() and get_system_data_dirs() functions.
Note that previously, the data dirs code did not fall
back to '/usr/local/share:/usr/share' when the XDG_DATA_DIRS
environment variable was either not set or empty, as required
by the XDG Base Directory Specification.
https://bugzilla.gnome.org/show_bug.cgi?id=747770
-rw-r--r-- | giscanner/cachestore.py | 51 | ||||
-rw-r--r-- | giscanner/transformer.py | 18 | ||||
-rw-r--r-- | giscanner/utils.py | 79 |
3 files changed, 100 insertions, 48 deletions
diff --git a/giscanner/cachestore.py b/giscanner/cachestore.py index 351bac38..c588792d 100644 --- a/giscanner/cachestore.py +++ b/giscanner/cachestore.py @@ -29,6 +29,9 @@ import tempfile import giscanner +from . import utils + + _CACHE_VERSION_FILENAME = '.cache-version' @@ -42,51 +45,19 @@ def _get_versionhash(): return hashlib.sha1(''.join(mtimes)).hexdigest() -def _get_cachedir(): - if 'GI_SCANNER_DISABLE_CACHE' in os.environ: - return None - - xdg_cache_home = os.environ.get('XDG_CACHE_HOME') - if xdg_cache_home is not None and os.path.exists(xdg_cache_home): - return xdg_cache_home - - homedir = os.path.expanduser('~') - if homedir is None: - return None - if not os.path.exists(homedir): - return None - - cachedir = os.path.join(homedir, '.cache') - if not os.path.exists(cachedir): - try: - os.mkdir(cachedir, 0o755) - except OSError: - return None - - scannerdir = os.path.join(cachedir, 'g-ir-scanner') - if not os.path.exists(scannerdir): - try: - os.mkdir(scannerdir, 0o755) - except OSError: - return None - # If it exists and is a file, don't cache at all - elif not os.path.isdir(scannerdir): - return None - return scannerdir - - class CacheStore(object): def __init__(self): - try: - self._directory = _get_cachedir() - except OSError as e: - if e.errno != errno.EPERM: - raise - self._directory = None - + self._directory = self._get_cachedir() self._check_cache_version() + def _get_cachedir(self): + if 'GI_SCANNER_DISABLE_CACHE' in os.environ: + return None + else: + cachedir = utils.get_user_cache_dir('g-ir-scanner') + return cachedir + def _check_cache_version(self): if self._directory is None: return diff --git a/giscanner/transformer.py b/giscanner/transformer.py index 6ae63897..5f88a617 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -24,6 +24,7 @@ import subprocess from . import ast from . import message +from . import utils from .cachestore import CacheStore from .girparser import GIRParser from .sourcescanner import ( @@ -40,13 +41,6 @@ class TransformerException(Exception): pass -_xdg_data_dirs = [x for x in os.environ.get('XDG_DATA_DIRS', '').split(os.pathsep)] -_xdg_data_dirs.append(DATADIR) - -if os.name != 'nt': - _xdg_data_dirs.append('/usr/share') - - class Transformer(object): namespace = property(lambda self: self._namespace) @@ -182,9 +176,17 @@ None.""" # Private + def _get_gi_data_dirs(self): + data_dirs = utils.get_system_data_dirs() + data_dirs.append(DATADIR) + if os.name != 'nt': + # For backwards compatibility, was always unconditionally added to the list. + data_dirs.append('/usr/share') + return data_dirs + def _find_include(self, include): searchdirs = self._includepaths[:] - for path in _xdg_data_dirs: + for path in self._get_gi_data_dirs(): searchdirs.append(os.path.join(path, 'gir-1.0')) searchdirs.append(os.path.join(DATADIR, 'gir-1.0')) diff --git a/giscanner/utils.py b/giscanner/utils.py index 537109cd..cffbec78 100644 --- a/giscanner/utils.py +++ b/giscanner/utils.py @@ -18,6 +18,7 @@ # Boston, MA 02111-1307, USA. # +import errno import re import os import subprocess @@ -209,3 +210,81 @@ def which(program): return exe_file + '.exe' return None + + +def makedirs(name, mode=0o777, exist_ok=False): + """Super-mkdir; create a leaf directory and all intermediate ones. Works like + mkdir, except that any intermediate path segment (not just the rightmost) + will be created if it does not exist. If the target directory already + exists, raise an OSError if exist_ok is False. Otherwise no exception is + raised. This is recursive. + + Note: This function has been imported from Python 3.4 sources and adapted to work + with Python 2.X because get_user_cache_dir() uses the exist_ok parameter. It can + be removed again when Python 2.X support is dropped. + """ + head, tail = os.path.split(name) + if not tail: + head, tail = os.path.split(head) + if head and tail and not os.path.exists(head): + try: + makedirs(head, mode, exist_ok) + except OSError as e: + # be happy if someone already created the path + if e.errno != errno.EEXIST: + raise + if tail == cdir: # xxx/newdir/. exists if xxx/newdir exists + return + try: + os.mkdir(name, mode) + except OSError as e: + if not exist_ok or e.errno != errno.EEXIST or not os.path.isdir(name): + raise + + +def get_user_cache_dir(dir=None): + ''' + This is a Python reimplemention of `g_get_user_cache_dir()` because we don't want to + rely on the python-xdg package and we can't depend on GLib via introspection. + If any changes are made to that function they'll need to be copied here. + ''' + + xdg_cache_home = os.environ.get('XDG_CACHE_HOME') + if xdg_cache_home is not None: + if dir is not None: + xdg_cache_home = os.path.join(xdg_cache_home, dir) + try: + makedirs(xdg_cache_home, mode=0o755, exist_ok=True) + except: + # Let's fall back to ~/.cache below + pass + else: + return xdg_cache_home + + homedir = os.path.expanduser('~') + if homedir is not None: + cachedir = os.path.join(homedir, '.cache') + if dir is not None: + cachedir = os.path.join(cachedir, dir) + try: + makedirs(cachedir, mode=0o755, exist_ok=True) + except: + return None + else: + return cachedir + + return None + + +def get_system_data_dirs(): + ''' + This is a Python reimplemention of `g_get_system_data_dirs()` because we don't want to + rely on the python-xdg package and we can't depend on GLib via introspection. + If any changes are made to that function they'll need to be copied here. + ''' + xdg_data_dirs = [x for x in os.environ.get('XDG_DATA_DIRS', '').split(os.pathsep)] + if not xdg_data_dirs and os.name != 'nt': + xdg_data_dirs.append('/usr/local/share') + xdg_data_dirs.append('/usr/share') + + return xdg_data_dirs |