From 09eea518b87e30c965db6c945a327f7a614d49b7 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Sat, 4 Jan 2020 17:52:21 +0100 Subject: [PATCH] Split packages into hpath{,-io,-filepath} --- .ghci | 2 - .travis.yml | 22 ++--- README.md | 90 +++---------------- cabal.project | 4 + hpath-filepath/CHANGELOG.md | 5 ++ hpath-filepath/LICENSE | 30 +++++++ hpath-filepath/README.md | 23 +++++ Setup.hs => hpath-filepath/Setup.hs | 0 hpath-filepath/hpath-filepath.cabal | 39 ++++++++ .../run-doctests.sh | 3 +- .../src}/System/Posix/FilePath.hs | 0 hpath-io/CHANGELOG.md | 5 ++ hpath-io/LICENSE | 30 +++++++ hpath-io/README.md | 26 ++++++ hpath-io/Setup.hs | 2 + {cbits => hpath-io/cbits}/dirutils.c | 0 {cbits => hpath-io/cbits}/dirutils.h | 0 hpath.cabal => hpath-io/hpath-io.cabal | 40 ++++----- {src => hpath-io/src}/HPath/IO.hs | 0 {src => hpath-io/src}/HPath/IO.hs-boot | 0 {src => hpath-io/src}/HPath/IO/Errors.hs | 6 +- .../src}/System/Posix/Directory/Foreign.hsc | 0 .../src}/System/Posix/Directory/Traversals.hs | 0 {src => hpath-io/src}/System/Posix/FD.hs | 0 .../test}/HPath/IO/AppendFileSpec.hs | 1 - .../test}/HPath/IO/CanonicalizePathSpec.hs | 0 .../IO/CopyDirRecursiveCollectFailuresSpec.hs | 3 +- .../HPath/IO/CopyDirRecursiveOverwriteSpec.hs | 9 +- .../test}/HPath/IO/CopyDirRecursiveSpec.hs | 3 +- .../test}/HPath/IO/CopyFileOverwriteSpec.hs | 0 .../test}/HPath/IO/CopyFileSpec.hs | 0 .../test}/HPath/IO/CreateDirRecursiveSpec.hs | 0 .../test}/HPath/IO/CreateDirSpec.hs | 0 .../test}/HPath/IO/CreateRegularFileSpec.hs | 0 .../test}/HPath/IO/CreateSymlinkSpec.hs | 0 .../test}/HPath/IO/DeleteDirRecursiveSpec.hs | 0 .../test}/HPath/IO/DeleteDirSpec.hs | 0 .../test}/HPath/IO/DeleteFileSpec.hs | 0 .../test}/HPath/IO/GetDirsFilesSpec.hs | 0 .../test}/HPath/IO/GetFileTypeSpec.hs | 0 .../test}/HPath/IO/MoveFileOverwriteSpec.hs | 0 .../test}/HPath/IO/MoveFileSpec.hs | 0 .../test}/HPath/IO/ReadFileEOFSpec.hs | 1 - .../test}/HPath/IO/ReadFileSpec.hs | 1 - .../HPath/IO/RecreateSymlinkOverwriteSpec.hs | 0 .../test}/HPath/IO/RecreateSymlinkSpec.hs | 0 .../test}/HPath/IO/RenameFileSpec.hs | 0 {test => hpath-io/test}/HPath/IO/ToAbsSpec.hs | 0 .../test}/HPath/IO/WriteFileSpec.hs | 1 - {test => hpath-io/test}/Main.hs | 9 +- {test => hpath-io/test}/Spec.hs | 0 {test => hpath-io/test}/Utils.hs | 64 +++++-------- CHANGELOG => hpath/CHANGELOG | 0 LICENSE => hpath/LICENSE | 0 hpath/README.md | 37 ++++++++ hpath/Setup.hs | 2 + hpath/hpath.cabal | 44 +++++++++ hpath/run-doctests.sh | 21 +++++ {src => hpath/src}/HPath.hs | 0 {src => hpath/src}/HPath/Internal.hs | 0 update-gh-pages.sh | 55 ------------ 61 files changed, 349 insertions(+), 229 deletions(-) delete mode 100755 .ghci create mode 100644 cabal.project create mode 100644 hpath-filepath/CHANGELOG.md create mode 100644 hpath-filepath/LICENSE create mode 100644 hpath-filepath/README.md rename Setup.hs => hpath-filepath/Setup.hs (100%) create mode 100644 hpath-filepath/hpath-filepath.cabal rename run-doctests.sh => hpath-filepath/run-doctests.sh (70%) rename {src => hpath-filepath/src}/System/Posix/FilePath.hs (100%) create mode 100644 hpath-io/CHANGELOG.md create mode 100644 hpath-io/LICENSE create mode 100644 hpath-io/README.md create mode 100644 hpath-io/Setup.hs rename {cbits => hpath-io/cbits}/dirutils.c (100%) rename {cbits => hpath-io/cbits}/dirutils.h (100%) rename hpath.cabal => hpath-io/hpath-io.cabal (81%) rename {src => hpath-io/src}/HPath/IO.hs (100%) rename {src => hpath-io/src}/HPath/IO.hs-boot (100%) rename {src => hpath-io/src}/HPath/IO/Errors.hs (97%) rename {src => hpath-io/src}/System/Posix/Directory/Foreign.hsc (100%) rename {src => hpath-io/src}/System/Posix/Directory/Traversals.hs (100%) rename {src => hpath-io/src}/System/Posix/FD.hs (100%) rename {test => hpath-io/test}/HPath/IO/AppendFileSpec.hs (99%) rename {test => hpath-io/test}/HPath/IO/CanonicalizePathSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/CopyDirRecursiveCollectFailuresSpec.hs (98%) rename {test => hpath-io/test}/HPath/IO/CopyDirRecursiveOverwriteSpec.hs (96%) rename {test => hpath-io/test}/HPath/IO/CopyDirRecursiveSpec.hs (98%) rename {test => hpath-io/test}/HPath/IO/CopyFileOverwriteSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/CopyFileSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/CreateDirRecursiveSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/CreateDirSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/CreateRegularFileSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/CreateSymlinkSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/DeleteDirRecursiveSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/DeleteDirSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/DeleteFileSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/GetDirsFilesSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/GetFileTypeSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/MoveFileOverwriteSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/MoveFileSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/ReadFileEOFSpec.hs (99%) rename {test => hpath-io/test}/HPath/IO/ReadFileSpec.hs (99%) rename {test => hpath-io/test}/HPath/IO/RecreateSymlinkOverwriteSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/RecreateSymlinkSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/RenameFileSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/ToAbsSpec.hs (100%) rename {test => hpath-io/test}/HPath/IO/WriteFileSpec.hs (99%) rename {test => hpath-io/test}/Main.hs (55%) rename {test => hpath-io/test}/Spec.hs (100%) rename {test => hpath-io/test}/Utils.hs (81%) rename CHANGELOG => hpath/CHANGELOG (100%) rename LICENSE => hpath/LICENSE (100%) create mode 100644 hpath/README.md create mode 100644 hpath/Setup.hs create mode 100644 hpath/hpath.cabal create mode 100755 hpath/run-doctests.sh rename {src => hpath/src}/HPath.hs (100%) rename {src => hpath/src}/HPath/Internal.hs (100%) delete mode 100755 update-gh-pages.sh diff --git a/.ghci b/.ghci deleted file mode 100755 index 01c3587..0000000 --- a/.ghci +++ /dev/null @@ -1,2 +0,0 @@ -:set -package HUnit -package hspec -:set -package template-haskell diff --git a/.travis.yml b/.travis.yml index 7d4ed72..08224c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ matrix: addons: {apt: {packages: [cabal-install-3.0,ghc-8.4.4], sources: [hvr-ghc]}} - env: CABALVER=3.0 GHCVER=8.6.5 addons: {apt: {packages: [cabal-install-3.0,ghc-8.6.5], sources: [hvr-ghc]}} - - env: CABALVER=3.0 GHCVER=8.8.1 UPDATE_GH_PAGES=yes + - env: CABALVER=3.0 GHCVER=8.8.1 addons: {apt: {packages: [cabal-install-3.0,ghc-8.8.1], sources: [hvr-ghc]}} - env: CABALVER=head GHCVER=head addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}} @@ -40,16 +40,16 @@ install: - cabal install --installdir=$HOME/.cabal/bin doctest script: - - cabal build --enable-tests - - cabal test - - ./run-doctests.sh - - cabal check - - cabal sdist - - cabal haddock --haddock-hyperlink-source --haddock-html-location=https://hackage.haskell.org/package/\$pkg-\$version/docs/ - - cabal install --lib - -after_script: - - ./update-gh-pages.sh + - cabal build --enable-tests all + - cabal test all + - ./hpath/run-doctests.sh + - ./hpath-filepath/run-doctests.sh + - (cd hpath && cabal check) + - (cd hpath-filepath && cabal check) + - (cd hpath-io && cabal check) + - cabal sdist all + - cabal haddock --haddock-hyperlink-source --haddock-html-location=https://hackage.haskell.org/package/\$pkg-\$version/docs/ all + - cabal install --lib all notifications: email: diff --git a/README.md b/README.md index 26e6cb3..b44b8e0 100644 --- a/README.md +++ b/README.md @@ -1,87 +1,17 @@ -# HPath +# HPath libraries -[![Gitter chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hasufell/hpath?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Hackage version](https://img.shields.io/hackage/v/hpath.svg?label=Hackage)](https://hackage.haskell.org/package/hpath) [![Build Status](https://api.travis-ci.org/hasufell/hpath.png?branch=master)](http://travis-ci.org/hasufell/hpath) [![Hackage-Deps](https://img.shields.io/hackage-deps/v/hpath.svg)](http://packdeps.haskellers.com/feed?needle=hpath) +[![Gitter chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hasufell/hpath?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Support for well-typed paths in Haskell. Also provides ByteString based filepath -manipulation. +Set of libraries to deal with filepaths and files. ## Motivation -The motivation came during development of -[hsfm](https://github.com/hasufell/hsfm) -which has a pretty strict File type, but lacks a strict Path type, e.g. -for user input. +* filepaths should be type-safe (absolute, relative, ...) +* filepaths should be ByteString under the hood, see [Abstract FilePath Proposal (AFPP)](https://gitlab.haskell.org/ghc/ghc/wikis/proposal/abstract-file-path) +* file high-level operations should be platform-specific, exception-stable, safe and as atomic as possible -The library that came closest to my needs was -[path](https://github.com/chrisdone/path), -but the API turned out to be oddly complicated for my use case, so I -decided to fork it. - -Similarly, [posix-paths](https://github.com/JohnLato/posix-paths) -was exactly what I wanted for the low-level operations, but upstream seems dead, -so it is forked as well and merged into this library. - -## Goals - -* well-typed paths -* high-level API to file operations like recursive directory copy -* safe filepath manipulation, never using String as filepath, but ByteString -* still allowing sufficient control to interact with the underlying low-level calls - -Note: this library was written for __posix__ systems and it will probably not support other systems. - -## Differences to 'path' - -* doesn't attempt to fake IO-related information into the path, so whether a path points to a file or directory is up to your IO-code to decide... -* trailing path separators will be preserved if they exist, no messing with that -* uses safe ByteString for filepaths under the hood instead of unsafe String -* fixes broken [dirname](https://github.com/chrisdone/path/issues/18) -* renames dirname/filename to basename/dirname to match the POSIX shell functions -* introduces a new `Path Fn` for safe filename guarantees and a `RelC` class -* allows pattern matching via unidirectional PatternSynonym -* uses simple doctest for testing -* allows `~/` as relative path, because on posix level `~` is just a regular filename that does _NOT_ point to `$HOME` -* remove TH, it sucks - -## Differences to 'posix-paths' - -* uses the `word8` package for save word8 literals instead of `OverloadedStrings` -* `hasTrailingPathSeparator` and `dropTrailingPathSeparator` behave in the same way as their `System.FilePath` counterpart -* added various functions: - * `equalFilePath` - * `getSearchPath` - * `hasParentDir` - * `hiddenFile` - * `isFileName` - * `isValid` - * `makeRelative` - * `makeValid` - * `normalise` - * `splitSearchPath` - * `stripExtension` -* has a custom versions of `openFd` which allows more control over the flags than its unix package counterpart -* adds a `getDirectoryContents'` version that works on Fd - -## Examples in ghci - -Start ghci via `cabal repl`: - -```hs --- enable OverloadedStrings -:set -XOverloadedStrings --- import HPath.IO -import HPath.IO --- parse an absolute path -abspath <- parseAbs "/home" --- parse a relative path (e.g. user users home directory) -relpath <- parseRel "jule" --- concatenate paths -let newpath = abspath relpath --- get file type -getFileType newpath --- return all contents of that directory -getDirsFiles newpath --- return all contents of the parent directory -getDirsFiles (dirname newpath) -``` +## Projects +* [hpath](./hpath): Support for well-typed paths +* [hpath-filepath](./hpath-filepath): ByteString based filepath manipulation (can be used without hpath) +* [hpath-io](./hpath-io): high-level file API (recursive copy, writeFile etc.) using hpath diff --git a/cabal.project b/cabal.project new file mode 100644 index 0000000..5659f42 --- /dev/null +++ b/cabal.project @@ -0,0 +1,4 @@ +packages: ./hpath + ./hpath-filepath + ./hpath-io + diff --git a/hpath-filepath/CHANGELOG.md b/hpath-filepath/CHANGELOG.md new file mode 100644 index 0000000..8c5da86 --- /dev/null +++ b/hpath-filepath/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for hpath-filepath + +## 0.9.3 -- 2020-01-04 + +* First version. Released on an unsuspecting world. diff --git a/hpath-filepath/LICENSE b/hpath-filepath/LICENSE new file mode 100644 index 0000000..7ecfe24 --- /dev/null +++ b/hpath-filepath/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2020, Julian Ospald + +All rights reserved. + +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 of Julian Ospald nor the names of other + 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 AND CONTRIBUTORS +"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 +OWNER OR CONTRIBUTORS 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. diff --git a/hpath-filepath/README.md b/hpath-filepath/README.md new file mode 100644 index 0000000..8b5cfb1 --- /dev/null +++ b/hpath-filepath/README.md @@ -0,0 +1,23 @@ +# HPath-filepath + +[![Gitter chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hasufell/hpath?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Hackage version](https://img.shields.io/hackage/v/hpath-filepath.svg?label=Hackage)](https://hackage.haskell.org/package/hpath-filepath) [![Build Status](https://api.travis-ci.org/hasufell/hpath.png?branch=master)](http://travis-ci.org/hasufell/hpath) [![Hackage-Deps](https://img.shields.io/hackage-deps/v/hpath-filepath.svg)](http://packdeps.haskellers.com/feed?needle=hpath-filepath) + +Support for bytestring based filepath manipulation, similar to 'filepath'. + +## Motivation + +This is basically a fork of [posix-paths](https://github.com/JohnLato/posix-paths), which seemed to have stalled development. + +There is also a similar library [filepath-bytestring](https://hackage.haskell.org/package/filepath-bytestring), but it doesn't follow an open development model and is cross-platform, which this library is not interested in. + +## Differences to 'posix-paths' + +* uses the `word8` package for save word8 literals instead of `OverloadedStrings` +* `hasTrailingPathSeparator` and `dropTrailingPathSeparator` behave in the same way as their `System.FilePath` counterpart +* has some additional functions + +## Differences to 'filepath-bytestring' + +* uses the `word8` package for save word8 literals instead of `OverloadedStrings` +* is not cross-platform (less odd code to maintain) +* has some additional functions diff --git a/Setup.hs b/hpath-filepath/Setup.hs similarity index 100% rename from Setup.hs rename to hpath-filepath/Setup.hs diff --git a/hpath-filepath/hpath-filepath.cabal b/hpath-filepath/hpath-filepath.cabal new file mode 100644 index 0000000..f25ad30 --- /dev/null +++ b/hpath-filepath/hpath-filepath.cabal @@ -0,0 +1,39 @@ +name: hpath-filepath +version: 0.9.3 +synopsis: ByteString based filepath manipulation +description: ByteString based filepath manipulation, similar to 'filepath' package. This is POSIX only. +-- bug-reports: +license: BSD3 +license-file: LICENSE +author: Julian Ospald +maintainer: Julian Ospald +copyright: Julian Ospald 2016 +category: Filesystem +build-type: Simple +cabal-version: 1.14 +tested-with: GHC==7.10.3 + , GHC==8.0.2 + , GHC==8.2.2 + , GHC==8.4.4 + , GHC==8.6.5 + , GHC==8.8.1 +extra-source-files: README.md + CHANGELOG.md + +library + if os(windows) + build-depends: unbuildable<0 + buildable: False + exposed-modules: System.Posix.FilePath + -- other-modules: + -- other-extensions: + build-depends: base >=4.8 && <5 + , bytestring >= 0.10.0.0 + , unix >= 2.5 + , word8 + hs-source-dirs: src + default-language: Haskell2010 + +source-repository head + type: git + location: https://github.com/hasufell/hpath diff --git a/run-doctests.sh b/hpath-filepath/run-doctests.sh similarity index 70% rename from run-doctests.sh rename to hpath-filepath/run-doctests.sh index b0a1332..305574c 100755 --- a/run-doctests.sh +++ b/hpath-filepath/run-doctests.sh @@ -18,5 +18,4 @@ fi set -x -cabal exec doctest -- -isrc -XOverloadedStrings System.Posix.FilePath -cabal exec doctest -- -isrc -XOverloadedStrings HPath +cabal exec doctest -- -ihpath-filepath/src -XOverloadedStrings System.Posix.FilePath diff --git a/src/System/Posix/FilePath.hs b/hpath-filepath/src/System/Posix/FilePath.hs similarity index 100% rename from src/System/Posix/FilePath.hs rename to hpath-filepath/src/System/Posix/FilePath.hs diff --git a/hpath-io/CHANGELOG.md b/hpath-io/CHANGELOG.md new file mode 100644 index 0000000..35b59e9 --- /dev/null +++ b/hpath-io/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for hpath-io + +## 0.9.3 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/hpath-io/LICENSE b/hpath-io/LICENSE new file mode 100644 index 0000000..7ecfe24 --- /dev/null +++ b/hpath-io/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2020, Julian Ospald + +All rights reserved. + +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 of Julian Ospald nor the names of other + 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 AND CONTRIBUTORS +"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 +OWNER OR CONTRIBUTORS 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. diff --git a/hpath-io/README.md b/hpath-io/README.md new file mode 100644 index 0000000..95166d4 --- /dev/null +++ b/hpath-io/README.md @@ -0,0 +1,26 @@ +# HPath-IO + +[![Gitter chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hasufell/hpath?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Hackage version](https://img.shields.io/hackage/v/hpath-io.svg?label=Hackage)](https://hackage.haskell.org/package/hpath-io) [![Build Status](https://api.travis-ci.org/hasufell/hpath.png?branch=master)](http://travis-ci.org/hasufell/hpath) [![Hackage-Deps](https://img.shields.io/hackage-deps/v/hpath-io.svg)](http://packdeps.haskellers.com/feed?needle=hpath-io) + +High-level IO operations on files/directories, utilizing type-safe Paths. + +## Motivation + +The motivation came during development of +[hsfm](https://github.com/hasufell/hsfm) +in order to have a proper high-level API of file related operations, +while utilizing type-safe Paths. + +## Goals + +* high-level API to file operations like recursive directory copy +* still allowing sufficient control to interact with the underlying low-level calls +* unit-testing exceptions (because yes, people may rely on them) + +Note: this library was written for __posix__ systems and it will probably not support other systems. + +## Differences to 'posix-paths' + +* has a custom versions of `openFd` which allows more control over the flags than its unix package counterpart +* adds a `getDirectoryContents'` version that works on Fd + diff --git a/hpath-io/Setup.hs b/hpath-io/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/hpath-io/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/cbits/dirutils.c b/hpath-io/cbits/dirutils.c similarity index 100% rename from cbits/dirutils.c rename to hpath-io/cbits/dirutils.c diff --git a/cbits/dirutils.h b/hpath-io/cbits/dirutils.h similarity index 100% rename from cbits/dirutils.h rename to hpath-io/cbits/dirutils.h diff --git a/hpath.cabal b/hpath-io/hpath-io.cabal similarity index 81% rename from hpath.cabal rename to hpath-io/hpath-io.cabal index f473dc1..f2b86fe 100644 --- a/hpath.cabal +++ b/hpath-io/hpath-io.cabal @@ -1,7 +1,8 @@ -name: hpath -version: 0.9.2 -synopsis: Support for well-typed paths -description: Support for well-typed paths, utilizing ByteString under the hood. +name: hpath-io +version: 0.9.3 +synopsis: High-level IO operations on files/directories +description: High-level IO operations on files/directories, utilizing type-safe Paths +-- bug-reports: license: BSD3 license-file: LICENSE author: Julian Ospald @@ -17,40 +18,33 @@ tested-with: GHC==7.10.3 , GHC==8.6.5 , GHC==8.8.1 extra-source-files: README.md - CHANGELOG + CHANGELOG.md cbits/dirutils.h library if os(windows) build-depends: unbuildable<0 buildable: False - hs-source-dirs: src/ - default-language: Haskell2010 - if impl(ghc >= 8.0) - ghc-options: -Wall -Wno-redundant-constraints - else - ghc-options: -Wall - c-sources: cbits/dirutils.c - exposed-modules: HPath, - HPath.IO, + exposed-modules: HPath.IO, HPath.IO.Errors, System.Posix.Directory.Foreign, System.Posix.Directory.Traversals, - System.Posix.FD, - System.Posix.FilePath - other-modules: HPath.Internal + System.Posix.FD + c-sources: cbits/dirutils.c + + -- other-modules: + -- other-extensions: build-depends: base >= 4.8 && <5 , IfElse , bytestring >= 0.10.0.0 - , deepseq - , exceptions - , hspec + , hpath + , hpath-filepath , streamly >= 0.7 , unix >= 2.5 , unix-bytestring , utf8-string - , word8 - + hs-source-dirs: src + default-language: Haskell2010 test-suite spec if os(windows) @@ -94,6 +88,7 @@ test-suite spec , IfElse , bytestring >= 0.10.0.0 , hpath + , hpath-io , hspec >= 1.3 , process , unix @@ -103,4 +98,3 @@ test-suite spec source-repository head type: git location: https://github.com/hasufell/hpath - diff --git a/src/HPath/IO.hs b/hpath-io/src/HPath/IO.hs similarity index 100% rename from src/HPath/IO.hs rename to hpath-io/src/HPath/IO.hs diff --git a/src/HPath/IO.hs-boot b/hpath-io/src/HPath/IO.hs-boot similarity index 100% rename from src/HPath/IO.hs-boot rename to hpath-io/src/HPath/IO.hs-boot diff --git a/src/HPath/IO/Errors.hs b/hpath-io/src/HPath/IO/Errors.hs similarity index 97% rename from src/HPath/IO/Errors.hs rename to hpath-io/src/HPath/IO/Errors.hs index 3e87c1c..f6ef440 100644 --- a/src/HPath/IO/Errors.hs +++ b/hpath-io/src/HPath/IO/Errors.hs @@ -149,9 +149,9 @@ toConstr RecursiveFailure {} = "RecursiveFailure" isSameFile, isDestinationInSource, isRecursiveFailure :: HPathIOException -> Bool -isSameFile ex = toConstr (ex :: HPathIOException) == toConstr SameFile{} -isDestinationInSource ex = toConstr (ex :: HPathIOException) == toConstr DestinationInSource{} -isRecursiveFailure ex = toConstr (ex :: HPathIOException) == toConstr RecursiveFailure{} +isSameFile ex = toConstr (ex :: HPathIOException) == toConstr (SameFile mempty mempty) +isDestinationInSource ex = toConstr (ex :: HPathIOException) == (toConstr $ DestinationInSource mempty mempty) +isRecursiveFailure ex = toConstr (ex :: HPathIOException) == (toConstr $ RecursiveFailure mempty) isReadContentsFailed, isCreateDirFailed, isCopyFileFailed, isRecreateSymlinkFailed ::RecursiveFailureHint -> Bool diff --git a/src/System/Posix/Directory/Foreign.hsc b/hpath-io/src/System/Posix/Directory/Foreign.hsc similarity index 100% rename from src/System/Posix/Directory/Foreign.hsc rename to hpath-io/src/System/Posix/Directory/Foreign.hsc diff --git a/src/System/Posix/Directory/Traversals.hs b/hpath-io/src/System/Posix/Directory/Traversals.hs similarity index 100% rename from src/System/Posix/Directory/Traversals.hs rename to hpath-io/src/System/Posix/Directory/Traversals.hs diff --git a/src/System/Posix/FD.hs b/hpath-io/src/System/Posix/FD.hs similarity index 100% rename from src/System/Posix/FD.hs rename to hpath-io/src/System/Posix/FD.hs diff --git a/test/HPath/IO/AppendFileSpec.hs b/hpath-io/test/HPath/IO/AppendFileSpec.hs similarity index 99% rename from test/HPath/IO/AppendFileSpec.hs rename to hpath-io/test/HPath/IO/AppendFileSpec.hs index c1c5b79..40bf4f5 100644 --- a/test/HPath/IO/AppendFileSpec.hs +++ b/hpath-io/test/HPath/IO/AppendFileSpec.hs @@ -13,7 +13,6 @@ import GHC.IO.Exception ( IOErrorType(..) ) -import System.Process import Utils diff --git a/test/HPath/IO/CanonicalizePathSpec.hs b/hpath-io/test/HPath/IO/CanonicalizePathSpec.hs similarity index 100% rename from test/HPath/IO/CanonicalizePathSpec.hs rename to hpath-io/test/HPath/IO/CanonicalizePathSpec.hs diff --git a/test/HPath/IO/CopyDirRecursiveCollectFailuresSpec.hs b/hpath-io/test/HPath/IO/CopyDirRecursiveCollectFailuresSpec.hs similarity index 98% rename from test/HPath/IO/CopyDirRecursiveCollectFailuresSpec.hs rename to hpath-io/test/HPath/IO/CopyDirRecursiveCollectFailuresSpec.hs index 4c34da3..2f8b784 100644 --- a/test/HPath/IO/CopyDirRecursiveCollectFailuresSpec.hs +++ b/hpath-io/test/HPath/IO/CopyDirRecursiveCollectFailuresSpec.hs @@ -127,7 +127,8 @@ spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ CollectFailures (system $ "diff -r --no-dereference " ++ toString tmpDir' ++ "inputDir" ++ " " - ++ toString tmpDir' ++ "outputDir") + ++ toString tmpDir' ++ "outputDir" + ++ " >/dev/null") `shouldReturn` ExitSuccess removeDirIfExists "outputDir" diff --git a/test/HPath/IO/CopyDirRecursiveOverwriteSpec.hs b/hpath-io/test/HPath/IO/CopyDirRecursiveOverwriteSpec.hs similarity index 96% rename from test/HPath/IO/CopyDirRecursiveOverwriteSpec.hs rename to hpath-io/test/HPath/IO/CopyDirRecursiveOverwriteSpec.hs index ccef46e..d64a5ef 100644 --- a/test/HPath/IO/CopyDirRecursiveOverwriteSpec.hs +++ b/hpath-io/test/HPath/IO/CopyDirRecursiveOverwriteSpec.hs @@ -106,7 +106,8 @@ spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ FailEarly (system $ "diff -r --no-dereference " ++ toString tmpDir' ++ "inputDir" ++ " " - ++ toString tmpDir' ++ "outputDir") + ++ toString tmpDir' ++ "outputDir" + ++ " >/dev/null") `shouldReturn` ExitSuccess removeDirIfExists "outputDir" @@ -114,7 +115,8 @@ spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ tmpDir' <- getRawTmpDir (system $ "diff -r --no-dereference " ++ toString tmpDir' ++ "inputDir" ++ " " - ++ toString tmpDir' ++ "alreadyExistsD") + ++ toString tmpDir' ++ "alreadyExistsD" + ++ " >/dev/null") `shouldReturn` (ExitFailure 1) copyDirRecursive' "inputDir" "alreadyExistsD" @@ -122,7 +124,8 @@ spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ FailEarly (system $ "diff -r --no-dereference " ++ toString tmpDir' ++ "inputDir" ++ " " - ++ toString tmpDir' ++ "alreadyExistsD") + ++ toString tmpDir' ++ "alreadyExistsD" + ++ " >/dev/null") `shouldReturn` ExitSuccess removeDirIfExists "outputDir" diff --git a/test/HPath/IO/CopyDirRecursiveSpec.hs b/hpath-io/test/HPath/IO/CopyDirRecursiveSpec.hs similarity index 98% rename from test/HPath/IO/CopyDirRecursiveSpec.hs rename to hpath-io/test/HPath/IO/CopyDirRecursiveSpec.hs index 66eede9..c614a15 100644 --- a/test/HPath/IO/CopyDirRecursiveSpec.hs +++ b/hpath-io/test/HPath/IO/CopyDirRecursiveSpec.hs @@ -91,7 +91,8 @@ spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ FailEarly (system $ "diff -r --no-dereference " ++ toString tmpDir' ++ "inputDir" ++ " " - ++ toString tmpDir' ++ "outputDir") + ++ toString tmpDir' ++ "outputDir" + ++ " >/dev/null") `shouldReturn` ExitSuccess removeDirIfExists "outputDir" diff --git a/test/HPath/IO/CopyFileOverwriteSpec.hs b/hpath-io/test/HPath/IO/CopyFileOverwriteSpec.hs similarity index 100% rename from test/HPath/IO/CopyFileOverwriteSpec.hs rename to hpath-io/test/HPath/IO/CopyFileOverwriteSpec.hs diff --git a/test/HPath/IO/CopyFileSpec.hs b/hpath-io/test/HPath/IO/CopyFileSpec.hs similarity index 100% rename from test/HPath/IO/CopyFileSpec.hs rename to hpath-io/test/HPath/IO/CopyFileSpec.hs diff --git a/test/HPath/IO/CreateDirRecursiveSpec.hs b/hpath-io/test/HPath/IO/CreateDirRecursiveSpec.hs similarity index 100% rename from test/HPath/IO/CreateDirRecursiveSpec.hs rename to hpath-io/test/HPath/IO/CreateDirRecursiveSpec.hs diff --git a/test/HPath/IO/CreateDirSpec.hs b/hpath-io/test/HPath/IO/CreateDirSpec.hs similarity index 100% rename from test/HPath/IO/CreateDirSpec.hs rename to hpath-io/test/HPath/IO/CreateDirSpec.hs diff --git a/test/HPath/IO/CreateRegularFileSpec.hs b/hpath-io/test/HPath/IO/CreateRegularFileSpec.hs similarity index 100% rename from test/HPath/IO/CreateRegularFileSpec.hs rename to hpath-io/test/HPath/IO/CreateRegularFileSpec.hs diff --git a/test/HPath/IO/CreateSymlinkSpec.hs b/hpath-io/test/HPath/IO/CreateSymlinkSpec.hs similarity index 100% rename from test/HPath/IO/CreateSymlinkSpec.hs rename to hpath-io/test/HPath/IO/CreateSymlinkSpec.hs diff --git a/test/HPath/IO/DeleteDirRecursiveSpec.hs b/hpath-io/test/HPath/IO/DeleteDirRecursiveSpec.hs similarity index 100% rename from test/HPath/IO/DeleteDirRecursiveSpec.hs rename to hpath-io/test/HPath/IO/DeleteDirRecursiveSpec.hs diff --git a/test/HPath/IO/DeleteDirSpec.hs b/hpath-io/test/HPath/IO/DeleteDirSpec.hs similarity index 100% rename from test/HPath/IO/DeleteDirSpec.hs rename to hpath-io/test/HPath/IO/DeleteDirSpec.hs diff --git a/test/HPath/IO/DeleteFileSpec.hs b/hpath-io/test/HPath/IO/DeleteFileSpec.hs similarity index 100% rename from test/HPath/IO/DeleteFileSpec.hs rename to hpath-io/test/HPath/IO/DeleteFileSpec.hs diff --git a/test/HPath/IO/GetDirsFilesSpec.hs b/hpath-io/test/HPath/IO/GetDirsFilesSpec.hs similarity index 100% rename from test/HPath/IO/GetDirsFilesSpec.hs rename to hpath-io/test/HPath/IO/GetDirsFilesSpec.hs diff --git a/test/HPath/IO/GetFileTypeSpec.hs b/hpath-io/test/HPath/IO/GetFileTypeSpec.hs similarity index 100% rename from test/HPath/IO/GetFileTypeSpec.hs rename to hpath-io/test/HPath/IO/GetFileTypeSpec.hs diff --git a/test/HPath/IO/MoveFileOverwriteSpec.hs b/hpath-io/test/HPath/IO/MoveFileOverwriteSpec.hs similarity index 100% rename from test/HPath/IO/MoveFileOverwriteSpec.hs rename to hpath-io/test/HPath/IO/MoveFileOverwriteSpec.hs diff --git a/test/HPath/IO/MoveFileSpec.hs b/hpath-io/test/HPath/IO/MoveFileSpec.hs similarity index 100% rename from test/HPath/IO/MoveFileSpec.hs rename to hpath-io/test/HPath/IO/MoveFileSpec.hs diff --git a/test/HPath/IO/ReadFileEOFSpec.hs b/hpath-io/test/HPath/IO/ReadFileEOFSpec.hs similarity index 99% rename from test/HPath/IO/ReadFileEOFSpec.hs rename to hpath-io/test/HPath/IO/ReadFileEOFSpec.hs index cb519f5..6a92b52 100644 --- a/test/HPath/IO/ReadFileEOFSpec.hs +++ b/hpath-io/test/HPath/IO/ReadFileEOFSpec.hs @@ -13,7 +13,6 @@ import GHC.IO.Exception ( IOErrorType(..) ) -import System.Process import Utils diff --git a/test/HPath/IO/ReadFileSpec.hs b/hpath-io/test/HPath/IO/ReadFileSpec.hs similarity index 99% rename from test/HPath/IO/ReadFileSpec.hs rename to hpath-io/test/HPath/IO/ReadFileSpec.hs index b844c30..61ec566 100644 --- a/test/HPath/IO/ReadFileSpec.hs +++ b/hpath-io/test/HPath/IO/ReadFileSpec.hs @@ -13,7 +13,6 @@ import GHC.IO.Exception ( IOErrorType(..) ) -import System.Process import Utils diff --git a/test/HPath/IO/RecreateSymlinkOverwriteSpec.hs b/hpath-io/test/HPath/IO/RecreateSymlinkOverwriteSpec.hs similarity index 100% rename from test/HPath/IO/RecreateSymlinkOverwriteSpec.hs rename to hpath-io/test/HPath/IO/RecreateSymlinkOverwriteSpec.hs diff --git a/test/HPath/IO/RecreateSymlinkSpec.hs b/hpath-io/test/HPath/IO/RecreateSymlinkSpec.hs similarity index 100% rename from test/HPath/IO/RecreateSymlinkSpec.hs rename to hpath-io/test/HPath/IO/RecreateSymlinkSpec.hs diff --git a/test/HPath/IO/RenameFileSpec.hs b/hpath-io/test/HPath/IO/RenameFileSpec.hs similarity index 100% rename from test/HPath/IO/RenameFileSpec.hs rename to hpath-io/test/HPath/IO/RenameFileSpec.hs diff --git a/test/HPath/IO/ToAbsSpec.hs b/hpath-io/test/HPath/IO/ToAbsSpec.hs similarity index 100% rename from test/HPath/IO/ToAbsSpec.hs rename to hpath-io/test/HPath/IO/ToAbsSpec.hs diff --git a/test/HPath/IO/WriteFileSpec.hs b/hpath-io/test/HPath/IO/WriteFileSpec.hs similarity index 99% rename from test/HPath/IO/WriteFileSpec.hs rename to hpath-io/test/HPath/IO/WriteFileSpec.hs index 0bbbbdb..3718e0e 100644 --- a/test/HPath/IO/WriteFileSpec.hs +++ b/hpath-io/test/HPath/IO/WriteFileSpec.hs @@ -13,7 +13,6 @@ import GHC.IO.Exception ( IOErrorType(..) ) -import System.Process import Utils diff --git a/test/Main.hs b/hpath-io/test/Main.hs similarity index 55% rename from test/Main.hs rename to hpath-io/test/Main.hs index 360bc4d..f3d1d7b 100644 --- a/test/Main.hs +++ b/hpath-io/test/Main.hs @@ -1,19 +1,24 @@ {-# LANGUAGE OverloadedStrings #-} +import qualified Data.ByteString as BS +import Data.IORef import Test.Hspec import Test.Hspec.Runner import Test.Hspec.Formatters import qualified Spec import Utils +import System.Posix.Temp.ByteString (mkdtemp) -- TODO: chardev, blockdev, namedpipe, socket main :: IO () -main = +main = do + tmpBase <- mkdtemp "/tmp/" + writeIORef baseTmpDir (Just (tmpBase `BS.append` "/")) + putStrLn $ ("Temporary test directory at: " <> show tmpBase) hspecWith defaultConfig { configFormatter = Just progress } - $ beforeAll_ createBaseTmpDir $ afterAll_ deleteBaseTmpDir $ Spec.spec diff --git a/test/Spec.hs b/hpath-io/test/Spec.hs similarity index 100% rename from test/Spec.hs rename to hpath-io/test/Spec.hs diff --git a/test/Utils.hs b/hpath-io/test/Utils.hs similarity index 81% rename from test/Utils.hs rename to hpath-io/test/Utils.hs index 63845b7..c069cde 100644 --- a/test/Utils.hs +++ b/hpath-io/test/Utils.hs @@ -39,10 +39,6 @@ import System.IO.Unsafe unsafePerformIO ) import qualified System.Posix.Directory.Traversals as DT -import System.Posix.Env.ByteString - ( - getEnv - ) import Data.ByteString ( ByteString @@ -61,18 +57,14 @@ import System.Posix.Files.ByteString , unionFileModes ) -import qualified "unix" System.Posix.IO.ByteString as SPI -import qualified "unix-bytestring" System.Posix.IO.ByteString as SPB - - +baseTmpDir :: IORef (Maybe ByteString) +{-# NOINLINE baseTmpDir #-} +baseTmpDir = unsafePerformIO (newIORef Nothing) -baseTmpDir :: ByteString -baseTmpDir = "test/HPath/IO/tmp/" - -tmpDir :: IORef ByteString +tmpDir :: IORef (Maybe ByteString) {-# NOINLINE tmpDir #-} -tmpDir = unsafePerformIO (newIORef baseTmpDir) +tmpDir = unsafePerformIO (newIORef Nothing) @@ -83,49 +75,39 @@ tmpDir = unsafePerformIO (newIORef baseTmpDir) setTmpDir :: ByteString -> IO () {-# NOINLINE setTmpDir #-} -setTmpDir bs = writeIORef tmpDir (baseTmpDir `BS.append` bs) +setTmpDir bs = do + tmp <- fromJust <$> readIORef baseTmpDir + writeIORef tmpDir (Just (tmp `BS.append` bs)) createTmpDir :: IO () {-# NOINLINE createTmpDir #-} createTmpDir = do - pwd <- fromJust <$> getEnv "PWD" >>= P.parseAbs - tmp <- P.parseRel =<< readIORef tmpDir - void $ createDir newDirPerms (pwd P. tmp) + tmp <- P.parseAbs =<< (fromJust <$> readIORef tmpDir) + void $ createDir newDirPerms tmp deleteTmpDir :: IO () {-# NOINLINE deleteTmpDir #-} deleteTmpDir = do - pwd <- fromJust <$> getEnv "PWD" >>= P.parseAbs - tmp <- P.parseRel =<< readIORef tmpDir - void $ deleteDir (pwd P. tmp) - - -createBaseTmpDir :: IO () -{-# NOINLINE createBaseTmpDir #-} -createBaseTmpDir = do - pwd <- fromJust <$> getEnv "PWD" >>= P.parseAbs - tmp <- P.parseRel baseTmpDir - void $ createDir newDirPerms (pwd P. tmp) + tmp <- P.parseAbs =<< (fromJust <$> readIORef tmpDir) + void $ deleteDir tmp deleteBaseTmpDir :: IO () {-# NOINLINE deleteBaseTmpDir #-} deleteBaseTmpDir = do - pwd <- fromJust <$> getEnv "PWD" >>= P.parseAbs - tmp <- P.parseRel baseTmpDir - contents <- getDirsFiles (pwd P. tmp) + tmp <- (fromJust <$> readIORef baseTmpDir) >>= P.parseAbs + contents <- getDirsFiles tmp forM_ contents deleteDir - void $ deleteDir (pwd P. tmp) + void $ deleteDir tmp withRawTmpDir :: (P.Path P.Abs -> IO a) -> IO a {-# NOINLINE withRawTmpDir #-} withRawTmpDir f = do - pwd <- fromJust <$> getEnv "PWD" >>= P.parseAbs - tmp <- P.parseRel =<< readIORef tmpDir - f (pwd P. tmp) + tmp <- P.parseAbs =<< (fromJust <$> readIORef tmpDir) + f tmp getRawTmpDir :: IO ByteString @@ -136,9 +118,8 @@ getRawTmpDir = withRawTmpDir (return . flip BS.append "/" . P.fromAbs) withTmpDir :: ByteString -> (P.Path P.Abs -> IO a) -> IO a {-# NOINLINE withTmpDir #-} withTmpDir ip f = do - pwd <- fromJust <$> getEnv "PWD" >>= P.parseAbs - tmp <- P.parseRel =<< readIORef tmpDir - p <- (pwd P. tmp P.) <$> P.parseRel ip + tmp <- P.parseAbs =<< (fromJust <$> readIORef tmpDir) + p <- (tmp P.) <$> P.parseRel ip f p @@ -148,10 +129,9 @@ withTmpDir' :: ByteString -> IO a {-# NOINLINE withTmpDir' #-} withTmpDir' ip1 ip2 f = do - pwd <- fromJust <$> getEnv "PWD" >>= P.parseAbs - tmp <- P.parseRel =<< readIORef tmpDir - p1 <- (pwd P. tmp P.) <$> P.parseRel ip1 - p2 <- (pwd P. tmp P.) <$> P.parseRel ip2 + tmp <- P.parseAbs =<< (fromJust <$> readIORef tmpDir) + p1 <- (tmp P.) <$> P.parseRel ip1 + p2 <- (tmp P.) <$> P.parseRel ip2 f p1 p2 diff --git a/CHANGELOG b/hpath/CHANGELOG similarity index 100% rename from CHANGELOG rename to hpath/CHANGELOG diff --git a/LICENSE b/hpath/LICENSE similarity index 100% rename from LICENSE rename to hpath/LICENSE diff --git a/hpath/README.md b/hpath/README.md new file mode 100644 index 0000000..1dd180b --- /dev/null +++ b/hpath/README.md @@ -0,0 +1,37 @@ +# HPath + +[![Gitter chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hasufell/hpath?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Hackage version](https://img.shields.io/hackage/v/hpath.svg?label=Hackage)](https://hackage.haskell.org/package/hpath) [![Build Status](https://api.travis-ci.org/hasufell/hpath.png?branch=master)](http://travis-ci.org/hasufell/hpath) [![Hackage-Deps](https://img.shields.io/hackage-deps/v/hpath.svg)](http://packdeps.haskellers.com/feed?needle=hpath) + +Support for well-typed paths in Haskell. + +## Motivation + +The motivation came during development of +[hsfm](https://github.com/hasufell/hsfm) +which has a pretty strict File type, but lacks a strict Path type, e.g. +for user input. + +The library that came closest to my needs was +[path](https://github.com/chrisdone/path), +but the API turned out to be oddly complicated for my use case, so I +decided to fork it. + +## Goals + +* well-typed paths +* safe filepath manipulation, never using String as filepath, but ByteString + +Note: this library was written for __posix__ systems and it will probably not support other systems. + +## Differences to 'path' + +* doesn't attempt to fake IO-related information into the path, so whether a path points to a file or directory is up to your IO-code to decide... +* trailing path separators will be preserved if they exist, no messing with that +* uses safe ByteString for filepaths under the hood instead of unsafe String +* fixes broken [dirname](https://github.com/chrisdone/path/issues/18) +* renames dirname/filename to basename/dirname to match the POSIX shell functions +* introduces a new `Path Fn` for safe filename guarantees and a `RelC` class +* allows pattern matching via unidirectional PatternSynonym +* uses simple doctest for testing +* allows `~/` as relative path, because on posix level `~` is just a regular filename that does _NOT_ point to `$HOME` +* remove TH, it sucks diff --git a/hpath/Setup.hs b/hpath/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/hpath/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/hpath/hpath.cabal b/hpath/hpath.cabal new file mode 100644 index 0000000..c0a928b --- /dev/null +++ b/hpath/hpath.cabal @@ -0,0 +1,44 @@ +name: hpath +version: 0.9.2 +synopsis: Support for well-typed paths +description: Support for well-typed paths, utilizing ByteString under the hood. +license: BSD3 +license-file: LICENSE +author: Julian Ospald +maintainer: Julian Ospald +copyright: Julian Ospald 2016 +category: Filesystem +build-type: Simple +cabal-version: 1.14 +tested-with: GHC==7.10.3 + , GHC==8.0.2 + , GHC==8.2.2 + , GHC==8.4.4 + , GHC==8.6.5 + , GHC==8.8.1 +extra-source-files: README.md + CHANGELOG + +library + if os(windows) + build-depends: unbuildable<0 + buildable: False + hs-source-dirs: src/ + default-language: Haskell2010 + if impl(ghc >= 8.0) + ghc-options: -Wall -Wno-redundant-constraints + else + ghc-options: -Wall + exposed-modules: HPath + HPath.Internal + build-depends: base >= 4.8 && <5 + , bytestring >= 0.10.0.0 + , deepseq + , exceptions + , hpath-filepath + , word8 + +source-repository head + type: git + location: https://github.com/hasufell/hpath + diff --git a/hpath/run-doctests.sh b/hpath/run-doctests.sh new file mode 100755 index 0000000..37d1638 --- /dev/null +++ b/hpath/run-doctests.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +set -e + +if [ -n "${SKIP_DOCTESTS}" ] ; then + echo "Skipping doctests" + exit 0 +fi + +if ! command -v doctest >/dev/null ; then + tempdir="$(mktemp -d)" + ( + cd "${tempdir}" + cabal install --installdir="${tempdir}" doctest + ) + export PATH="${tempdir}:$PATH" +fi + +set -x + +cabal exec doctest -- -ihpath/src -XOverloadedStrings HPath diff --git a/src/HPath.hs b/hpath/src/HPath.hs similarity index 100% rename from src/HPath.hs rename to hpath/src/HPath.hs diff --git a/src/HPath/Internal.hs b/hpath/src/HPath/Internal.hs similarity index 100% rename from src/HPath/Internal.hs rename to hpath/src/HPath/Internal.hs diff --git a/update-gh-pages.sh b/update-gh-pages.sh deleted file mode 100755 index d10a686..0000000 --- a/update-gh-pages.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -SOURCE_BRANCH="master" -TARGET_BRANCH="gh-pages" -REPO="https://${GITHUB_TOKEN}@github.com/hasufell/hpath" - -if [ -z "${UPDATE_GH_PAGES}" ] ; then - exit 0 -fi - - -# Pull requests and commits to other branches shouldn't try to deploy, -# just build to verify -if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then - echo "Skipping docs deploy." - exit 0 -fi - - -cd "$HOME" -git config --global user.email "travis@travis-ci.org" -git config --global user.name "travis-ci" -git clone --branch=${TARGET_BRANCH} ${REPO} ${TARGET_BRANCH} || exit 1 - -# docs -cd ${TARGET_BRANCH} || exit 1 -echo "Removing old docs." -rm -rf * -echo "Adding new docs." -cp -rf "${TRAVIS_BUILD_DIR}"/dist-newstyle/build/x86_64-linux/ghc-*/hpath-*/doc/html/hpath/* . || exit 1 - -# If there are no changes to the compiled out (e.g. this is a README update) -# then just bail. -if [ -z "`git diff --exit-code`" ]; then - echo "No changes to the output on this push; exiting." - exit 0 -fi - -git add -- . - -if [[ -e ./index.html ]] ; then - echo "Commiting docs." - git commit -m "Lastest docs updated - -travis build: $TRAVIS_BUILD_NUMBER -commit: $TRAVIS_COMMIT -auto-pushed to gh-pages" - - git push origin $TARGET_BRANCH - echo "Published docs to gh-pages." -else - echo "Error: docs are empty." - exit 1 -fi -