summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDieter Verfaillie <dieterv@optionexplicit.be>2015-06-09 21:09:27 +0200
committerDieter Verfaillie <dieterv@optionexplicit.be>2015-06-20 00:32:19 +0200
commitec91f9d11b40de198b2faf8a80b49dbd71107750 (patch)
treeb1a1c1d14800bac46da2ed3f7994f0426f71453a
parent047244537c8ad5725cc3f8e4f9ea0d5e226fe7e0 (diff)
downloadgobject-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.py51
-rw-r--r--giscanner/transformer.py18
-rw-r--r--giscanner/utils.py79
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