[gobject-introspection] scanner: add "XDG Base Directory" functions



commit ec91f9d11b40de198b2faf8a80b49dbd71107750
Author: Dieter Verfaillie <dieterv optionexplicit be>
Date:   Tue Jun 9 21:09:27 2015 +0200

    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

 giscanner/cachestore.py  |   51 ++++++-----------------------
 giscanner/transformer.py |   18 ++++++-----
 giscanner/utils.py       |   79 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+), 48 deletions(-)
---
diff --git a/giscanner/cachestore.py b/giscanner/cachestore.py
index 351bac3..c588792 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 6ae6389..5f88a61 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 537109c..cffbec7 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]