[commit: packages/directory] master: Implement support for XDG-conforming application directories (ab9d081)

git at git.haskell.org git at git.haskell.org
Fri Dec 18 09:50:24 UTC 2015


Repository : ssh://git@git.haskell.org/directory

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/ab9d0810ce0172e10ff1ca437ad7f723d6648f0d/directory

>---------------------------------------------------------------

commit ab9d0810ce0172e10ff1ca437ad7f723d6648f0d
Author: Phil Ruffwind <rf at rufflewind.com>
Date:   Sun Apr 26 22:11:47 2015 -0400

    Implement support for XDG-conforming application directories
    
    This addresses issue #6 in a backward-compatible way by adding a new
    function that conforms to the XDG Base Directory Specification.


>---------------------------------------------------------------

ab9d0810ce0172e10ff1ca437ad7f723d6648f0d
 System/Directory.hs | 122 +++++++++++++++++++++++++++++++++++++++++-----------
 changelog.md        |   5 +++
 directory.cabal     |   2 +-
 3 files changed, 103 insertions(+), 26 deletions(-)

diff --git a/System/Directory.hs b/System/Directory.hs
index d49d909..43edc9a 100644
--- a/System/Directory.hs
+++ b/System/Directory.hs
@@ -34,6 +34,8 @@ module System.Directory
 
     -- * Pre-defined directories
     , getHomeDirectory
+    , XdgDirectory(..)
+    , getXdgDirectory
     , getAppUserDataDirectory
     , getUserDocumentsDirectory
     , getTemporaryDirectory
@@ -80,6 +82,7 @@ module System.Directory
     , getModificationTime
    ) where
 
+import System.Environment ( getEnv )
 import System.FilePath
 import System.IO
 import System.IO.Error
@@ -111,7 +114,6 @@ import qualified System.Win32 as Win32
 #else
 import GHC.IO.Encoding
 import GHC.Foreign as GHC
-import System.Environment ( getEnv )
 import qualified System.Posix as Posix
 #endif
 
@@ -1169,31 +1171,101 @@ getHomeDirectory =
     getEnv "HOME"
 #endif
 
-{- | Returns the pathname of a directory in which application-specific
-data for the current user can be stored.  The result of
-'getAppUserDataDirectory' for a given application is specific to
-the current user.
-
-The argument should be the name of the application, which will be used
-to construct the pathname (so avoid using unusual characters that
-might result in an invalid pathname).
-
-Note: the directory may not actually exist, and may need to be created
-first.  It is expected that the parent directory exists and is
-writable.
-
-On Unix, this function returns @$HOME\/.appName at .  On Windows, a
-typical path might be @C:\/Users\//\<user\>/\/AppData\/Roaming\//\<app\>/@
-
-The operation may fail with:
-
-* 'UnsupportedOperation'
-The operating system has no notion of application-specific data directory.
+-- | Special directories for storing user-specific application data,
+--   configuration, and cache files, as specified by the
+--   <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG Base Directory Specification>.
+--
+--   These will also work on Windows, although in that case 'XdgData' and
+--   'XdgConfig' will map to the same directory.
+--
+--   Note: the directory may not actually exist, in which case you would need
+--   to create it with file mode @700@ (i.e. only accessible by the owner).
+--
+--   /Since: 1.2.3.0/
+data XdgDirectory
+  = XdgData
+    -- ^ Data files:
+    --   may be overridden by the @XDG_DATA_HOME@ environment variable;
+    --   defaults to @~\/.local\/share@;
+    --   Windows equivalent: @%APPDATA%@
+    --   (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming@)
+  | XdgConfig
+    -- ^ For configuration files;
+    --   may be overridden by the @XDG_CONFIG_HOME@ environment variable;
+    --   defaults to @~\/.config@;
+    --   Windows equivalent: @%APPDATA%@
+    --   (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming@)
+  | XdgCache
+    -- ^ For non-essential (cached) data;
+    --   may be overridden by the @XDG_CACHE_HOME@ environment variable;
+    --   defaults to @~\/.cache@;
+    --   Windows equivalent: @%LOCALAPPDATA%@
+    --   (e.g. @C:\/Users\//\<user\>/\/AppData\/Local@)
+  deriving (Eq, Ord, Read, Show)
+
+-- | Obtain the path to special directories for storing user-specific
+--   application data, configuration, and cache files, as specified by the
+--   <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG Base Directory Specification>.
+--
+--   These will also work on Windows, although in that case 'XdgData' and
+--   'XdgConfig' will map to the same directory.  See 'XdgDirectory' for
+--   details.
+--
+--   Note: the directory may not actually exist, in which case you would need
+--   to create it with file mode @700@ (i.e. only accessible by the owner).
+--
+--   /Since: 1.2.3.0/
+getXdgDirectory :: XdgDirectory -> IO FilePath
+getXdgDirectory xdgDir = modifyIOError (`ioeSetLocation` "getXdgDirectory") $
+  case xdgDir of
+    XdgData   -> get "XDG_DATA_HOME"   (alternative False ".local/share")
+    XdgConfig -> get "XDG_CONFIG_HOME" (alternative False ".config")
+    XdgCache  -> get "XDG_CACHE_HOME"  (alternative True  ".cache")
+  where get name fallback = do
+          env <- tryIOErrorType isDoesNotExistError (getEnv name)
+          case env of
+            Left  _                      -> fallback
+            Right path | isRelative path -> fallback
+                       | otherwise       -> return (normalise path)
+        tryIOErrorType check action = do
+          result <- tryIOError action
+          case result of
+            Left  err -> if check err then return (Left err) else throwIO err
+            Right val -> return (Right val)
+#if defined(mingw32_HOST_OS)
+        alternative local _ =
+          normalise `fmap` Win32.sHGetFolderPath nullPtr which nullPtr 0
+          where which | local     = Win32.cSIDL_LOCAL_APPDATA
+                      | otherwise = Win32.cSIDL_APPDATA
+#else
+        alternative _  path = fmap (normalise . (</> path)) getHomeDirectory
+#endif
 
-* 'isDoesNotExistError'
-The home directory for the current user does not exist, or
-cannot be found.
--}
+-- | Obtain the path to a special directory for storing user-specific
+--   application data.
+--
+--   The argument should the name of the application, which will be integrated
+--   into the directory name and therefore should not contain any unusual
+--   characters that result in an invalid path.
+--
+--   * On Unix-like systems, the path is @~\/./\<app\>/@.
+--   * On Windows, the path is @%APPDATA%\//\<app\>/@
+--     (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming\//\<app\>/@)
+--
+--   Note: the directory may not actually exist, in which case you would need
+--   to create it.  It is expected that the parent directory exists and is
+--   writable.
+--
+--   The operation may fail with:
+--
+--   * 'UnsupportedOperation'
+--     The operating system has no notion of application-specific data
+--     directory.
+--
+--   * 'isDoesNotExistError'
+--     The home directory for the current user does not exist, or cannot be
+--     found.
+--
 getAppUserDataDirectory :: String -> IO FilePath
 getAppUserDataDirectory appName = do
   modifyIOError ((`ioeSetLocation` "getAppUserDataDirectory")) $ do
diff --git a/changelog.md b/changelog.md
index d54fdf8..857d0a7 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,6 +1,11 @@
 Changelog for the [`directory`][1] package
 ==========================================
 
+## 1.2.3.0 (May 2015)
+
+  * Add support for XDG Base Directory Specification
+    ([#6](https://github.com/haskell/directory/issues/6))
+
 ## 1.2.2.1 (Apr 2015)
 
   * Fix dependency problem on NixOS when building with tests
diff --git a/directory.cabal b/directory.cabal
index 396c845..3e5c7fb 100644
--- a/directory.cabal
+++ b/directory.cabal
@@ -1,5 +1,5 @@
 name:           directory
-version:        1.2.2.1
+version:        1.2.3.0
 -- NOTE: Don't forget to update ./changelog.md
 license:        BSD3
 license-file:   LICENSE



More information about the ghc-commits mailing list