packages feed

plan-b 0.2.0 → 0.2.1

raw patch · 7 files changed

+122/−172 lines, 7 filesdep +semigroupsdep ~basedep ~exceptionsdep ~hspec

Dependencies added: semigroups

Dependency ranges changed: base, exceptions, hspec, path, path-io, plan-b, transformers

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+## Plan B 0.2.1++* Implement `Semigroup` instance for the `PgConfig` type.++* Improved documentation and metadata.+ ## Plan B 0.2.0  * Added `moveByRenaming` option to allow move files and directories by
LICENSE.md view
@@ -1,4 +1,4 @@-Copyright © 2016 Mark Karpov+Copyright © 2016–2017 Mark Karpov  All rights reserved. 
README.md view
@@ -3,6 +3,7 @@ [![License BSD3](https://img.shields.io/badge/license-BSD3-brightgreen.svg)](http://opensource.org/licenses/BSD-3-Clause) [![Hackage](https://img.shields.io/hackage/v/plan-b.svg?style=flat)](https://hackage.haskell.org/package/plan-b) [![Stackage Nightly](http://stackage.org/package/plan-b/badge/nightly)](http://stackage.org/nightly/package/plan-b)+[![Stackage LTS](http://stackage.org/package/plan-b/badge/lts)](http://stackage.org/lts/package/plan-b) [![Build Status](https://travis-ci.org/mrkkrp/plan-b.svg?branch=master)](https://travis-ci.org/mrkkrp/plan-b) [![Coverage Status](https://coveralls.io/repos/mrkkrp/plan-b/badge.svg?branch=master&service=github)](https://coveralls.io/github/mrkkrp/plan-b?branch=master) @@ -11,10 +12,9 @@  ## Quick start -The library allows to create and/or edit files, directories, and-containers. By “container” we mean archive-like object that can contain-representation of a directory inside it. Consequently, we have six functions-available:+The library allows to create and/or edit files, directories, and containers.+By “container” we mean archive-like object that can contain representation+of a directory inside it. Consequently, we have six functions available:  * `withNewFile` * `withExstingFile`@@ -23,16 +23,17 @@ * `withNewContainer` * `withExistingContainer` -You specify name of object to edit or create, options (more on them below),-and action that is passed `Path` argument with the same type as object you-intend to edit (we use type-safe file paths from-[`path`](https://hackage.haskell.org/package/path) package here to prevent a-certain class of potential bugs). Then, having that path, you can do all-actions you want to and if at some point during this editing an exception is-thrown, state of file system is rolled back — you get no corrupted files,-half-way edited directories, everything is intact as if nothing happened at-all. If, however, the action is executed successfully (i.e. no exceptions-thrown), all your manipulations are reflected in the file system.+You specify name of an object to edit or create, options (more on them+below), and an action that gets a `Path` argument with the same type as+object you intend to edit (we use type-safe file paths+from [`path`](https://hackage.haskell.org/package/path) package here to+prevent a certain class of potential bugs). Then, having that path, you can+perform all actions you want to and if at some point during this editing an+exception is thrown, state of file system is rolled back—you get no+corrupted files, half-way edited directories, everything is intact as if+nothing happened at all. If, however, the action is executed successfully+(i.e. no exceptions thrown), all your manipulations are reflected in the+file system.  This is a lightweight solution that makes it harder to corrupt sensitive information. And since file system exists in the real world, all sorts of@@ -43,12 +44,12 @@ used with every function, but wrong combinations won't type-check, so it's OK. -Collection of options is a monoid. `mempty` corresponds to default behavior,-while non-standard behavioral deviations can be `mappend`ed to it.+Collection of options is a monoid. `mempty` corresponds to the default+behavior, while non-standard behavioral deviations can be `mappend`ed to it. -By default, when we want to create new object and it already exists, we get-an exception, two alternative options exist (only work when you create new-object):+By default, when we want to create a new object and it already exists, we+get an exception, two alternative options exist (only work when you create a+new object):  * `overrideIfExist` * `useIfExist`@@ -59,26 +60,28 @@ All functions make use of temporary directories. You can control certain aspects of this business: -* `tempDir dir` — will tell the library to create temporary directories and-  files inside `dir`. By default system's standard temporary directory-  (e.g. `/tmp/` on Unix-like systems) is used.+* `tempDir dir`—tells the library to create temporary directories and files+  inside `dir`. By default system's standard temporary directory (e.g.+  `/tmp/` on Unix-like systems) is used. -* `nameTemplate template` — specifies template to use for generation of-  unique file and directory names. By default `"plan-b"` is used.+* `nameTemplate template`—specifies template to use for generation of unique+  file and directory names. By default `"plan-b"` is used. -* `preserveCorpse` — if you add this to options, in case of failure+* `preserveCorpse`—if you add this to options, in case of failure   (exception), temporary directory is not automatically deleted and can be   inspected. However, if operation succeeds, temporary directory is *always*   deleted. -* `moveByRenaming` — by default files and directories are moved by copying,-  this option enables moving by renaming.+* `moveByRenaming`—by default files and directories are moved by copying,+  this option enables moving by renaming. If you also specify `tempDir` that+  is on the same disk/partition as the final file you're generating, this+  may speed up things considerably.  That should be enough for a quick intro, for more information regarding concrete functions, consult Haddocks.  ## License -Copyright © 2016 Mark Karpov+Copyright © 2016–2017 Mark Karpov  Distributed under BSD 3 clause license.
System/PlanB.hs view
@@ -1,16 +1,16 @@ -- | -- Module      :  System.PlanB--- Copyright   :  © 2016 Mark Karpov+-- Copyright   :  © 2016–2017 Mark Karpov -- License     :  BSD 3 clause ----- Maintainer  :  Mark Karpov <markkarpov@openmailbox.org>+-- Maintainer  :  Mark Karpov <markkarpov92@gmail.com> -- Stability   :  experimental -- Portability :  portable -- -- Failure-tolerant file and directory editing. All functions here can--- recover from exceptions thrown while they work. They bring file-system to--- the state it was in before specific function was called. Temporary files--- and backups are handled automatically.+-- recover from exceptions thrown while they work. They bring file-system+-- into the state it was in before specific function was called. Temporary+-- files and backups are handled automatically.  {-# LANGUAGE DataKinds #-} @@ -46,10 +46,10 @@ ---------------------------------------------------------------------------- -- Operations on files --- | Create new file. Name of the file is taken as the second argument. The--- third argument allows to perform actions (in simplest case just creation--- of file), result of those actions should be new file with given file--- name.+-- | Create a new file. Name of the file is taken as the second argument.+-- The third argument allows to perform actions (in simplest case just+-- creation of file), result of those actions should be new file with the+-- given file name. -- -- This action throws 'alreadyExistsErrorType' by default instead of -- silently overwriting already existing file, use 'overrideIfExists' and@@ -65,9 +65,9 @@   checkExistenceOfFile pbc apath fpath   liftM2 const (action apath) (moveFile pbc apath fpath) --- | Edit existing file. Name of the file is taken as the second+-- | Edit an existing file. Name of the file is taken as the second -- argument. The third argument allows to perform actions on temporary copy--- of specified file.+-- of the specified file. -- -- This action throws 'doesNotExistErrorType' exception if target file does -- not exist.@@ -85,9 +85,9 @@ ---------------------------------------------------------------------------- -- Operations on directories --- | Create new directory. Name of the directory is specified as the second--- argument. The third argument allows to perform actions in “sandboxed”--- version of new directory.+-- | Create a new directory. Name of the directory is specified as the+-- second argument. The third argument allows to perform actions in+-- “sandboxed” version of new directory. -- -- This action throws 'alreadyExistsErrorType' by default instead of -- silently overwriting already existing directory, use 'overrideIfExists'@@ -102,7 +102,7 @@   checkExistenceOfDir pbc tdir dpath   liftM2 const (action tdir) (moveDir pbc tdir dpath) --- | Edit existing directory. Name of the directory is specified as the+-- | Edit an existing directory. Name of the directory is specified as the -- second argument. The third argument allows to perform actions in -- “sandboxed” copy of target directory. --@@ -121,11 +121,11 @@ ---------------------------------------------------------------------------- -- Operations on containers --- | Create new container file. This is suitable for processing of all sorts--- of archive-like objects. The first and second arguments specify how to--- unpack directory from file and pack it back. The fourth argument names--- new file. The fifth argument allows to perform actions knowing name of--- temporary directory.+-- | Create a new container file. This is suitable for processing of all+-- sorts of archive-like objects. The first and second arguments specify how+-- to unpack directory from file and pack it back. The fourth argument names+-- the new file. The fifth argument allows to perform actions knowing name+-- of temporary directory. -- -- This action throws 'alreadyExistsErrorType' by default instead of -- silently overwriting already existing file, use 'overrideIfExists' and@@ -149,11 +149,11 @@       when using (unpack apath tdir)     liftM2 const (action tdir) (pack tdir fpath) --- | Edit existing container file. This is suitable for processing of all+-- | Edit an existing container file. This is suitable for processing of all -- sorts of archive-like objects. The first and second arguments specify how--- to unpack directory from file and pack it back (overwriting old--- version). Fourth argument names container file to edit. The last argument--- allows to perform actions knowing name of temporary directory.+-- to unpack directory from file and pack it back (overwriting old version).+-- Fourth argument names container file to edit. The last argument allows to+-- perform actions knowing name of temporary directory. -- -- This action throws 'doesNotExistErrorType' exception if target file does -- not exist.@@ -175,7 +175,7 @@ ---------------------------------------------------------------------------- -- Helpers --- | Use temporary directory. This action is controlled by supplied+-- | Use a temporary directory. This action is controlled by the supplied -- configuration, see 'HasTemp'. The temporary directory is removed -- automatically when given action finishes, although this can be changed -- via the mentioned configuration value too. If given action finishes@@ -206,14 +206,14 @@   -> Path Abs File     -- ^ Resulting path constructFilePath dir file = dir </> filename file --- | Check existence of file and perform actions according to given--- configuration. By default we throw 'alreadyExistsErrorType' unless user--- has specified different 'AlreadyExistsBehavior'. If it's 'AebOverride',--- then we don't need to do anything, file will be overwritten--- automatically, if we have 'AebUse', then we should copy it into given--- directory.+-- | Check existence of file and perform actions according to the given+-- configuration. By default we throw 'alreadyExistsErrorType' unless the+-- user has specified different 'AlreadyExistsBehavior'. If it's+-- 'AebOverride', then we don't need to do anything, file will be+-- overwritten automatically, if we have 'AebUse', then we should copy it+-- into given directory. -checkExistenceOfFile :: (CanHandleExisting c, MonadIO m, MonadThrow m)+checkExistenceOfFile :: (CanHandleExisting c, MonadIO m)   => c                 -- ^ Configuration   -> Path Abs File     -- ^ Where to copy file (when we have 'AebUse')   -> Path b   File     -- ^ File to check@@ -229,10 +229,10 @@       Just AebOverride -> return ()       Just AebUse -> copyFile fpath apath --- | Check existence of directory and perform actions according to given+-- | Check existence of directory and perform actions according to the given -- configuration. See 'checkExistenceOfFile', overall behavior is the same. -checkExistenceOfDir :: (CanHandleExisting c, MonadIO m, MonadThrow m)+checkExistenceOfDir :: (CanHandleExisting c, MonadIO m)   => c                 -- ^ Configuration   -> Path Abs Dir      -- ^ Where to copy directory (when we have 'AebUse')   -> Path b   Dir      -- ^ Directory to check@@ -248,8 +248,8 @@       Just AebOverride -> return ()       Just AebUse -> copyDir dpath apath --- | Move specified file to another location. File can be moved either by--- copying or by renaming, exact method is determined by supplied+-- | Move a specified file to another location. File can be moved either by+-- copying or by renaming, exact method is determined by the supplied -- configuration.  moveFile :: (HasTemp c, MonadIO m)@@ -259,10 +259,10 @@   -> m () moveFile pbc = bool P.copyFile P.renameFile (getMoveByRenaming pbc) --- | Move specified directory to another location. If destination location+-- | Move a specified directory to another location. If destination location -- is already occupied, delete that object first. Directory can be moved--- either by copying or by renaming, exact method is determined by supplied--- configuration.+-- either by copying or by renaming, exact method is determined by the+-- supplied configuration.  moveDir :: (HasTemp c, MonadIO m, MonadCatch m)   => c                 -- ^ Configuration@@ -274,10 +274,10 @@   when exists (P.removeDirRecur dest)   bool P.copyDirRecur P.renameDir (getMoveByRenaming pbc) src dest --- | Copy file to new location. Throw 'doesNotExistErrorType' if it does not--- exist.+-- | Copy a file to a new location. Throw 'doesNotExistErrorType' if it does+-- not exist. -copyFile :: (MonadIO m, MonadThrow m)+copyFile :: MonadIO m   => Path b0 File      -- ^ Original location   -> Path b1 File      -- ^ Where to put copy of the file   -> m ()@@ -291,8 +291,8 @@       mkIOError doesNotExistErrorType location Nothing (Just fsrc)  -- | Copy contents of one directory into another (recursively). Source--- directory must exist, otherwise 'doesNotExistErrorType' is--- thrown. Destination directory will be created if it doesn't exist.+-- directory must exist, otherwise 'doesNotExistErrorType' is thrown.+-- Destination directory will be created if it doesn't exist.  copyDir :: (MonadIO m, MonadCatch m)   => Path b0 Dir       -- ^ Original location@@ -307,7 +307,7 @@      else throwM $        mkIOError doesNotExistErrorType location Nothing (Just fsrc) --- | Perform specified action ignoring IO exceptions it may throw.+-- | Perform an action ignoring IO exceptions it may throw.  ignoringIOErrors :: MonadCatch m => m () -> m () ignoringIOErrors ioe = ioe `catch` handler
System/PlanB/Type.hs view
@@ -1,15 +1,14 @@ -- | -- Module      :  System.PlanB.Type--- Copyright   :  © 2016 Mark Karpov+-- Copyright   :  © 2016–2017 Mark Karpov -- License     :  BSD 3 clause ----- Maintainer  :  Mark Karpov <markkarpov@openmailbox.org>+-- Maintainer  :  Mark Karpov <markkarpov92@gmail.com> -- Stability   :  experimental -- Portability :  portable ----- Types and type classes for “Plan B” library. You usually don't need to--- import this module because "System.PlanB" already exports everything you--- need.+-- Types and type classes. You usually don't need to import this module+-- because "System.PlanB" already exports everything you need.  {-# LANGUAGE DataKinds         #-} {-# LANGUAGE FlexibleInstances #-}@@ -25,11 +24,11 @@ where  import Control.Applicative-import Data.Monoid+import Data.Semigroup import Path --- | We use this as named kind with two promoted constructors. The--- constructors are used as phantom types to index 'PbConfig'.+-- | We use this as a kind with two promoted constructors. The constructors+-- are used as phantom types to index 'PbConfig'.  data Subject = New | Existing @@ -40,9 +39,9 @@   | AebUse             -- ^ Continue to work with that object instead   deriving (Eq, Enum, Bounded) --- | The configuration allows to control behavior of the library in--- details. It's a 'Monoid' and so various configuration settings can be--- combined using 'mappend' while 'mempty' represents default behavior.+-- | The configuration allows to control behavior of the library in details.+-- It's a 'Monoid' and so various configuration settings can be combined+-- using 'mappend' while 'mempty' represents default behavior. -- -- When combining conflicting configuration settings, the value on the left -- side of 'mappend' wins:@@ -58,28 +57,31 @@     , pbcAlreadyExists  :: Maybe AlreadyExistsBehavior     } -> PbConfig k -instance Monoid (PbConfig k) where-  mempty  = PbConfig empty empty mempty mempty empty-  x `mappend` y = PbConfig+instance Semigroup (PbConfig k) where+  x <> y = PbConfig     { pbcTempDir        = pbcTempDir x       <|> pbcTempDir y     , pbcNameTemplate   = pbcNameTemplate x  <|> pbcNameTemplate y     , pbcPreserveCorpse = pbcPreserveCorpse x <> pbcPreserveCorpse y     , pbcMoveByRenaming = pbcMoveByRenaming x <> pbcMoveByRenaming y     , pbcAlreadyExists  = pbcAlreadyExists x <|> pbcAlreadyExists y } --- | The type class is for data types that include information specifying--- how to create temporary files and directories and whether to delete them--- automatically or not.+instance Monoid (PbConfig k) where+  mempty  = PbConfig empty empty mempty mempty empty+  mappend = (<>) +-- | The type class is for the data types that include information+-- specifying how to create temporary files and directories and whether to+-- delete them automatically or not.+ class HasTemp c where -  -- | Specifies name of temporary directory to use. Default is the system+  -- | Specify name of temporary directory to use. The default is the system   -- temporary directory. If the directory does not exist, it will be-  -- created, but not deleted.+  -- created, but won't be deleted.    tempDir :: Path Abs Dir -> c -  -- | Specify template to use to name temporary directory, see+  -- | Specify the template string to use to name temporary directory, see   -- 'System.Directory.openTempFile', default is @\"plan-b\"@.    nameTemplate :: String -> c
plan-b.cabal view
@@ -1,49 +1,18 @@------ Cabal configuration for ‘plan-b’.------ Copyright © 2016 Mark Karpov------ Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are--- met:------ * Redistributions of source code must retain the above copyright notice,---   this list of conditions and the following disclaimer.------ * Redistributions in binary form must reproduce the above copyright---   notice, this list of conditions and the following disclaimer in the---   documentation and/or other materials provided with the distribution.------ * Neither the name Mark Karpov nor the names of contributors may be used---   to endorse or promote products derived from this software without---   specific prior written permission.------ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS “AS IS” AND ANY--- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED--- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE--- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY--- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL--- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS--- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)--- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,--- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN--- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE--- POSSIBILITY OF SUCH DAMAGE.- name:                 plan-b-version:              0.2.0+version:              0.2.1 cabal-version:        >= 1.10+tested-with:          GHC==7.8.4, GHC==7.10.3, GHC==8.0.2, GHC==8.2.1 license:              BSD3 license-file:         LICENSE.md-author:               Mark Karpov <markkarpov@opmbx.org>-maintainer:           Mark Karpov <markkarpov@opmbx.org>+author:               Mark Karpov <markkarpov92@gmail.com>+maintainer:           Mark Karpov <markkarpov92@gmail.com> homepage:             https://github.com/mrkkrp/plan-b bug-reports:          https://github.com/mrkkrp/plan-b/issues category:             System, Filesystem synopsis:             Failure-tolerant file and directory editing build-type:           Simple description:          Failure-tolerant file and directory editing.-extra-source-files:   CHANGELOG.md+extra-doc-files:      CHANGELOG.md                     , README.md  flag dev@@ -52,11 +21,13 @@   default:            False  library-  build-depends:      base         >= 4.7 && < 5-                    , exceptions   >= 0.8-                    , path         >= 0.5-                    , path-io      >= 1.0.1-                    , transformers >= 0.3+  build-depends:      base         >= 4.7   && < 5.0+                    , exceptions   >= 0.8   && < 0.9+                    , path         >= 0.5   && < 0.6+                    , path-io      >= 1.0.1 && < 2.0+                    , transformers >= 0.3   && < 0.6+  if !impl(ghc >= 8.0)+    build-depends:    semigroups   == 0.18.*   exposed-modules:    System.PlanB                     , System.PlanB.Type   if flag(dev)@@ -73,11 +44,11 @@     ghc-options:      -Wall -Werror   else     ghc-options:      -O2 -Wall-  build-depends:      base         >= 4.7 && < 5-                    , hspec        >= 2.0-                    , path         >= 0.5-                    , path-io      >= 1.0.1-                    , plan-b       >= 0.2.0+  build-depends:      base         >= 4.7   && < 5.0+                    , hspec        >= 2.0   && < 3.0+                    , path         >= 0.5   && < 0.6+                    , path-io      >= 1.0.1 && < 2.0+                    , plan-b   default-language:   Haskell2010  source-repository head
tests/Main.hs view
@@ -1,35 +1,3 @@------ Plan B tests.------ Copyright © 2016 Mark Karpov------ Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are--- met:------ * Redistributions of source code must retain the above copyright notice,---   this list of conditions and the following disclaimer.------ * Redistributions in binary form must reproduce the above copyright---   notice, this list of conditions and the following disclaimer in the---   documentation and/or other materials provided with the distribution.------ * Neither the name Mark Karpov nor the names of contributors may be used---   to endorse or promote products derived from this software without---   specific prior written permission.------ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS “AS IS” AND ANY--- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED--- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE--- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY--- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL--- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS--- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)--- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,--- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN--- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE--- POSSIBILITY OF SUCH DAMAGE.- {-# LANGUAGE CPP                #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE TemplateHaskell    #-}