@@ -1,14 +0,0 @@ | |||
*.o | |||
*.hi | |||
*~ | |||
dist/ | |||
cabal-dev/ | |||
.hsenv | |||
TAGS | |||
tags | |||
*.tag | |||
.stack-work/ | |||
dist/ | |||
dist-newstyle/ | |||
.cabal-sandbox/ | |||
cabal.sandbox.config |
@@ -1,84 +0,0 @@ | |||
# See https://github.com/hvr/multi-ghc-travis for more information | |||
language: c | |||
sudo: required | |||
dist: trusty | |||
matrix: | |||
include: | |||
- env: CABALVER=3.0 GHCVER=7.10.3 SKIP_DOCTESTS=yes | |||
addons: {apt: {packages: [cabal-install-3.0,ghc-7.10.3], sources: [hvr-ghc]}} | |||
before_install: | |||
- sudo apt-get install -y hscolour | |||
- export PATH=~/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH | |||
- env: CABALVER=3.0 GHCVER=8.0.2 SKIP_DOCTESTS=yes | |||
addons: {apt: {packages: [cabal-install-3.0,ghc-8.0.2], sources: [hvr-ghc]}} | |||
before_install: | |||
- sudo apt-get install -y hscolour | |||
- export PATH=~/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH | |||
- env: CABALVER=3.0 GHCVER=8.2.2 | |||
addons: {apt: {packages: [cabal-install-3.0,ghc-8.2.2], sources: [hvr-ghc]}} | |||
before_install: | |||
- sudo apt-get install -y hscolour | |||
- export PATH=~/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH | |||
- env: CABALVER=3.0 GHCVER=8.4.4 | |||
addons: {apt: {packages: [cabal-install-3.0,ghc-8.4.4], sources: [hvr-ghc]}} | |||
before_install: | |||
- sudo apt-get install -y hscolour | |||
- export PATH=~/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH | |||
- env: CABALVER=3.0 GHCVER=8.6.5 | |||
addons: {apt: {packages: [cabal-install-3.0,ghc-8.6.5], sources: [hvr-ghc]}} | |||
before_install: | |||
- sudo apt-get install -y hscolour | |||
- export PATH=~/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH | |||
- env: CABALVER=3.0 GHCVER=8.8.3 | |||
addons: {apt: {packages: [cabal-install-3.0,ghc-8.8.3], sources: [hvr-ghc]}} | |||
before_install: | |||
- sudo apt-get install -y hscolour | |||
- export PATH=~/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH | |||
- env: CABALVER=head GHCVER=head | |||
addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}} | |||
before_install: | |||
- sudo apt-get install -y hscolour | |||
- export PATH=~/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH | |||
- os: osx | |||
osx_image: xcode11.3 | |||
language: generic | |||
before_install: | |||
- mkdir -p ~/.ghcup/bin | |||
- curl https://gitlab.haskell.org/haskell/ghcup/raw/master/ghcup > ~/.ghcup/bin/ghcup | |||
- chmod +x ~/.ghcup/bin/ghcup | |||
- export PATH=~/.cabal/bin:~/.ghcup/bin:$PATH | |||
- ghcup install 8.6.5 | |||
- ghcup set 8.6.5 | |||
- ghcup install-cabal 3.2.0.0 | |||
allow_failures: | |||
- env: CABALVER=head GHCVER=head | |||
env: | |||
global: | |||
- secure: HPBARvNM85ea2U0Ynq5MMe6BRlnuwqXWuSn20VY3EYCAT2njkVPYnR3O7+bGE6aq0KHAV87zz5iUfGJontd86tE0sDVjcSuRY0hqjOeJTkQq5M8WXJZOpVqlBTwDP1Q3x/fwoRa0dt9Z0tZZdKMlrf2XdcKPDdhcP1QYP4aV/jO4ZCfAQr7zVCvTae+Lp/KmwFYcBbFo/pj0duF1M4Oqx/D388b/W4jVE3lgd/TK7Ja1xWP6g+Oyvo6iQK8yJVYGdm6E+cVsNueiisnTJ/rRA53lsaC9dmWtZaFGl41wPviSU5zPq03vOuZMiyE2WtCHoo46ONXrXJ9N2soqdQVfEkr9Nw5LQl+6C5lCPEejZ575YUkuO05H3wvHMk3YY4zWXNFA9eZ47PEH8tpoUk9LPBacCKQFtp5lfRk63crba5CiFtcMyFq++0mLpNthNvtto7ffHMZrt6fvK9axI+r21VPftf/3FiFY4mnCp/Bln+ijklfZSN71VqiT20EWuqxQHw8aCpT00KA/PKGl9iJfoN4OO3XzNRTtmM+L9Im4bc1ni9YQ6N3UYg3z0nEnCLwFcTmTH/tDMHRremE0dM6B++YfcnyIhen8w+hG4bcXk7jbMUizRhUhStN7TZQuC9S4wE5whhp9c03rJZMmH5E2rlXY3lwVgeyWm1TuMp1RYWI= | |||
install: | |||
- cabal --version | |||
- travis_retry cabal update | |||
- cabal install --installdir=$HOME/.cabal/bin hspec-discover | |||
- cabal install --installdir=$HOME/.cabal/bin doctest | |||
script: | |||
- 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 install --lib all | |||
notifications: | |||
email: | |||
- hasufell@posteo.de | |||
@@ -1,19 +0,0 @@ | |||
# 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) [![Build Status](https://api.travis-ci.org/hasufell/hpath.png?branch=master)](http://travis-ci.org/hasufell/hpath) | |||
Set of libraries to deal with filepaths and files. | |||
## Motivation | |||
* 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 | |||
## Projects | |||
* [![Hackage version](https://img.shields.io/hackage/v/hpath.svg?label=Hackage)](https://hackage.haskell.org/package/hpath) [hpath](./hpath): Support for well-typed paths | |||
* [![Hackage version](https://img.shields.io/hackage/v/hpath-filepath.svg?label=Hackage)](https://hackage.haskell.org/package/hpath-filepath) [hpath-filepath](./hpath-filepath): ByteString based filepath manipulation (can be used without hpath) | |||
* [![Hackage version](https://img.shields.io/hackage/v/hpath-directory.svg?label=Hackage)](https://hackage.haskell.org/package/hpath-directory) [hpath-directory](./hpath-directory): High-level IO operations for files/directories on raw ByteString filepaths (use hpath-io for the type-safe path version) | |||
* [![Hackage version](https://img.shields.io/hackage/v/hpath-io.svg?label=Hackage)](https://hackage.haskell.org/package/hpath-io) [hpath-io](./hpath-io): High-level IO operations for files/directories utilizing type-safe Path | |||
* [![Hackage version](https://img.shields.io/hackage/v/hpath-posix.svg?label=Hackage)](https://hackage.haskell.org/package/hpath-posix) [hpath-posix](./hpath-posix): Some low-level POSIX glue code that is not in 'unix' |
@@ -0,0 +1,9 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>System.Posix.FD</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();setSynopsis("mini_System-Posix-FD.html");}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/System-Posix-FD.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Copyright</th><td>© 2016 Julian Ospald</td></tr><tr><th>License</th><td>BSD3</td></tr><tr><th>Maintainer</th><td>Julian Ospald <hasufell@posteo.de></td></tr><tr><th>Stability</th><td>experimental</td></tr><tr><th>Portability</th><td>portable</td></tr><tr><th>Safe Haskell</th><td>Safe</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">System.Posix.FD</p></div><div id="description"><p class="caption">Description</p><div class="doc"><p>Provides an alternative for <code><a href="https://hackage.haskell.org/package/unix-2.7.1.0/docs/System-Posix-IO-ByteString.html#v:openFd">openFd</a></code> | |||
which gives us more control on what status flags to pass to the | |||
low-level <code>open(2)</code> call, in contrast to the unix package.</p></div></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><a href="#v:openFd">openFd</a> :: <a href="https://hackage.haskell.org/package/unix-2.7.1.0/docs/System-Posix-ByteString-FilePath.html#t:RawFilePath">RawFilePath</a> -> <a href="https://hackage.haskell.org/package/unix-2.7.1.0/docs/System-Posix-IO-ByteString.html#t:OpenMode">OpenMode</a> -> [<a href="System-Posix-Directory-Foreign.html#t:Flags">Flags</a>] -> <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/Data-Maybe.html#t:Maybe">Maybe</a> <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/System-Posix-Types.html#t:FileMode">FileMode</a> -> <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/System-IO.html#t:IO">IO</a> <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/System-Posix-Types.html#t:Fd">Fd</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:openFd" class="def">openFd</a> <a href="src/System-Posix-FD.html#openFd" class="link">Source</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: <a href="https://hackage.haskell.org/package/unix-2.7.1.0/docs/System-Posix-ByteString-FilePath.html#t:RawFilePath">RawFilePath</a></td><td class="doc empty"> </td></tr><tr><td class="src">-> <a href="https://hackage.haskell.org/package/unix-2.7.1.0/docs/System-Posix-IO-ByteString.html#t:OpenMode">OpenMode</a></td><td class="doc empty"> </td></tr><tr><td class="src">-> [<a href="System-Posix-Directory-Foreign.html#t:Flags">Flags</a>]</td><td class="doc"><p>status flags of <code>open(2)</code></p></td></tr><tr><td class="src">-> <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/Data-Maybe.html#t:Maybe">Maybe</a> <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/System-Posix-Types.html#t:FileMode">FileMode</a></td><td class="doc"><p><code>Just x</code> => creates the file with the given modes, Nothing => the file must exist.</p></td></tr><tr><td class="src">-> <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/System-IO.html#t:IO">IO</a> <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/System-Posix-Types.html#t:Fd">Fd</a></td><td class="doc empty"> </td></tr></table></div><div class="doc"><p>Open and optionally create this file. See <code><a href="https://hackage.haskell.org/package/unix-2.7.1.0/docs/System-Posix.html#v:Files">Files</a></code> | |||
for information on how to use the <code>FileMode</code> type.</p><p>Note that passing <code>Just x</code> as the 4th argument triggers the | |||
<code><a href="System-Posix-Directory-Foreign.html#v:oCreat">oCreat</a></code> status flag, which must be set when you pass in <code><a href="System-Posix-Directory-Foreign.html#v:oExcl">oExcl</a></code> | |||
to the status flags. Also see the manpage for <code>open(2)</code>.</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -1,12 +0,0 @@ | |||
packages: ./hpath | |||
./hpath-directory | |||
./hpath-filepath | |||
./hpath-io | |||
./hpath-posix | |||
package hpath-io | |||
ghc-options: -O2 -fspec-constr-recursive=16 -fmax-worker-args=16 | |||
package streamly | |||
ghc-options: -O2 -fspec-constr-recursive=16 -fmax-worker-args=16 |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - <)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - <</p><table><tr><td class="src"><.></td><td class="module"><a href="System-Posix-FilePath.html#v:-60-.-62-">System.Posix.FilePath</a></td></tr><tr><td class="src"></></td><td> </td></tr><tr><td class="alt">1 (Function)</td><td class="module"><a href="System-Posix-FilePath.html#v:-60--47--62-">System.Posix.FilePath</a></td></tr><tr><td class="alt">2 (Function)</td><td class="module"><a href="HPath.html#v:-60--47--62-">HPath</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - A)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - A</p><table><tr><td class="src">Abs</td><td class="module"><a href="HPath.html#t:Abs">HPath</a></td></tr><tr><td class="src">addExtension</td><td class="module"><a href="System-Posix-FilePath.html#v:addExtension">System.Posix.FilePath</a></td></tr><tr><td class="src">addTrailingPathSeparator</td><td class="module"><a href="System-Posix-FilePath.html#v:addTrailingPathSeparator">System.Posix.FilePath</a></td></tr><tr><td class="src">allDirectoryContents</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:allDirectoryContents">System.Posix.Directory.Traversals</a></td></tr><tr><td class="src">allDirectoryContents'</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:allDirectoryContents-39-">System.Posix.Directory.Traversals</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - B)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - B</p><table><tr><td class="src">basename</td><td class="module"><a href="HPath.html#v:basename">HPath</a></td></tr><tr><td class="src">BlockDevice</td><td class="module"><a href="HPath-IO.html#v:BlockDevice">HPath.IO</a></td></tr><tr><td class="src">bracketeer</td><td class="module"><a href="HPath-IO-Errors.html#v:bracketeer">HPath.IO.Errors</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - C)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - C</p><table><tr><td class="src">canonicalizePath</td><td class="module"><a href="HPath-IO.html#v:canonicalizePath">HPath.IO</a></td></tr><tr><td class="src">canOpenDirectory</td><td class="module"><a href="HPath-IO-Errors.html#v:canOpenDirectory">HPath.IO.Errors</a></td></tr><tr><td class="src">catchErrno</td><td class="module"><a href="HPath-IO-Errors.html#v:catchErrno">HPath.IO.Errors</a></td></tr><tr><td class="src">CharacterDevice</td><td class="module"><a href="HPath-IO.html#v:CharacterDevice">HPath.IO</a></td></tr><tr><td class="src">CollectFailures</td><td class="module"><a href="HPath-IO.html#v:CollectFailures">HPath.IO</a></td></tr><tr><td class="src">combine</td><td class="module"><a href="System-Posix-FilePath.html#v:combine">System.Posix.FilePath</a></td></tr><tr><td class="src">copyDirRecursive</td><td class="module"><a href="HPath-IO.html#v:copyDirRecursive">HPath.IO</a></td></tr><tr><td class="src">copyFile</td><td class="module"><a href="HPath-IO.html#v:copyFile">HPath.IO</a></td></tr><tr><td class="src">CopyFileFailed</td><td class="module"><a href="HPath-IO-Errors.html#v:CopyFileFailed">HPath.IO.Errors</a></td></tr><tr><td class="src">CopyMode</td><td class="module"><a href="HPath-IO.html#t:CopyMode">HPath.IO</a></td></tr><tr><td class="src">createDir</td><td class="module"><a href="HPath-IO.html#v:createDir">HPath.IO</a></td></tr><tr><td class="src">CreateDirFailed</td><td class="module"><a href="HPath-IO-Errors.html#v:CreateDirFailed">HPath.IO.Errors</a></td></tr><tr><td class="src">createDirRecursive</td><td class="module"><a href="HPath-IO.html#v:createDirRecursive">HPath.IO</a></td></tr><tr><td class="src">createRegularFile</td><td class="module"><a href="HPath-IO.html#v:createRegularFile">HPath.IO</a></td></tr><tr><td class="src">createSymlink</td><td class="module"><a href="HPath-IO.html#v:createSymlink">HPath.IO</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - D)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - D</p><table><tr><td class="src">deleteDir</td><td class="module"><a href="HPath-IO.html#v:deleteDir">HPath.IO</a></td></tr><tr><td class="src">deleteDirRecursive</td><td class="module"><a href="HPath-IO.html#v:deleteDirRecursive">HPath.IO</a></td></tr><tr><td class="src">deleteFile</td><td class="module"><a href="HPath-IO.html#v:deleteFile">HPath.IO</a></td></tr><tr><td class="src">DestinationInSource</td><td class="module"><a href="HPath-IO-Errors.html#v:DestinationInSource">HPath.IO.Errors</a></td></tr><tr><td class="src">Directory</td><td class="module"><a href="HPath-IO.html#v:Directory">HPath.IO</a></td></tr><tr><td class="src">dirname</td><td class="module"><a href="HPath.html#v:dirname">HPath</a></td></tr><tr><td class="src">DirType</td><td> </td></tr><tr><td class="alt">1 (Type/Class)</td><td class="module"><a href="System-Posix-Directory-Foreign.html#t:DirType">System.Posix.Directory.Foreign</a></td></tr><tr><td class="alt">2 (Data Constructor)</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:DirType">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">doesDirectoryExist</td><td class="module"><a href="HPath-IO-Errors.html#v:doesDirectoryExist">HPath.IO.Errors</a></td></tr><tr><td class="src">doesFileExist</td><td class="module"><a href="HPath-IO-Errors.html#v:doesFileExist">HPath.IO.Errors</a></td></tr><tr><td class="src">dropExtension</td><td class="module"><a href="System-Posix-FilePath.html#v:dropExtension">System.Posix.FilePath</a></td></tr><tr><td class="src">dropExtensions</td><td class="module"><a href="System-Posix-FilePath.html#v:dropExtensions">System.Posix.FilePath</a></td></tr><tr><td class="src">dropFileName</td><td class="module"><a href="System-Posix-FilePath.html#v:dropFileName">System.Posix.FilePath</a></td></tr><tr><td class="src">dropTrailingPathSeparator</td><td class="module"><a href="System-Posix-FilePath.html#v:dropTrailingPathSeparator">System.Posix.FilePath</a></td></tr><tr><td class="src">dtBlk</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:dtBlk">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">dtChr</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:dtChr">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">dtDir</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:dtDir">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">dtFifo</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:dtFifo">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">dtLnk</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:dtLnk">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">dtReg</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:dtReg">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">dtSock</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:dtSock">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">dtUnknown</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:dtUnknown">System.Posix.Directory.Foreign</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - E)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - E</p><table><tr><td class="src">easyCopy</td><td class="module"><a href="HPath-IO.html#v:easyCopy">HPath.IO</a></td></tr><tr><td class="src">easyDelete</td><td class="module"><a href="HPath-IO.html#v:easyDelete">HPath.IO</a></td></tr><tr><td class="src">equalFilePath</td><td class="module"><a href="System-Posix-FilePath.html#v:equalFilePath">System.Posix.FilePath</a></td></tr><tr><td class="src">executeFile</td><td class="module"><a href="HPath-IO.html#v:executeFile">HPath.IO</a></td></tr><tr><td class="src">extSeparator</td><td class="module"><a href="System-Posix-FilePath.html#v:extSeparator">System.Posix.FilePath</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - F)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - F</p><table><tr><td class="src">FailEarly</td><td class="module"><a href="HPath-IO.html#v:FailEarly">HPath.IO</a></td></tr><tr><td class="src">fdOpendir</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:fdOpendir">System.Posix.Directory.Traversals</a></td></tr><tr><td class="src">FileType</td><td class="module"><a href="HPath-IO.html#t:FileType">HPath.IO</a></td></tr><tr><td class="src">Flags</td><td> </td></tr><tr><td class="alt">1 (Type/Class)</td><td class="module"><a href="System-Posix-Directory-Foreign.html#t:Flags">System.Posix.Directory.Foreign</a></td></tr><tr><td class="alt">2 (Data Constructor)</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:Flags">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">Fn</td><td class="module"><a href="HPath.html#t:Fn">HPath</a></td></tr><tr><td class="src">fromAbs</td><td class="module"><a href="HPath.html#v:fromAbs">HPath</a></td></tr><tr><td class="src">fromRel</td><td class="module"><a href="HPath.html#v:fromRel">HPath</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - G)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - G</p><table><tr><td class="src">getAllParents</td><td class="module"><a href="HPath.html#v:getAllParents">HPath</a></td></tr><tr><td class="src">getDirectoryContents</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:getDirectoryContents">System.Posix.Directory.Traversals</a></td></tr><tr><td class="src">getDirectoryContents'</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:getDirectoryContents-39-">System.Posix.Directory.Traversals</a></td></tr><tr><td class="src">getDirsFiles</td><td class="module"><a href="HPath-IO.html#v:getDirsFiles">HPath.IO</a></td></tr><tr><td class="src">getFileType</td><td class="module"><a href="HPath-IO.html#v:getFileType">HPath.IO</a></td></tr><tr><td class="src">getSearchPath</td><td class="module"><a href="System-Posix-FilePath.html#v:getSearchPath">System.Posix.FilePath</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - H)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - H</p><table><tr><td class="src">handleIOError</td><td class="module"><a href="HPath-IO-Errors.html#v:handleIOError">HPath.IO.Errors</a></td></tr><tr><td class="src">hasExtension</td><td class="module"><a href="System-Posix-FilePath.html#v:hasExtension">System.Posix.FilePath</a></td></tr><tr><td class="src">hasParentDir</td><td class="module"><a href="System-Posix-FilePath.html#v:hasParentDir">System.Posix.FilePath</a></td></tr><tr><td class="src">hasTrailingPathSeparator</td><td class="module"><a href="System-Posix-FilePath.html#v:hasTrailingPathSeparator">System.Posix.FilePath</a></td></tr><tr><td class="src">hiddenFile</td><td class="module"><a href="System-Posix-FilePath.html#v:hiddenFile">System.Posix.FilePath</a></td></tr><tr><td class="src">HPathIOException</td><td class="module"><a href="HPath-IO-Errors.html#t:HPathIOException">HPath.IO.Errors</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - I)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - I</p><table><tr><td class="src">isAbsolute</td><td class="module"><a href="System-Posix-FilePath.html#v:isAbsolute">System.Posix.FilePath</a></td></tr><tr><td class="src">isCopyFileFailed</td><td class="module"><a href="HPath-IO-Errors.html#v:isCopyFileFailed">HPath.IO.Errors</a></td></tr><tr><td class="src">isCreateDirFailed</td><td class="module"><a href="HPath-IO-Errors.html#v:isCreateDirFailed">HPath.IO.Errors</a></td></tr><tr><td class="src">isDestinationInSource</td><td class="module"><a href="HPath-IO-Errors.html#v:isDestinationInSource">HPath.IO.Errors</a></td></tr><tr><td class="src">isExtSeparator</td><td class="module"><a href="System-Posix-FilePath.html#v:isExtSeparator">System.Posix.FilePath</a></td></tr><tr><td class="src">isFileName</td><td class="module"><a href="System-Posix-FilePath.html#v:isFileName">System.Posix.FilePath</a></td></tr><tr><td class="src">isParentOf</td><td class="module"><a href="HPath.html#v:isParentOf">HPath</a></td></tr><tr><td class="src">isPathSeparator</td><td class="module"><a href="System-Posix-FilePath.html#v:isPathSeparator">System.Posix.FilePath</a></td></tr><tr><td class="src">isReadContentsFailed</td><td class="module"><a href="HPath-IO-Errors.html#v:isReadContentsFailed">HPath.IO.Errors</a></td></tr><tr><td class="src">isRecreateSymlinkFailed</td><td class="module"><a href="HPath-IO-Errors.html#v:isRecreateSymlinkFailed">HPath.IO.Errors</a></td></tr><tr><td class="src">isRecursiveFailure</td><td class="module"><a href="HPath-IO-Errors.html#v:isRecursiveFailure">HPath.IO.Errors</a></td></tr><tr><td class="src">isRelative</td><td class="module"><a href="System-Posix-FilePath.html#v:isRelative">System.Posix.FilePath</a></td></tr><tr><td class="src">isSameFile</td><td class="module"><a href="HPath-IO-Errors.html#v:isSameFile">HPath.IO.Errors</a></td></tr><tr><td class="src">isSearchPathSeparator</td><td class="module"><a href="System-Posix-FilePath.html#v:isSearchPathSeparator">System.Posix.FilePath</a></td></tr><tr><td class="src">isSupported</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:isSupported">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">isValid</td><td class="module"><a href="System-Posix-FilePath.html#v:isValid">System.Posix.FilePath</a></td></tr><tr><td class="src">isWritable</td><td class="module"><a href="HPath-IO-Errors.html#v:isWritable">HPath.IO.Errors</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - J)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - J</p><table><tr><td class="src">joinPath</td><td class="module"><a href="System-Posix-FilePath.html#v:joinPath">System.Posix.FilePath</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - M)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - M</p><table><tr><td class="src">makeRelative</td><td class="module"><a href="System-Posix-FilePath.html#v:makeRelative">System.Posix.FilePath</a></td></tr><tr><td class="src">makeValid</td><td class="module"><a href="System-Posix-FilePath.html#v:makeValid">System.Posix.FilePath</a></td></tr><tr><td class="src">moveFile</td><td class="module"><a href="HPath-IO.html#v:moveFile">HPath.IO</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - N)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - N</p><table><tr><td class="src">NamedPipe</td><td class="module"><a href="HPath-IO.html#v:NamedPipe">HPath.IO</a></td></tr><tr><td class="src">newDirPerms</td><td class="module"><a href="HPath-IO.html#v:newDirPerms">HPath.IO</a></td></tr><tr><td class="src">newFilePerms</td><td class="module"><a href="HPath-IO.html#v:newFilePerms">HPath.IO</a></td></tr><tr><td class="src">normalise</td><td class="module"><a href="System-Posix-FilePath.html#v:normalise">System.Posix.FilePath</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - O)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - O</p><table><tr><td class="src">oAppend</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oAppend">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oAsync</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oAsync">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oCloexec</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oCloexec">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oCreat</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oCreat">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oDirectory</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oDirectory">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oExcl</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oExcl">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oNoctty</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oNoctty">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oNofollow</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oNofollow">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oNonblock</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oNonblock">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">openFd</td><td class="module"><a href="System-Posix-FD.html#v:openFd">System.Posix.FD</a></td></tr><tr><td class="src">openFile</td><td class="module"><a href="HPath-IO.html#v:openFile">HPath.IO</a></td></tr><tr><td class="src">oRdonly</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oRdonly">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oRdwr</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oRdwr">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oSync</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oSync">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">oTrunc</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oTrunc">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">Overwrite</td><td class="module"><a href="HPath-IO.html#v:Overwrite">HPath.IO</a></td></tr><tr><td class="src">oWronly</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:oWronly">System.Posix.Directory.Foreign</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - P)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - P</p><table><tr><td class="src">packDirStream</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:packDirStream">System.Posix.Directory.Traversals</a></td></tr><tr><td class="src">parseAbs</td><td class="module"><a href="HPath.html#v:parseAbs">HPath</a></td></tr><tr><td class="src">parseFn</td><td class="module"><a href="HPath.html#v:parseFn">HPath</a></td></tr><tr><td class="src">parseRel</td><td class="module"><a href="HPath.html#v:parseRel">HPath</a></td></tr><tr><td class="src">Path</td><td> </td></tr><tr><td class="alt">1 (Type/Class)</td><td class="module"><a href="HPath.html#t:Path">HPath</a></td></tr><tr><td class="alt">2 (Data Constructor)</td><td class="module"><a href="HPath.html#v:Path">HPath</a></td></tr><tr><td class="src">PathException</td><td class="module"><a href="HPath.html#t:PathException">HPath</a></td></tr><tr><td class="src">pathMax</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:pathMax">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">PathParseException</td><td class="module"><a href="HPath.html#t:PathParseException">HPath</a></td></tr><tr><td class="src">pathSeparator</td><td class="module"><a href="System-Posix-FilePath.html#v:pathSeparator">System.Posix.FilePath</a></td></tr><tr><td class="src">peekFilePath</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">peekFilePathLen</td><td class="module">System.Posix.FilePath</td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - R)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - R</p><table><tr><td class="src">RawFilePath</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">reactOnError</td><td class="module"><a href="HPath-IO-Errors.html#v:reactOnError">HPath.IO.Errors</a></td></tr><tr><td class="src">ReadContentsFailed</td><td class="module"><a href="HPath-IO-Errors.html#v:ReadContentsFailed">HPath.IO.Errors</a></td></tr><tr><td class="src">readDirEnt</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:readDirEnt">System.Posix.Directory.Traversals</a></td></tr><tr><td class="src">realpath</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:realpath">System.Posix.Directory.Traversals</a></td></tr><tr><td class="src">recreateSymlink</td><td class="module"><a href="HPath-IO.html#v:recreateSymlink">HPath.IO</a></td></tr><tr><td class="src">RecreateSymlinkFailed</td><td class="module"><a href="HPath-IO-Errors.html#v:RecreateSymlinkFailed">HPath.IO.Errors</a></td></tr><tr><td class="src">RecursiveErrorMode</td><td class="module"><a href="HPath-IO.html#t:RecursiveErrorMode">HPath.IO</a></td></tr><tr><td class="src">RecursiveFailure</td><td class="module"><a href="HPath-IO-Errors.html#v:RecursiveFailure">HPath.IO.Errors</a></td></tr><tr><td class="src">RecursiveFailureHint</td><td class="module"><a href="HPath-IO-Errors.html#t:RecursiveFailureHint">HPath.IO.Errors</a></td></tr><tr><td class="src">RegularFile</td><td class="module"><a href="HPath-IO.html#v:RegularFile">HPath.IO</a></td></tr><tr><td class="src">Rel</td><td class="module"><a href="HPath.html#t:Rel">HPath</a></td></tr><tr><td class="src">RelC</td><td class="module"><a href="HPath.html#t:RelC">HPath</a></td></tr><tr><td class="src">renameFile</td><td class="module"><a href="HPath-IO.html#v:renameFile">HPath.IO</a></td></tr><tr><td class="src">replaceBaseName</td><td class="module"><a href="System-Posix-FilePath.html#v:replaceBaseName">System.Posix.FilePath</a></td></tr><tr><td class="src">replaceDirectory</td><td class="module"><a href="System-Posix-FilePath.html#v:replaceDirectory">System.Posix.FilePath</a></td></tr><tr><td class="src">replaceExtension</td><td class="module"><a href="System-Posix-FilePath.html#v:replaceExtension">System.Posix.FilePath</a></td></tr><tr><td class="src">replaceFileName</td><td class="module"><a href="System-Posix-FilePath.html#v:replaceFileName">System.Posix.FilePath</a></td></tr><tr><td class="src">rethrowErrnoAs</td><td class="module"><a href="HPath-IO-Errors.html#v:rethrowErrnoAs">HPath.IO.Errors</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - S)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - S</p><table><tr><td class="src">SameFile</td><td class="module"><a href="HPath-IO-Errors.html#v:SameFile">HPath.IO.Errors</a></td></tr><tr><td class="src">sameFile</td><td class="module"><a href="HPath-IO-Errors.html#v:sameFile">HPath.IO.Errors</a></td></tr><tr><td class="src">searchPathSeparator</td><td class="module"><a href="System-Posix-FilePath.html#v:searchPathSeparator">System.Posix.FilePath</a></td></tr><tr><td class="src">Socket</td><td class="module"><a href="HPath-IO.html#v:Socket">HPath.IO</a></td></tr><tr><td class="src">splitDirectories</td><td class="module"><a href="System-Posix-FilePath.html#v:splitDirectories">System.Posix.FilePath</a></td></tr><tr><td class="src">splitExtension</td><td class="module"><a href="System-Posix-FilePath.html#v:splitExtension">System.Posix.FilePath</a></td></tr><tr><td class="src">splitExtensions</td><td class="module"><a href="System-Posix-FilePath.html#v:splitExtensions">System.Posix.FilePath</a></td></tr><tr><td class="src">splitFileName</td><td class="module"><a href="System-Posix-FilePath.html#v:splitFileName">System.Posix.FilePath</a></td></tr><tr><td class="src">splitPath</td><td class="module"><a href="System-Posix-FilePath.html#v:splitPath">System.Posix.FilePath</a></td></tr><tr><td class="src">splitSearchPath</td><td class="module"><a href="System-Posix-FilePath.html#v:splitSearchPath">System.Posix.FilePath</a></td></tr><tr><td class="src">Strict</td><td class="module"><a href="HPath-IO.html#v:Strict">HPath.IO</a></td></tr><tr><td class="src">stripDir</td><td class="module"><a href="HPath.html#v:stripDir">HPath</a></td></tr><tr><td class="src">stripExtension</td><td class="module"><a href="System-Posix-FilePath.html#v:stripExtension">System.Posix.FilePath</a></td></tr><tr><td class="src">SymbolicLink</td><td class="module"><a href="HPath-IO.html#v:SymbolicLink">HPath.IO</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - T)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - T</p><table><tr><td class="src">takeBaseName</td><td class="module"><a href="System-Posix-FilePath.html#v:takeBaseName">System.Posix.FilePath</a></td></tr><tr><td class="src">takeDirectory</td><td class="module"><a href="System-Posix-FilePath.html#v:takeDirectory">System.Posix.FilePath</a></td></tr><tr><td class="src">takeExtension</td><td class="module"><a href="System-Posix-FilePath.html#v:takeExtension">System.Posix.FilePath</a></td></tr><tr><td class="src">takeExtensions</td><td class="module"><a href="System-Posix-FilePath.html#v:takeExtensions">System.Posix.FilePath</a></td></tr><tr><td class="src">takeFileName</td><td class="module"><a href="System-Posix-FilePath.html#v:takeFileName">System.Posix.FilePath</a></td></tr><tr><td class="src">throwDestinationInSource</td><td class="module"><a href="HPath-IO-Errors.html#v:throwDestinationInSource">HPath.IO.Errors</a></td></tr><tr><td class="src">throwDirDoesExist</td><td class="module"><a href="HPath-IO-Errors.html#v:throwDirDoesExist">HPath.IO.Errors</a></td></tr><tr><td class="src">throwErrnoPath</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwErrnoPathIf</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwErrnoPathIfMinus1</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwErrnoPathIfMinus1Retry</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwErrnoPathIfMinus1Retry_</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwErrnoPathIfMinus1_</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwErrnoPathIfNull</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwErrnoPathIfNullRetry</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwErrnoPathIfRetry</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwErrnoPathIf_</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">throwFileDoesExist</td><td class="module"><a href="HPath-IO-Errors.html#v:throwFileDoesExist">HPath.IO.Errors</a></td></tr><tr><td class="src">throwSameFile</td><td class="module"><a href="HPath-IO-Errors.html#v:throwSameFile">HPath.IO.Errors</a></td></tr><tr><td class="src">toFilePath</td><td class="module"><a href="HPath.html#v:toFilePath">HPath</a></td></tr><tr><td class="src">traverseDirectory</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:traverseDirectory">System.Posix.Directory.Traversals</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - U)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - U</p><table><tr><td class="src">unFlags</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:unFlags">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">unionFlags</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:unionFlags">System.Posix.Directory.Foreign</a></td></tr><tr><td class="src">unpackDirStream</td><td class="module"><a href="System-Posix-Directory-Traversals.html#v:unpackDirStream">System.Posix.Directory.Traversals</a></td></tr><tr><td class="src">UnsupportedFlag</td><td class="module"><a href="System-Posix-Directory-Foreign.html#v:UnsupportedFlag">System.Posix.Directory.Foreign</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index - W)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div><div id="index"><p class="caption">Index - W</p><table><tr><td class="src">withAbsPath</td><td class="module"><a href="HPath.html#v:withAbsPath">HPath</a></td></tr><tr><td class="src">withFilePath</td><td class="module">System.Posix.FilePath</td></tr><tr><td class="src">withFnPath</td><td class="module"><a href="HPath.html#v:withFnPath">HPath</a></td></tr><tr><td class="src">withRelPath</td><td class="module"><a href="HPath.html#v:withRelPath">HPath</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,4 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>hpath-0.8.0: Support for well-typed paths (Index)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[ | |||
window.onload = function () {pageLoad();}; | |||
//]]> | |||
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">hpath-0.8.0: Support for well-typed paths</p></div><div id="content"><div id="alphabet"><ul><li><a href="doc-index-A.html">A</a></li><li><a href="doc-index-B.html">B</a></li><li><a href="doc-index-C.html">C</a></li><li><a href="doc-index-D.html">D</a></li><li><a href="doc-index-E.html">E</a></li><li><a href="doc-index-F.html">F</a></li><li><a href="doc-index-G.html">G</a></li><li><a href="doc-index-H.html">H</a></li><li><a href="doc-index-I.html">I</a></li><li><a href="doc-index-J.html">J</a></li><li><a href="doc-index-M.html">M</a></li><li><a href="doc-index-N.html">N</a></li><li><a href="doc-index-O.html">O</a></li><li><a href="doc-index-P.html">P</a></li><li><a href="doc-index-R.html">R</a></li><li><a href="doc-index-S.html">S</a></li><li><a href="doc-index-T.html">T</a></li><li><a href="doc-index-U.html">U</a></li><li><a href="doc-index-W.html">W</a></li><li><a href="doc-index-60.html"><</a></li><li><a href="doc-index-All.html">All</a></li></ul></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.16.1</p></div></body></html> |
@@ -0,0 +1,30 @@ | |||
<!DOCTYPE html | |||
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" | |||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml"> | |||
<head> | |||
<title></title> | |||
<script src="haddock-util.js" type="text/javascript"></script> | |||
<script type="text/javascript"><!-- | |||
/* | |||
The synopsis frame needs to be updated using javascript, so we hide | |||
it by default and only show it if javascript is enabled. | |||
TODO: provide some means to disable it. | |||
*/ | |||
function load() { | |||
var d = document.getElementById("inner-fs"); | |||
d.rows = "50%,50%"; | |||
postReframe(); | |||
} | |||
--></script> | |||
</head> | |||
<frameset id="outer-fs" cols="25%,75%" onload="load()"> | |||
<frameset id="inner-fs" rows="100%,0%"> | |||
<frame src="index-frames.html" name="modules" /> | |||
<frame src="" name="synopsis" /> | |||
</frameset> | |||
<frame src="index.html" name="main" /> | |||
</frameset> | |||
</html> |
@@ -0,0 +1,344 @@ | |||
// Haddock JavaScript utilities | |||
var rspace = /\s\s+/g, | |||
rtrim = /^\s+|\s+$/g; | |||
function spaced(s) { return (" " + s + " ").replace(rspace, " "); } | |||
function trim(s) { return s.replace(rtrim, ""); } | |||
function hasClass(elem, value) { | |||
var className = spaced(elem.className || ""); | |||
return className.indexOf( " " + value + " " ) >= 0; | |||
} | |||
function addClass(elem, value) { | |||
var className = spaced(elem.className || ""); | |||
if ( className.indexOf( " " + value + " " ) < 0 ) { | |||
elem.className = trim(className + " " + value); | |||
} | |||
} | |||
function removeClass(elem, value) { | |||
var className = spaced(elem.className || ""); | |||
className = className.replace(" " + value + " ", " "); | |||
elem.className = trim(className); | |||
} | |||
function toggleClass(elem, valueOn, valueOff, bool) { | |||
if (bool == null) { bool = ! hasClass(elem, valueOn); } | |||
if (bool) { | |||
removeClass(elem, valueOff); | |||
addClass(elem, valueOn); | |||
} | |||
else { | |||
removeClass(elem, valueOn); | |||
addClass(elem, valueOff); | |||
} | |||
return bool; | |||
} | |||
function makeClassToggle(valueOn, valueOff) | |||
{ | |||
return function(elem, bool) { | |||
return toggleClass(elem, valueOn, valueOff, bool); | |||
} | |||
} | |||
toggleShow = makeClassToggle("show", "hide"); | |||
toggleCollapser = makeClassToggle("collapser", "expander"); | |||
function toggleSection(id) | |||
{ | |||
var b = toggleShow(document.getElementById("section." + id)); | |||
toggleCollapser(document.getElementById("control." + id), b); | |||
rememberCollapsed(id, b); | |||
return b; | |||
} | |||
var collapsed = {}; | |||
function rememberCollapsed(id, b) | |||
{ | |||
if(b) | |||
delete collapsed[id] | |||
else | |||
collapsed[id] = null; | |||
var sections = []; | |||
for(var i in collapsed) | |||
{ | |||
if(collapsed.hasOwnProperty(i)) | |||
sections.push(i); | |||
} | |||
// cookie specific to this page; don't use setCookie which sets path=/ | |||
document.cookie = "collapsed=" + escape(sections.join('+')); | |||
} | |||
function restoreCollapsed() | |||
{ | |||
var cookie = getCookie("collapsed"); | |||
if(!cookie) | |||
return; | |||
var ids = cookie.split('+'); | |||
for(var i in ids) | |||
{ | |||
if(document.getElementById("section." + ids[i])) | |||
toggleSection(ids[i]); | |||
} | |||
} | |||
function setCookie(name, value) { | |||
document.cookie = name + "=" + escape(value) + ";path=/;"; | |||
} | |||
function clearCookie(name) { | |||
document.cookie = name + "=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;"; | |||
} | |||
function getCookie(name) { | |||
var nameEQ = name + "="; | |||
var ca = document.cookie.split(';'); | |||
for(var i=0;i < ca.length;i++) { | |||
var c = ca[i]; | |||
while (c.charAt(0)==' ') c = c.substring(1,c.length); | |||
if (c.indexOf(nameEQ) == 0) { | |||
return unescape(c.substring(nameEQ.length,c.length)); | |||
} | |||
} | |||
return null; | |||
} | |||
var max_results = 75; // 50 is not enough to search for map in the base libraries | |||
var shown_range = null; | |||
var last_search = null; | |||
function quick_search() | |||
{ | |||
perform_search(false); | |||
} | |||
function full_search() | |||
{ | |||
perform_search(true); | |||
} | |||
function perform_search(full) | |||
{ | |||
var text = document.getElementById("searchbox").value.toLowerCase(); | |||
if (text == last_search && !full) return; | |||
last_search = text; | |||
var table = document.getElementById("indexlist"); | |||
var status = document.getElementById("searchmsg"); | |||
var children = table.firstChild.childNodes; | |||
// first figure out the first node with the prefix | |||
var first = bisect(-1); | |||
var last = (first == -1 ? -1 : bisect(1)); | |||
if (first == -1) | |||
{ | |||
table.className = ""; | |||
status.innerHTML = "No results found, displaying all"; | |||
} | |||
else if (first == 0 && last == children.length - 1) | |||
{ | |||
table.className = ""; | |||
status.innerHTML = ""; | |||
} | |||
else if (last - first >= max_results && !full) | |||
{ | |||
table.className = ""; | |||
status.innerHTML = "More than " + max_results + ", press Search to display"; | |||
} | |||
else | |||
{ | |||
// decide what you need to clear/show | |||
if (shown_range) | |||
setclass(shown_range[0], shown_range[1], "indexrow"); | |||
setclass(first, last, "indexshow"); | |||
shown_range = [first, last]; | |||
table.className = "indexsearch"; | |||
status.innerHTML = ""; | |||
} | |||
function setclass(first, last, status) | |||
{ | |||
for (var i = first; i <= last; i++) | |||
{ | |||
children[i].className = status; | |||
} | |||
} | |||
// do a binary search, treating 0 as ... | |||
// return either -1 (no 0's found) or location of most far match | |||
function bisect(dir) | |||
{ | |||
var first = 0, finish = children.length - 1; | |||
var mid, success = false; | |||
while (finish - first > 3) | |||
{ | |||
mid = Math.floor((finish + first) / 2); | |||
var i = checkitem(mid); | |||
if (i == 0) i = dir; | |||
if (i == -1) | |||
finish = mid; | |||
else | |||
first = mid; | |||
} | |||
var a = (dir == 1 ? first : finish); | |||
var b = (dir == 1 ? finish : first); | |||
for (var i = b; i != a - dir; i -= dir) | |||
{ | |||
if (checkitem(i) == 0) return i; | |||
} | |||
return -1; | |||
} | |||
// from an index, decide what the result is | |||
// 0 = match, -1 is lower, 1 is higher | |||
function checkitem(i) | |||
{ | |||
var s = getitem(i).toLowerCase().substr(0, text.length); | |||
if (s == text) return 0; | |||
else return (s > text ? -1 : 1); | |||
} | |||
// from an index, get its string | |||
// this abstracts over alternates | |||
function getitem(i) | |||
{ | |||
for ( ; i >= 0; i--) | |||
{ | |||
var s = children[i].firstChild.firstChild.data; | |||
if (s.indexOf(' ') == -1) | |||
return s; | |||
} | |||
return ""; // should never be reached | |||
} | |||
} | |||
function setSynopsis(filename) { | |||
if (parent.window.synopsis) { | |||
if (parent.window.synopsis.location.replace) { | |||
// In Firefox this avoids adding the change to the history. | |||
parent.window.synopsis.location.replace(filename); | |||
} else { | |||
parent.window.synopsis.location = filename; | |||
} | |||
} | |||
} | |||
function addMenuItem(html) { | |||
var menu = document.getElementById("page-menu"); | |||
if (menu) { | |||
var btn = menu.firstChild.cloneNode(false); | |||
btn.innerHTML = html; | |||
menu.appendChild(btn); | |||
} | |||
} | |||
function adjustForFrames() { | |||
var bodyCls; | |||
if (parent.location.href == window.location.href) { | |||
// not in frames, so add Frames button | |||
addMenuItem("<a href='#' onclick='reframe();return true;'>Frames</a>"); | |||
bodyCls = "no-frame"; | |||
} | |||
else { | |||
bodyCls = "in-frame"; | |||
} | |||
addClass(document.body, bodyCls); | |||
} | |||
function reframe() { | |||
setCookie("haddock-reframe", document.URL); | |||
window.location = "frames.html"; | |||
} | |||
function postReframe() { | |||
var s = getCookie("haddock-reframe"); | |||
if (s) { | |||
parent.window.main.location = s; | |||
clearCookie("haddock-reframe"); | |||
} | |||
} | |||
function styles() { | |||
var i, a, es = document.getElementsByTagName("link"), rs = []; | |||
for (i = 0; a = es[i]; i++) { | |||
if(a.rel.indexOf("style") != -1 && a.title) { | |||
rs.push(a); | |||
} | |||
} | |||
return rs; | |||
} | |||
function addStyleMenu() { | |||
var as = styles(); | |||
var i, a, btns = ""; | |||
for(i=0; a = as[i]; i++) { | |||
btns += "<li><a href='#' onclick=\"setActiveStyleSheet('" | |||
+ a.title + "'); return false;\">" | |||
+ a.title + "</a></li>" | |||
} | |||
if (as.length > 1) { | |||
var h = "<div id='style-menu-holder'>" | |||
+ "<a href='#' onclick='styleMenu(); return false;'>Style ▾</a>" | |||
+ "<ul id='style-menu' class='hide'>" + btns + "</ul>" | |||
+ "</div>"; | |||
addMenuItem(h); | |||
} | |||
} | |||
function setActiveStyleSheet(title) { | |||
var as = styles(); | |||
var i, a, found; | |||
for(i=0; a = as[i]; i++) { | |||
a.disabled = true; | |||
// need to do this always, some browsers are edge triggered | |||
if(a.title == title) { | |||
found = a; | |||
} | |||
} | |||
if (found) { | |||
found.disabled = false; | |||
setCookie("haddock-style", title); | |||
} | |||
else { | |||
as[0].disabled = false; | |||
clearCookie("haddock-style"); | |||
} | |||
styleMenu(false); | |||
} | |||
function resetStyle() { | |||
var s = getCookie("haddock-style"); | |||
if (s) setActiveStyleSheet(s); | |||
} | |||
function styleMenu(show) { | |||
var m = document.getElementById('style-menu'); | |||
if (m) toggleShow(m, show); | |||
} | |||
function pageLoad() { | |||
addStyleMenu(); | |||
adjustForFrames(); | |||
resetStyle(); | |||
restoreCollapsed(); | |||
} | |||
@@ -1,21 +0,0 @@ | |||
# Revision history for hpath-directory | |||
## 0.13.4 -- 2020-05-08 | |||
* Add getDirsFilesStream and use streamly-posix for dircontents (#34) | |||
## 0.13.3 -- 2020-04-14 | |||
* Fix tests on mac | |||
## 0.13.2 -- 2020-02-17 | |||
* Fix bug in `createDirRecursive` with trailing path separators | |||
## 0.13.1 -- 2020-01-29 | |||
* Split some functionality out into 'hpath-posix' | |||
## 0.1.0.0 -- 2020-01-26 | |||
* First version. Released on an unsuspecting world. |
@@ -1,30 +0,0 @@ | |||
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. |
@@ -1,21 +0,0 @@ | |||
# 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-directory.svg?label=Hackage)](https://hackage.haskell.org/package/hpath-directory) [![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-directory.svg)](http://packdeps.haskellers.com/feed?needle=hpath-directory) | |||
Support high-level IO operations on files/directories, utilizing ByteString | |||
as FilePaths. | |||
This package is part of the HPath suite, also check out: | |||
* [hpath](https://hackage.haskell.org/package/hpath) | |||
* [hpath-filepath](https://hackage.haskell.org/package/hpath-filepath) | |||
* [hpath-io](https://hackage.haskell.org/package/hpath-io) | |||
## Motivation | |||
This is basically a fork of [directory](https://hackage.haskell.org/package/directory), but is a complete rewrite and the API doesn't follow the directory package. | |||
## 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 |
@@ -1,2 +0,0 @@ | |||
import Distribution.Simple | |||
main = defaultMain |
@@ -1,116 +0,0 @@ | |||
cabal-version: >=1.10 | |||
name: hpath-directory | |||
version: 0.13.4 | |||
synopsis: Alternative to 'directory' package with ByteString based filepaths | |||
description: This provides a safer alternative to the 'directory' | |||
package. FilePaths are ByteString based, so this | |||
package only works on POSIX systems. | |||
For a more high-level version of this with | |||
proper Path type, use 'hpath-io', which makes | |||
use of this package. | |||
homepage: https://github.com/hasufell/hpath | |||
bug-reports: https://github.com/hasufell/hpath/issues | |||
license: BSD3 | |||
license-file: LICENSE | |||
author: Julian Ospald <hasufell@posteo.de> | |||
maintainer: Julian Ospald <hasufell@posteo.de> | |||
copyright: Julian Ospald <hasufell@posteo.de> 2020 | |||
category: Filesystem | |||
build-type: Simple | |||
extra-source-files: CHANGELOG.md | |||
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 | |||
library | |||
if os(windows) | |||
build-depends: unbuildable<0 | |||
buildable: False | |||
exposed-modules: System.Posix.RawFilePath.Directory | |||
System.Posix.RawFilePath.Directory.Errors | |||
-- other-modules: | |||
-- other-extensions: | |||
build-depends: base >= 4.8 && <5 | |||
, IfElse | |||
, bytestring >= 0.10 | |||
, exceptions >= 0.10 | |||
, hpath-filepath >= 0.10.3 | |||
, hpath-posix >= 0.13 | |||
, safe-exceptions >= 0.1 | |||
, streamly >= 0.7 | |||
, streamly-bytestring >= 0.1.2 | |||
, streamly-posix >= 0.1.0.1 | |||
, time >= 1.8 | |||
, transformers | |||
, unix >= 2.5 | |||
, unix-bytestring >= 0.3 | |||
, utf8-string | |||
if impl(ghc < 8.0) | |||
build-depends: | |||
fail >= 4.9 | |||
hs-source-dirs: src | |||
default-language: Haskell2010 | |||
default-extensions: PackageImports | |||
test-suite spec | |||
if os(windows) | |||
build-depends: unbuildable<0 | |||
buildable: False | |||
Type: exitcode-stdio-1.0 | |||
Default-Language: Haskell2010 | |||
Hs-Source-Dirs: test | |||
Main-Is: Main.hs | |||
other-modules: | |||
System.Posix.RawFilePath.Directory.AppendFileSpec | |||
System.Posix.RawFilePath.Directory.CanonicalizePathSpec | |||
System.Posix.RawFilePath.Directory.CopyDirRecursiveCollectFailuresSpec | |||
System.Posix.RawFilePath.Directory.CopyDirRecursiveOverwriteSpec | |||
System.Posix.RawFilePath.Directory.CopyDirRecursiveSpec | |||
System.Posix.RawFilePath.Directory.CopyFileOverwriteSpec | |||
System.Posix.RawFilePath.Directory.CopyFileSpec | |||
System.Posix.RawFilePath.Directory.CreateDirIfMissingSpec | |||
System.Posix.RawFilePath.Directory.CreateDirRecursiveSpec | |||
System.Posix.RawFilePath.Directory.CreateDirSpec | |||
System.Posix.RawFilePath.Directory.CreateRegularFileSpec | |||
System.Posix.RawFilePath.Directory.CreateSymlinkSpec | |||
System.Posix.RawFilePath.Directory.DeleteDirRecursiveSpec | |||
System.Posix.RawFilePath.Directory.DeleteDirSpec | |||
System.Posix.RawFilePath.Directory.DeleteFileSpec | |||
System.Posix.RawFilePath.Directory.GetDirsFilesSpec | |||
System.Posix.RawFilePath.Directory.GetFileTypeSpec | |||
System.Posix.RawFilePath.Directory.MoveFileOverwriteSpec | |||
System.Posix.RawFilePath.Directory.MoveFileSpec | |||
System.Posix.RawFilePath.Directory.ReadFileSpec | |||
System.Posix.RawFilePath.Directory.RecreateSymlinkOverwriteSpec | |||
System.Posix.RawFilePath.Directory.RecreateSymlinkSpec | |||
System.Posix.RawFilePath.Directory.RenameFileSpec | |||
System.Posix.RawFilePath.Directory.ToAbsSpec | |||
System.Posix.RawFilePath.Directory.WriteFileLSpec | |||
System.Posix.RawFilePath.Directory.WriteFileSpec | |||
Spec | |||
Utils | |||
GHC-Options: -Wall | |||
Build-Depends: base | |||
, HUnit | |||
, IfElse | |||
, bytestring >= 0.10.0.0 | |||
, hpath-directory | |||
, hpath-filepath >= 0.10 | |||
, hpath-posix >= 0.13 | |||
, hspec >= 1.3 | |||
, process | |||
, time >= 1.8 | |||
, unix | |||
, unix-bytestring | |||
, utf8-string | |||
default-extensions: PackageImports | |||
source-repository head | |||
type: git | |||
location: https://github.com/hasufell/hpath |
@@ -1,1228 +0,0 @@ | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
{-# LANGUAGE CPP #-} | |||
{-# LANGUAGE FlexibleContexts #-} -- streamly | |||
module System.Posix.RawFilePath.Directory | |||
( | |||
-- * Types | |||
FileType(..) | |||
, RecursiveErrorMode(..) | |||
, CopyMode(..) | |||
-- * File copying | |||
, copyDirRecursive | |||
, recreateSymlink | |||
, copyFile | |||
, easyCopy | |||
-- * File deletion | |||
, deleteFile | |||
, deleteDir | |||
, deleteDirRecursive | |||
, easyDelete | |||
-- * File opening | |||
, openFile | |||
, executeFile | |||
-- * File creation | |||
, createRegularFile | |||
, createDir | |||
, createDirIfMissing | |||
, createDirRecursive | |||
, createSymlink | |||
-- * File renaming/moving | |||
, renameFile | |||
, moveFile | |||
-- * File reading | |||
, readFile | |||
, readFileStream | |||
-- * File writing | |||
, writeFile | |||
, writeFileL | |||
, appendFile | |||
-- * File permissions | |||
, newFilePerms | |||
, newDirPerms | |||
-- * File checks | |||
, doesExist | |||
, doesFileExist | |||
, doesDirectoryExist | |||
, isReadable | |||
, isWritable | |||
, isExecutable | |||
, canOpenDirectory | |||
-- * File times | |||
, getModificationTime | |||
, setModificationTime | |||
, setModificationTimeHiRes | |||
-- * Directory reading | |||
, getDirsFiles | |||
, getDirsFiles' | |||
, getDirsFilesStream | |||
-- * Filetype operations | |||
, getFileType | |||
-- * Others | |||
, canonicalizePath | |||
, toAbs | |||
) | |||
where | |||
import Control.Applicative ( (<$>) ) | |||
import Control.Exception.Safe ( IOException | |||
, MonadCatch | |||
, MonadMask | |||
, bracket | |||
, bracketOnError | |||
, onException | |||
, throwIO | |||
, finally | |||
) | |||
import Control.Monad ( unless | |||
, void | |||
, when | |||
) | |||
import Control.Monad.Catch ( MonadThrow(..) ) | |||
import Control.Monad.Fail ( MonadFail ) | |||
import Control.Monad.IfElse ( unlessM ) | |||
import Control.Monad.IO.Class ( liftIO ) | |||
import qualified Data.ByteString as BS | |||
import Data.ByteString ( ByteString ) | |||
import Data.Traversable ( for ) | |||
import Data.Functor ( ($>) ) | |||
#if MIN_VERSION_bytestring(0,10,2) | |||
import Data.ByteString.Builder | |||
#else | |||
import Data.ByteString.Lazy.Builder | |||
#endif | |||
( Builder | |||
, byteString | |||
, toLazyByteString | |||
) | |||
import qualified Data.ByteString.Lazy as L | |||
import Data.ByteString.Unsafe ( unsafePackCStringFinalizer ) | |||
import qualified Data.ByteString.UTF8 as UTF8 | |||
import Data.Foldable ( for_ ) | |||
import Data.IORef ( IORef | |||
, modifyIORef | |||
, newIORef | |||
, readIORef | |||
) | |||
import Data.Maybe ( catMaybes ) | |||
import Data.Monoid ( (<>) | |||
, mempty | |||
) | |||
import Data.Time.Clock | |||
import Data.Time.Clock.POSIX ( getPOSIXTime | |||
, posixSecondsToUTCTime | |||
, POSIXTime | |||
) | |||
import Data.Word ( Word8 ) | |||
import Foreign.C.Error ( eEXIST | |||
, eNOENT | |||
, eNOTEMPTY | |||
, eXDEV | |||
, getErrno | |||
) | |||
import Foreign.C.Types ( CSize ) | |||
import Foreign.Marshal.Alloc ( allocaBytes ) | |||
import Foreign.Ptr ( Ptr ) | |||
import GHC.IO.Exception ( IOErrorType(..) ) | |||
import Prelude hiding ( appendFile | |||
, readFile | |||
, writeFile | |||
) | |||
import Streamly | |||
import Streamly.External.ByteString | |||
import qualified Streamly.External.ByteString.Lazy | |||
as SL | |||
import qualified Streamly.External.Posix.DirStream | |||
as SD | |||
import qualified Streamly.Data.Fold as FL | |||
import Streamly.Memory.Array | |||
import qualified Streamly.FileSystem.Handle as FH | |||
import qualified Streamly.Internal.Data.Unfold as SU | |||
import qualified Streamly.Internal.FileSystem.Handle | |||
as IFH | |||
import qualified Streamly.Internal.Memory.ArrayStream | |||
as AS | |||
import qualified Streamly.Prelude as S | |||
import qualified System.IO as SIO | |||
import System.IO.Error ( catchIOError | |||
, ioeGetErrorType | |||
) | |||
import System.Posix.FilePath | |||
import System.Posix.ByteString ( exclusive ) | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.Posix.Directory.ByteString | |||
( createDirectory | |||
, closeDirStream | |||
, getWorkingDirectory | |||
, openDirStream | |||
, removeDirectory | |||
) | |||
import System.Posix.RawFilePath.Directory.Traversals | |||
( getDirectoryContents' ) | |||
import System.Posix.Files.ByteString ( createSymbolicLink | |||
, fileAccess | |||
, fileMode | |||
, getFdStatus | |||
, groupExecuteMode | |||
, groupReadMode | |||
, groupWriteMode | |||
, otherExecuteMode | |||
, otherReadMode | |||
, otherWriteMode | |||
, ownerModes | |||
, ownerReadMode | |||
, ownerWriteMode | |||
, readSymbolicLink | |||
, removeLink | |||
, rename | |||
, setFileMode | |||
, unionFileModes | |||
) | |||
import qualified System.Posix.FilePath as FP | |||
import qualified System.Posix.Files.ByteString as PF | |||
import qualified "unix" System.Posix.IO.ByteString | |||
as SPI | |||
import qualified "unix-bytestring" System.Posix.IO.ByteString | |||
as SPB | |||
import System.Posix.FD ( openFd ) | |||
import qualified System.Posix.RawFilePath.Directory.Traversals | |||
as SPDT | |||
import qualified System.Posix.Foreign as SPDF | |||
import qualified System.Posix.Process.ByteString | |||
as SPP | |||
import System.Posix.Types ( FileMode | |||
, ProcessID | |||
, Fd | |||
, EpochTime | |||
) | |||
import System.Posix.Time | |||
------------- | |||
--[ Types ]-- | |||
------------- | |||
data FileType = Directory | |||
| RegularFile | |||
| SymbolicLink | |||
| BlockDevice | |||
| CharacterDevice | |||
| NamedPipe | |||
| Socket | |||
deriving (Eq, Show) | |||
-- | |||
-- | |||
data RecursiveErrorMode = FailEarly | |||
| CollectFailures | |||
data CopyMode = Strict -- ^ fail if any target exists | |||
| Overwrite -- ^ overwrite targets | |||
-------------------- | |||
--[ File Copying ]-- | |||
-------------------- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
copyDirRecursive :: RawFilePath -- ^ source dir | |||
-> RawFilePath -- ^ destination (parent dirs | |||
-- are not automatically created) | |||
-> CopyMode | |||
-> RecursiveErrorMode | |||
-> IO () | |||
copyDirRecursive fromp destdirp cm rm = do | |||
ce <- newIORef [] | |||
-- for performance, sanity checks are only done for the top dir | |||
throwSameFile fromp destdirp | |||
throwDestinationInSource fromp destdirp | |||
go ce fromp destdirp | |||
collectedExceptions <- readIORef ce | |||
unless (null collectedExceptions) | |||
(throwIO . RecursiveFailure $ collectedExceptions) | |||
where | |||
basename :: MonadFail m => RawFilePath -> m RawFilePath | |||
basename x = | |||
let b = takeBaseName x | |||
in if BS.null b then fail ("No base name" :: String) else pure b | |||
go :: IORef [(RecursiveFailureHint, IOException)] | |||
-> RawFilePath | |||
-> RawFilePath | |||
-> IO () | |||
go ce from destdir = do | |||
-- NOTE: order is important here, so we don't get empty directories | |||
-- on failure | |||
-- get the contents of the source dir | |||
contents <- handleIOE (ReadContentsFailed from destdir) ce [] $ do | |||
contents <- getDirsFiles from | |||
-- create the destination dir and | |||
-- only return contents if we succeed | |||
handleIOE (CreateDirFailed from destdir) ce [] $ do | |||
fmode' <- PF.fileMode <$> PF.getSymbolicLinkStatus from | |||
case cm of | |||
Strict -> createDirectory destdir fmode' | |||
Overwrite -> catchIOError (createDirectory destdir fmode') $ \e -> | |||
case ioeGetErrorType e of | |||
AlreadyExists -> setFileMode destdir fmode' | |||
_ -> ioError e | |||
return contents | |||
-- NOTE: we can't use `easyCopy` here, because we want to call `go` | |||
-- recursively to skip the top-level sanity checks | |||
-- if reading the contents and creating the destination dir worked, | |||
-- then copy the contents to the destination too | |||
for_ contents $ \f -> do | |||
ftype <- getFileType f | |||
newdest <- (destdir </>) <$> basename f | |||
case ftype of | |||
SymbolicLink -> | |||
handleIOE (RecreateSymlinkFailed f newdest) ce () | |||
$ recreateSymlink f newdest cm | |||
Directory -> go ce f newdest | |||
RegularFile -> | |||
handleIOE (CopyFileFailed f newdest) ce () $ copyFile f newdest cm | |||
_ -> return () | |||
-- helper to handle errors for both RecursiveErrorModes and return a | |||
-- default value | |||
handleIOE :: RecursiveFailureHint | |||
-> IORef [(RecursiveFailureHint, IOException)] | |||
-> a | |||
-> IO a | |||
-> IO a | |||
handleIOE hint ce def = case rm of | |||
FailEarly -> handleIOError throwIO | |||
CollectFailures -> | |||
handleIOError (\e -> modifyIORef ce ((hint, e) :) >> return def) | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
recreateSymlink :: RawFilePath -- ^ the old symlink file | |||
-> RawFilePath -- ^ destination file | |||
-> CopyMode | |||
-> IO () | |||
recreateSymlink symsource newsym cm = do | |||
throwSameFile symsource newsym | |||
sympoint <- readSymbolicLink symsource | |||
case cm of | |||
Strict -> return () | |||
Overwrite -> do | |||
writable <- do | |||
e <- doesExist newsym | |||
if e then isWritable newsym else pure False | |||
isfile <- doesFileExist newsym | |||
isdir <- doesDirectoryExist newsym | |||
when (writable && isfile) (deleteFile newsym) | |||
when (writable && isdir) (deleteDir newsym) | |||
createSymbolicLink sympoint newsym | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
copyFile :: RawFilePath -- ^ source file | |||
-> RawFilePath -- ^ destination file | |||
-> CopyMode | |||
-> IO () | |||
copyFile from to cm = do | |||
throwSameFile from to | |||
bracket | |||
(do | |||
fd <- openFd from SPI.ReadOnly [SPDF.oNofollow] Nothing | |||
handle <- SPI.fdToHandle fd | |||
pure (fd, handle) | |||
) | |||
(\(_, handle) -> SIO.hClose handle) | |||
$ \(fromFd, fH) -> do | |||
sourceFileMode <- System.Posix.Files.ByteString.fileMode | |||
<$> getFdStatus fromFd | |||
let dflags = | |||
[ SPDF.oNofollow | |||
, case cm of | |||
Strict -> SPDF.oExcl | |||
Overwrite -> SPDF.oTrunc | |||
] | |||
bracketeer | |||
(do | |||
fd <- openFd to SPI.WriteOnly dflags $ Just sourceFileMode | |||
handle <- SPI.fdToHandle fd | |||
pure (fd, handle) | |||
) | |||
(\(_, handle) -> SIO.hClose handle) | |||
(\(_, handle) -> do | |||
SIO.hClose handle | |||
case cm of | |||
-- if we created the file and copying failed, it's | |||
-- safe to clean up | |||
Strict -> deleteFile to | |||
Overwrite -> pure () | |||
) | |||
$ \(_, tH) -> do | |||
SIO.hSetBinaryMode fH True | |||
SIO.hSetBinaryMode tH True | |||
streamlyCopy (fH, tH) | |||
where | |||
streamlyCopy (fH, tH) = | |||
S.fold (FH.writeChunks tH) $ IFH.toChunksWithBufferOf (256 * 1024) fH | |||
-- | |||
-- | |||
-- | |||
easyCopy :: RawFilePath | |||
-> RawFilePath | |||
-> CopyMode | |||
-> RecursiveErrorMode | |||
-> IO () | |||
easyCopy from to cm rm = do | |||
ftype <- getFileType from | |||
case ftype of | |||
SymbolicLink -> recreateSymlink from to cm | |||
RegularFile -> copyFile from to cm | |||
Directory -> copyDirRecursive from to cm rm | |||
_ -> return () | |||
--------------------- | |||
--[ File Deletion ]-- | |||
--------------------- | |||
-- | |||
-- | |||
-- | |||
deleteFile :: RawFilePath -> IO () | |||
deleteFile = removeLink | |||
-- | |||
-- | |||
-- | |||
deleteDir :: RawFilePath -> IO () | |||
deleteDir = removeDirectory | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
deleteDirRecursive :: RawFilePath -> IO () | |||
deleteDirRecursive p = catchErrno [eNOTEMPTY, eEXIST] (deleteDir p) $ do | |||
files <- getDirsFiles p | |||
for_ files $ \file -> do | |||
ftype <- getFileType file | |||
case ftype of | |||
SymbolicLink -> deleteFile file | |||
Directory -> deleteDirRecursive file | |||
RegularFile -> deleteFile file | |||
_ -> return () | |||
removeDirectory p | |||
-- | |||
-- | |||
easyDelete :: RawFilePath -> IO () | |||
easyDelete p = do | |||
ftype <- getFileType p | |||
case ftype of | |||
SymbolicLink -> deleteFile p | |||
Directory -> deleteDirRecursive p | |||
RegularFile -> deleteFile p | |||
_ -> return () | |||
-------------------- | |||
--[ File Opening ]-- | |||
-------------------- | |||
openFile :: RawFilePath -> IO ProcessID | |||
openFile fp = SPP.forkProcess | |||
$ SPP.executeFile (UTF8.fromString "xdg-open") True [fp] Nothing | |||
executeFile :: RawFilePath -- ^ program | |||
-> [ByteString] -- ^ arguments | |||
-> IO ProcessID | |||
executeFile fp args = SPP.forkProcess $ SPP.executeFile fp True args Nothing | |||
--------------------- | |||
--[ File Creation ]-- | |||
--------------------- | |||
-- | |||
-- | |||
createRegularFile :: FileMode -> RawFilePath -> IO () | |||
createRegularFile fm destBS = bracket | |||
(SPI.openFd destBS | |||
SPI.WriteOnly | |||
(Just fm) | |||
(SPI.defaultFileFlags { exclusive = True }) | |||
) | |||
SPI.closeFd | |||
(\_ -> return ()) | |||
-- | |||
-- | |||
createDir :: FileMode -> RawFilePath -> IO () | |||
createDir fm destBS = createDirectory destBS fm | |||
-- | |||
-- | |||
createDirIfMissing :: FileMode -> RawFilePath -> IO () | |||
createDirIfMissing fm destBS = | |||
hideError AlreadyExists $ createDirectory destBS fm | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
createDirRecursive :: FileMode -> RawFilePath -> IO () | |||
createDirRecursive fm p = go p | |||
where | |||
go :: RawFilePath -> IO () | |||
go dest = do | |||
catchIOError (createDirectory dest fm) $ \e -> do | |||
errno <- getErrno | |||
case errno of | |||
en | |||
| en == eEXIST | |||
-> unlessM (doesDirectoryExist dest) (ioError e) | |||
| en == eNOENT | |||
-> go (takeDirectory $ dropTrailingPathSeparator dest) | |||
>> createDir fm dest | |||
| otherwise | |||
-> ioError e | |||
-- | |||
-- | |||
-- | |||
createSymlink :: RawFilePath -- ^ destination file | |||
-> RawFilePath -- ^ path the symlink points to | |||
-> IO () | |||
createSymlink destBS sympoint = createSymbolicLink sympoint destBS | |||
---------------------------- | |||
--[ File Renaming/Moving ]-- | |||
---------------------------- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
renameFile :: RawFilePath -> RawFilePath -> IO () | |||
renameFile fromf tof = do | |||
throwSameFile fromf tof | |||
throwFileDoesExist tof | |||
throwDirDoesExist tof | |||
rename fromf tof | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
moveFile :: RawFilePath -- ^ file to move | |||
-> RawFilePath -- ^ destination | |||
-> CopyMode | |||
-> IO () | |||
moveFile from to cm = do | |||
throwSameFile from to | |||
case cm of | |||
Strict -> catchErrno [eXDEV] (renameFile from to) $ do | |||
easyCopy from to Strict FailEarly | |||
easyDelete from | |||
Overwrite -> do | |||
ft <- getFileType from | |||
writable <- do | |||
e <- doesFileExist to | |||
if e then isWritable to else pure False | |||
case ft of | |||
RegularFile -> do | |||
exists <- doesFileExist to | |||
when (exists && writable) (deleteFile to) | |||
SymbolicLink -> do | |||
exists <- doesFileExist to | |||
when (exists && writable) (deleteFile to) | |||
Directory -> do | |||
exists <- doesDirectoryExist to | |||
when (exists && writable) (deleteDir to) | |||
_ -> return () | |||
moveFile from to Strict | |||
-------------------- | |||
--[ File Reading ]-- | |||
-------------------- | |||
-- | |||
-- | |||
-- | |||
-- | |||
readFile :: RawFilePath -> IO L.ByteString | |||
readFile path = do | |||
stream <- readFileStream path | |||
toLazyByteString <$> S.fold FL.mconcat (fmap byteString stream) | |||
-- | |||
-- | |||
readFileStream :: RawFilePath -> IO (SerialT IO ByteString) | |||
readFileStream fp = do | |||
fd <- openFd fp SPI.ReadOnly [] Nothing | |||
handle <- SPI.fdToHandle fd | |||
let stream = | |||
fmap fromArray (S.unfold (SU.finally SIO.hClose FH.readChunks) handle) | |||
pure stream | |||
-------------------- | |||
--[ File Writing ]-- | |||
-------------------- | |||
-- | |||
-- | |||
writeFile :: RawFilePath | |||
-> Maybe FileMode -- ^ if Nothing, file must exist | |||
-> ByteString | |||
-> IO () | |||
writeFile fp fmode bs = | |||
bracket (openFd fp SPI.WriteOnly [SPDF.oTrunc] fmode) (SPI.closeFd) | |||
$ \fd -> void $ SPB.fdWrite fd bs | |||
-- | |||
-- | |||
-- | |||
writeFileL :: RawFilePath | |||
-> Maybe FileMode -- ^ if Nothing, file must exist | |||
-> L.ByteString | |||
-> IO () | |||
writeFileL fp fmode lbs = do | |||
handle <- | |||
bracketOnError (openFd fp SPI.WriteOnly [SPDF.oTrunc] fmode) (SPI.closeFd) | |||
$ SPI.fdToHandle | |||
finally (streamlyCopy handle) (SIO.hClose handle) | |||
where streamlyCopy tH = S.fold (FH.writeChunks tH) $ SL.toChunks lbs | |||
-- | |||
-- | |||
appendFile :: RawFilePath -> ByteString -> IO () | |||
appendFile fp bs = | |||
bracket (openFd fp SPI.WriteOnly [SPDF.oAppend] Nothing) (SPI.closeFd) | |||
$ \fd -> void $ SPB.fdWrite fd bs | |||
----------------------- | |||
--[ File Permissions]-- | |||
----------------------- | |||
newFilePerms :: FileMode | |||
newFilePerms = | |||
ownerWriteMode | |||
`unionFileModes` ownerReadMode | |||
`unionFileModes` groupWriteMode | |||
`unionFileModes` groupReadMode | |||
`unionFileModes` otherWriteMode | |||
`unionFileModes` otherReadMode | |||
newDirPerms :: FileMode | |||
newDirPerms = | |||
ownerModes | |||
`unionFileModes` groupExecuteMode | |||
`unionFileModes` groupReadMode | |||
`unionFileModes` otherExecuteMode | |||
`unionFileModes` otherReadMode | |||
------------------- | |||
--[ File checks ]-- | |||
------------------- | |||
-- | |||
doesExist :: RawFilePath -> IO Bool | |||
doesExist bs = | |||
catchErrno | |||
[eNOENT] | |||
(do | |||
_ <- PF.getSymbolicLinkStatus bs | |||
return $ True | |||
) | |||
$ return False | |||
-- | |||
doesFileExist :: RawFilePath -> IO Bool | |||
doesFileExist bs = | |||
catchErrno | |||
[eNOENT] | |||
(do | |||
fs <- PF.getSymbolicLinkStatus bs | |||
return $ not . PF.isDirectory $ fs | |||
) | |||
$ return False | |||
-- | |||
doesDirectoryExist :: RawFilePath -> IO Bool | |||
doesDirectoryExist bs = | |||
catchErrno | |||
[eNOENT] | |||
(do | |||
fs <- PF.getSymbolicLinkStatus bs | |||
return $ PF.isDirectory fs | |||
) | |||
$ return False | |||
-- | |||
-- | |||
-- | |||
isReadable :: RawFilePath -> IO Bool | |||
isReadable bs = fileAccess bs True False False | |||
-- | |||
-- | |||
-- | |||
isWritable :: RawFilePath -> IO Bool | |||
isWritable bs = fileAccess bs False True False | |||
-- | |||
-- | |||
-- | |||
isExecutable :: RawFilePath -> IO Bool | |||
isExecutable bs = fileAccess bs False False True | |||
canOpenDirectory :: RawFilePath -> IO Bool | |||
canOpenDirectory bs = handleIOError (\_ -> return False) $ do | |||
bracket (openDirStream bs) closeDirStream (\_ -> return ()) | |||
return True | |||
------------------ | |||
--[ File times ]-- | |||
------------------ | |||
getModificationTime :: RawFilePath -> IO UTCTime | |||
getModificationTime bs = do | |||
fs <- PF.getFileStatus bs | |||
pure $ posixSecondsToUTCTime $ PF.modificationTimeHiRes fs | |||
setModificationTime :: RawFilePath -> EpochTime -> IO () | |||
setModificationTime bs t = do | |||
-- TODO: setFileTimes doesn't allow to pass NULL to utime | |||
ctime <- epochTime | |||
PF.setFileTimes bs ctime t | |||
setModificationTimeHiRes :: RawFilePath -> POSIXTime -> IO () | |||
setModificationTimeHiRes bs t = do | |||
-- TODO: setFileTimesHiRes doesn't allow to pass NULL to utimes | |||
ctime <- getPOSIXTime | |||
PF.setFileTimesHiRes bs ctime t | |||
------------------------- | |||
--[ Directory reading ]-- | |||
------------------------- | |||
-- | |||
-- | |||
-- | |||
getDirsFiles :: RawFilePath -- ^ dir to read | |||
-> IO [RawFilePath] | |||
getDirsFiles p = do | |||
contents <- getDirsFiles' p | |||
pure $ fmap (p </>) contents | |||
getDirsFiles' :: RawFilePath -- ^ dir to read | |||
-> IO [RawFilePath] | |||
getDirsFiles' fp = getDirsFilesStream fp >>= S.toList | |||
getDirsFilesStream :: (MonadCatch m, MonadAsync m, MonadMask m) | |||
=> RawFilePath | |||
-> IO (SerialT m RawFilePath) | |||
getDirsFilesStream fp = do | |||
fd <- openFd fp SPI.ReadOnly [SPDF.oNofollow] Nothing | |||
ds <- SPDT.fdOpendir fd `onException` SPI.closeFd fd | |||
pure $ fmap snd $ SD.dirContentsStream ds | |||
--------------------------- | |||
--[ FileType operations ]-- | |||
--------------------------- | |||
-- | |||
-- | |||
getFileType :: RawFilePath -> IO FileType | |||
getFileType fp = do | |||
fs <- PF.getSymbolicLinkStatus fp | |||
decide fs | |||
where | |||
decide fs | PF.isDirectory fs = return Directory | |||
| PF.isRegularFile fs = return RegularFile | |||
| PF.isSymbolicLink fs = return SymbolicLink | |||
| PF.isBlockDevice fs = return BlockDevice | |||
| PF.isCharacterDevice fs = return CharacterDevice | |||
| PF.isNamedPipe fs = return NamedPipe | |||
| PF.isSocket fs = return Socket | |||
| otherwise = ioError $ userError "No filetype?!" | |||
-------------- | |||
--[ Others ]-- | |||
-------------- | |||
-- | |||
-- | |||
canonicalizePath :: RawFilePath -> IO RawFilePath | |||
canonicalizePath = SPDT.realpath | |||
-- | |||
toAbs :: RawFilePath -> IO RawFilePath | |||
toAbs bs = do | |||
case isAbsolute bs of | |||
True -> return bs | |||
False -> do | |||
cwd <- getWorkingDirectory | |||
return $ cwd </> bs |
@@ -1,15 +0,0 @@ | |||
module System.Posix.RawFilePath.Directory where | |||
import System.Posix.ByteString.FilePath (RawFilePath) | |||
canonicalizePath :: RawFilePath -> IO RawFilePath | |||
toAbs :: RawFilePath -> IO RawFilePath | |||
doesFileExist :: RawFilePath -> IO Bool | |||
doesDirectoryExist :: RawFilePath -> IO Bool | |||
isWritable :: RawFilePath -> IO Bool | |||
canOpenDirectory :: RawFilePath -> IO Bool |
@@ -1,327 +0,0 @@ | |||
-- | |||
-- | |||
{-# LANGUAGE DeriveDataTypeable #-} | |||
{-# LANGUAGE ScopedTypeVariables #-} | |||
module System.Posix.RawFilePath.Directory.Errors | |||
( | |||
-- * Types | |||
HPathIOException(..) | |||
, RecursiveFailureHint(..) | |||
-- * Exception identifiers | |||
, isSameFile | |||
, isDestinationInSource | |||
, isRecursiveFailure | |||
, isReadContentsFailed | |||
, isCreateDirFailed | |||
, isCopyFileFailed | |||
, isRecreateSymlinkFailed | |||
-- * Path based functions | |||
, throwFileDoesExist | |||
, throwDirDoesExist | |||
, throwSameFile | |||
, sameFile | |||
, throwDestinationInSource | |||
-- * Error handling functions | |||
, catchErrno | |||
, rethrowErrnoAs | |||
, handleIOError | |||
, hideError | |||
, bracketeer | |||
, reactOnError | |||
) | |||
where | |||
import Control.Applicative | |||
( | |||
(<$>) | |||
) | |||
import Control.Exception.Safe hiding (handleIOError) | |||
import Control.Monad | |||
( | |||
forM | |||
, when | |||
) | |||
import Control.Monad.IfElse | |||
( | |||
whenM | |||
) | |||
import Data.ByteString | |||
( | |||
ByteString | |||
) | |||
import qualified Data.ByteString as BS | |||
import Data.ByteString.UTF8 | |||
( | |||
toString | |||
) | |||
import Data.Typeable | |||
( | |||
Typeable | |||
) | |||
import Foreign.C.Error | |||
( | |||
getErrno | |||
, Errno | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType | |||
) | |||
import {-# SOURCE #-} System.Posix.RawFilePath.Directory | |||
( | |||
canonicalizePath | |||
, toAbs | |||
, doesFileExist | |||
, doesDirectoryExist | |||
, isWritable | |||
, canOpenDirectory | |||
) | |||
import System.IO.Error | |||
( | |||
alreadyExistsErrorType | |||
, ioeGetErrorType | |||
, mkIOError | |||
) | |||
import System.Posix.FilePath | |||
import qualified System.Posix.Directory.ByteString as PFD | |||
import System.Posix.Files.ByteString | |||
( | |||
fileAccess | |||
, getFileStatus | |||
) | |||
import qualified System.Posix.Files.ByteString as PF | |||
data HPathIOException = SameFile ByteString ByteString | |||
| DestinationInSource ByteString ByteString | |||
| RecursiveFailure [(RecursiveFailureHint, IOException)] | |||
deriving (Eq, Show, Typeable) | |||
-- | |||
data RecursiveFailureHint = ReadContentsFailed ByteString ByteString | |||
| CreateDirFailed ByteString ByteString | |||
| CopyFileFailed ByteString ByteString | |||
| RecreateSymlinkFailed ByteString ByteString | |||
deriving (Eq, Show) | |||
instance Exception HPathIOException | |||
toConstr :: HPathIOException -> String | |||
toConstr SameFile {} = "SameFile" | |||
toConstr DestinationInSource {} = "DestinationInSource" | |||
toConstr RecursiveFailure {} = "RecursiveFailure" | |||
----------------------------- | |||
--[ Exception identifiers ]-- | |||
----------------------------- | |||
isSameFile, isDestinationInSource, isRecursiveFailure :: HPathIOException -> Bool | |||
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 | |||
isReadContentsFailed ReadContentsFailed{} = True | |||
isReadContentsFailed _ = False | |||
isCreateDirFailed CreateDirFailed{} = True | |||
isCreateDirFailed _ = False | |||
isCopyFileFailed CopyFileFailed{} = True | |||
isCopyFileFailed _ = False | |||
isRecreateSymlinkFailed RecreateSymlinkFailed{} = True | |||
isRecreateSymlinkFailed _ = False | |||
---------------------------- | |||
--[ Path based functions ]-- | |||
---------------------------- | |||
throwFileDoesExist :: RawFilePath -> IO () | |||
throwFileDoesExist bs = | |||
whenM (doesFileExist bs) | |||
(ioError . mkIOError | |||
alreadyExistsErrorType | |||
"File already exists" | |||
Nothing | |||
$ (Just (toString $ bs)) | |||
) | |||
throwDirDoesExist :: RawFilePath -> IO () | |||
throwDirDoesExist bs = | |||
whenM (doesDirectoryExist bs) | |||
(ioError . mkIOError | |||
alreadyExistsErrorType | |||
"Directory already exists" | |||
Nothing | |||
$ (Just (toString $ bs)) | |||
) | |||
throwSameFile :: RawFilePath | |||
-> RawFilePath | |||
-> IO () | |||
throwSameFile bs1 bs2 = | |||
whenM (sameFile bs1 bs2) | |||
(throwIO $ SameFile bs1 bs2) | |||
sameFile :: RawFilePath -> RawFilePath -> IO Bool | |||
sameFile fp1 fp2 = | |||
handleIOError (\_ -> return False) $ do | |||
fs1 <- getFileStatus fp1 | |||
fs2 <- getFileStatus fp2 | |||
if ((PF.deviceID fs1, PF.fileID fs1) == | |||
(PF.deviceID fs2, PF.fileID fs2)) | |||
then return True | |||
else return False | |||
throwDestinationInSource :: RawFilePath -- ^ source dir | |||
-> RawFilePath -- ^ full destination, @dirname dest@ | |||
-- must exist | |||
-> IO () | |||
throwDestinationInSource sbs dbs = do | |||
destAbs <- toAbs dbs | |||
dest' <- (\x -> maybe x (\y -> x </> y) $ basename dbs) | |||
<$> (canonicalizePath $ takeDirectory destAbs) | |||
dids <- forM (takeAllParents dest') $ \p -> do | |||
fs <- PF.getSymbolicLinkStatus p | |||
return (PF.deviceID fs, PF.fileID fs) | |||
sid <- fmap (\x -> (PF.deviceID x, PF.fileID x)) | |||
$ PF.getFileStatus sbs | |||
when (elem sid dids) | |||
(throwIO $ DestinationInSource dbs sbs) | |||
where | |||
basename x = let b = takeBaseName x | |||
in if BS.null b then Nothing else Just b | |||
-------------------------------- | |||
--[ Error handling functions ]-- | |||
-------------------------------- | |||
catchErrno :: [Errno] -- ^ errno to catch | |||
-> IO a -- ^ action to try, which can raise an IOException | |||
-> IO a -- ^ action to carry out in case of an IOException and | |||
-- if errno matches | |||
-> IO a | |||
catchErrno en a1 a2 = | |||
catchIOError a1 $ \e -> do | |||
errno <- getErrno | |||
if errno `elem` en | |||
then a2 | |||
else ioError e | |||
rethrowErrnoAs :: Exception e | |||
=> [Errno] -- ^ errno to catch | |||
-> e -- ^ rethrow as if errno matches | |||
-> IO a -- ^ action to try | |||
-> IO a | |||
rethrowErrnoAs en fmex action = catchErrno en action (throwIO fmex) | |||
handleIOError :: (IOError -> IO a) -> IO a -> IO a | |||
handleIOError = flip catchIOError | |||
hideError :: IOErrorType -> IO () -> IO () | |||
hideError err = handleIO (\e -> if err == ioeGetErrorType e then pure () else ioError e) | |||
bracketeer :: IO a -- ^ computation to run first | |||
-> (a -> IO b) -- ^ computation to run last, when | |||
-- no exception was raised | |||
-> (a -> IO b) -- ^ computation to run last, | |||
-- when an exception was raised | |||
-> (a -> IO c) -- ^ computation to run in-between | |||
-> IO c | |||
bracketeer before after afterEx thing = | |||
mask $ \restore -> do | |||
a <- before | |||
r <- restore (thing a) `onException` afterEx a | |||
_ <- after a | |||
return r | |||
reactOnError :: IO a | |||
-> [(IOErrorType, IO a)] -- ^ reaction on IO errors | |||
-> [(HPathIOException, IO a)] -- ^ reaction on HPathIOException | |||
-> IO a | |||
reactOnError a ios fmios = | |||
a `catches` [iohandler, fmiohandler] | |||
where | |||
iohandler = Handler $ | |||
\(ex :: IOException) -> | |||
foldr (\(t, a') y -> if ioeGetErrorType ex == t | |||
then a' | |||
else y) | |||
(throwIO ex) | |||
ios | |||
fmiohandler = Handler $ | |||
\(ex :: HPathIOException) -> | |||
foldr (\(t, a') y -> if toConstr ex == toConstr t | |||
then a' | |||
else y) | |||
(throwIO ex) | |||
fmios | |||
@@ -1,28 +0,0 @@ | |||
{-# 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) | |||
import System.Posix.Env.ByteString (getEnvDefault) | |||
import System.Posix.FilePath ((</>)) | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
main :: IO () | |||
main = do | |||
tmpdir <- getEnvDefault "TMPDIR" "/tmp" >>= canonicalizePath | |||
tmpBase <- mkdtemp (tmpdir </> "hpath-directory") | |||
writeIORef baseTmpDir (Just (tmpBase `BS.append` "/")) | |||
putStrLn $ ("Temporary test directory at: " ++ show tmpBase) | |||
hspecWith | |||
defaultConfig { configFormatter = Just progress } | |||
$ afterAll_ deleteBaseTmpDir | |||
$ Spec.spec |
@@ -1,2 +0,0 @@ | |||
{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --module-name=Spec #-} |
@@ -1,108 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.AppendFileSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "AppendFileSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "fileWithContent" | |||
createRegularFile' "fileWithoutContent" | |||
createSymlink' "inputFileSymL" "fileWithContent" | |||
createDir' "alreadyExistsD" | |||
createRegularFile' "noPerms" | |||
noPerms "noPerms" | |||
createDir' "noPermsD" | |||
createRegularFile' "noPermsD/inputFile" | |||
noPerms "noPermsD" | |||
writeFile' "fileWithContent" "BLKASL" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
deleteFile' "fileWithContent" | |||
deleteFile' "fileWithoutContent" | |||
deleteFile' "inputFileSymL" | |||
deleteDir' "alreadyExistsD" | |||
normalFilePerms "noPerms" | |||
deleteFile' "noPerms" | |||
normalDirPerms "noPermsD" | |||
deleteFile' "noPermsD/inputFile" | |||
deleteDir' "noPermsD" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.appendFile" $ do | |||
-- successes -- | |||
it "appendFile file with content, everything clear" $ do | |||
appendFile' "fileWithContent" "blahfaselllll" | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "BLKASLblahfaselllll" | |||
it "appendFile file with content, everything clear" $ do | |||
appendFile' "fileWithContent" "gagagaga" | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "BLKASLblahfaselllllgagagaga" | |||
it "appendFile file with content, everything clear" $ do | |||
appendFile' "fileWithContent" "" | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "BLKASLblahfaselllllgagagaga" | |||
it "appendFile file without content, everything clear" $ do | |||
appendFile' "fileWithoutContent" "blahfaselllll" | |||
out <- readFile' "fileWithoutContent" | |||
out `shouldBe` "blahfaselllll" | |||
it "appendFile, everything clear" $ do | |||
appendFile' "fileWithoutContent" "gagagaga" | |||
out <- readFile' "fileWithoutContent" | |||
out `shouldBe` "blahfaselllllgagagaga" | |||
it "appendFile symlink, everything clear" $ do | |||
appendFile' "inputFileSymL" "blahfaselllll" | |||
out <- readFile' "inputFileSymL" | |||
out `shouldBe` "BLKASLblahfaselllllgagagagablahfaselllll" | |||
it "appendFile symlink, everything clear" $ do | |||
appendFile' "inputFileSymL" "gagagaga" | |||
out <- readFile' "inputFileSymL" | |||
out `shouldBe` "BLKASLblahfaselllllgagagagablahfaselllllgagagaga" | |||
-- posix failures -- | |||
it "appendFile to dir, inappropriate type" $ do | |||
appendFile' "alreadyExistsD" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == InappropriateType) | |||
it "appendFile, no permissions to file" $ do | |||
appendFile' "noPerms" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == PermissionDenied) | |||
it "appendFile, no permissions to file" $ do | |||
appendFile' "noPermsD/inputFile" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == PermissionDenied) | |||
it "appendFile, file does not exist" $ do | |||
appendFile' "gaga" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == NoSuchThing) |
@@ -1,78 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CanonicalizePathSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CanonicalizePathSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "file" | |||
createDir' "dir" | |||
createSymlink' "dirSym" "dir/" | |||
createSymlink' "brokenSym" "nothing" | |||
createSymlink' "fileSym" "file" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
deleteFile' "file" | |||
deleteDir' "dir" | |||
deleteFile' "dirSym" | |||
deleteFile' "brokenSym" | |||
deleteFile' "fileSym" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.canonicalizePath" $ do | |||
-- successes -- | |||
it "canonicalizePath, all fine" $ do | |||
path <- withTmpDir "file" return | |||
canonicalizePath' "file" | |||
`shouldReturn` path | |||
it "canonicalizePath, all fine" $ do | |||
path <- withTmpDir "dir" return | |||
canonicalizePath' "dir" | |||
`shouldReturn` path | |||
it "canonicalizePath, all fine" $ do | |||
path <- withTmpDir "file" return | |||
canonicalizePath' "fileSym" | |||
`shouldReturn` path | |||
it "canonicalizePath, all fine" $ do | |||
path <- withTmpDir "dir" return | |||
canonicalizePath' "dirSym" | |||
`shouldReturn` path | |||
-- posix failures -- | |||
it "canonicalizePath, broken symlink" $ | |||
canonicalizePath' "brokenSym" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "canonicalizePath, file does not exist" $ | |||
canonicalizePath' "nothingBlah" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
@@ -1,248 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CopyDirRecursiveCollectFailuresSpec where | |||
import Test.Hspec | |||
import Data.List (sort) | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import System.Exit | |||
import System.Process | |||
import Utils | |||
import qualified Data.ByteString as BS | |||
import Data.ByteString.UTF8 (toString) | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CopyDirRecursiveCollectFailuresSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "alreadyExists" | |||
createRegularFile' "wrongInput" | |||
createSymlink' "wrongInputSymL" "inputDir/" | |||
createDir' "alreadyExistsD" | |||
createDir' "noPerms" | |||
createDir' "noWritePerm" | |||
createDir' "inputDir" | |||
createDir' "inputDir/bar" | |||
createDir' "inputDir/foo" | |||
createRegularFile' "inputDir/foo/inputFile1" | |||
createRegularFile' "inputDir/inputFile2" | |||
createRegularFile' "inputDir/bar/inputFile3" | |||
writeFile' "inputDir/foo/inputFile1" "SDAADSdsada" | |||
writeFile' "inputDir/inputFile2" "Blahfaselgagaga" | |||
writeFile' "inputDir/bar/inputFile3" | |||
"fdfdssdffsd3223sasdasdasdadasasddasdasdasasd4" | |||
createDir' "inputDir1" | |||
createDir' "inputDir1/foo2" | |||
createDir' "inputDir1/foo2/foo3" | |||
createDir' "inputDir1/foo2/foo4" | |||
createRegularFile' "inputDir1/foo2/inputFile1" | |||
createRegularFile' "inputDir1/foo2/inputFile2" | |||
createRegularFile' "inputDir1/foo2/inputFile3" | |||
createRegularFile' "inputDir1/foo2/foo4/inputFile4" | |||
createRegularFile' "inputDir1/foo2/foo4/inputFile6" | |||
createRegularFile' "inputDir1/foo2/foo3/inputFile5" | |||
noPerms "inputDir1/foo2/foo3" | |||
createDir' "outputDir1" | |||
createDir' "outputDir1/foo2" | |||
createDir' "outputDir1/foo2/foo4" | |||
createDir' "outputDir1/foo2/foo4/inputFile4" | |||
createRegularFile' "outputDir1/foo2/foo4/inputFile6" | |||
noPerms "outputDir1/foo2/foo4/inputFile4" | |||
noPerms "outputDir1/foo2/foo4" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerm" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerm" | |||
normalDirPerms "inputDir1/foo2/foo3" | |||
deleteFile' "inputDir1/foo2/foo4/inputFile4" | |||
deleteFile' "inputDir1/foo2/foo4/inputFile6" | |||
deleteFile' "inputDir1/foo2/inputFile1" | |||
deleteFile' "inputDir1/foo2/inputFile2" | |||
deleteFile' "inputDir1/foo2/inputFile3" | |||
deleteFile' "inputDir1/foo2/foo3/inputFile5" | |||
deleteDir' "inputDir1/foo2/foo3" | |||
deleteDir' "inputDir1/foo2/foo4" | |||
deleteDir' "inputDir1/foo2" | |||
deleteDir' "inputDir1" | |||
normalDirPerms "outputDir1/foo2/foo4" | |||
normalDirPerms "outputDir1/foo2/foo4/inputFile4" | |||
deleteFile' "outputDir1/foo2/foo4/inputFile6" | |||
deleteDir' "outputDir1/foo2/foo4/inputFile4" | |||
deleteDir' "outputDir1/foo2/foo4" | |||
deleteDir' "outputDir1/foo2" | |||
deleteDir' "outputDir1" | |||
deleteFile' "alreadyExists" | |||
deleteFile' "wrongInput" | |||
deleteFile' "wrongInputSymL" | |||
deleteDir' "alreadyExistsD" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerm" | |||
deleteFile' "inputDir/foo/inputFile1" | |||
deleteFile' "inputDir/inputFile2" | |||
deleteFile' "inputDir/bar/inputFile3" | |||
deleteDir' "inputDir/foo" | |||
deleteDir' "inputDir/bar" | |||
deleteDir' "inputDir" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.copyDirRecursive" $ do | |||
-- successes -- | |||
it "copyDirRecursive (Strict, CollectFailures), all fine and compare" $ do | |||
tmpDir' <- getRawTmpDir | |||
copyDirRecursive' "inputDir" | |||
"outputDir" | |||
Strict | |||
CollectFailures | |||
(system $ "diff -r " | |||
++ toString tmpDir' ++ "inputDir" ++ " " | |||
++ toString tmpDir' ++ "outputDir" | |||
++ " >/dev/null") | |||
`shouldReturn` ExitSuccess | |||
removeDirIfExists "outputDir" | |||
-- posix failures -- | |||
it "copyDirRecursive (Strict, CollectFailures), source directory does not exist" $ | |||
copyDirRecursive' "doesNotExist" | |||
"outputDir" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "copyDirRecursive (Strict, CollectFailures), cannot open source dir" $ | |||
copyDirRecursive' "noPerms/inputDir" | |||
"foo" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
-- custom failures | |||
it "copyDirRecursive (Overwrite, CollectFailures), various failures" $ do | |||
copyDirRecursive' "inputDir1/foo2" | |||
"outputDir1/foo2" | |||
Overwrite | |||
CollectFailures | |||
`shouldThrow` | |||
(\(RecursiveFailure ex@[_, _]) -> | |||
any (\(h, e) -> ioeGetErrorType e == InappropriateType | |||
&& isCopyFileFailed h) ex && | |||
any (\(h, e) -> ioeGetErrorType e == PermissionDenied | |||
&& isReadContentsFailed h) ex) | |||
normalDirPerms "outputDir1/foo2/foo4" | |||
normalDirPerms "outputDir1/foo2/foo4/inputFile4" | |||
c <- allDirectoryContents' "outputDir1" | |||
tmpDir' <- getRawTmpDir | |||
let shouldC = (fmap (\x -> tmpDir' `BS.append` x) | |||
["outputDir1" | |||
,"outputDir1/foo2" | |||
,"outputDir1/foo2/inputFile1" | |||
,"outputDir1/foo2/inputFile2" | |||
,"outputDir1/foo2/inputFile3" | |||
,"outputDir1/foo2/foo4" | |||
,"outputDir1/foo2/foo4/inputFile6" | |||
,"outputDir1/foo2/foo4/inputFile4"]) | |||
deleteFile' "outputDir1/foo2/inputFile1" | |||
deleteFile' "outputDir1/foo2/inputFile2" | |||
deleteFile' "outputDir1/foo2/inputFile3" | |||
sort c `shouldBe` sort shouldC | |||
it "copyDirRecursive (Strict, CollectFailures), no write permission on output dir" $ | |||
copyDirRecursive' "inputDir" | |||
"noWritePerm/foo" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
(\(RecursiveFailure [(CreateDirFailed{}, e)]) -> ioeGetErrorType e == PermissionDenied) | |||
it "copyDirRecursive (Strict, CollectFailures), cannot open output dir" $ | |||
copyDirRecursive' "inputDir" | |||
"noPerms/foo" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
isRecursiveFailure | |||
it "copyDirRecursive (Strict, CollectFailures), destination dir already exists" $ | |||
copyDirRecursive' "inputDir" | |||
"alreadyExistsD" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
(\(RecursiveFailure [(CreateDirFailed{}, e)]) -> ioeGetErrorType e == AlreadyExists) | |||
it "copyDirRecursive (Strict, CollectFailures), destination already exists and is a file" $ | |||
copyDirRecursive' "inputDir" | |||
"alreadyExists" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
isRecursiveFailure | |||
it "copyDirRecursive (Strict, CollectFailures), wrong input (regular file)" $ | |||
copyDirRecursive' "wrongInput" | |||
"outputDir" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
(\(RecursiveFailure [(ReadContentsFailed{}, e)]) -> ioeGetErrorType e == InappropriateType) | |||
it "copyDirRecursive (Strict, CollectFailures), wrong input (symlink to directory)" $ | |||
copyDirRecursive' "wrongInputSymL" | |||
"outputDir" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
(\(RecursiveFailure [(ReadContentsFailed{}, e)]) -> ioeGetErrorType e == InvalidArgument) | |||
it "copyDirRecursive (Strict, CollectFailures), destination in source" $ | |||
copyDirRecursive' "inputDir" | |||
"inputDir/foo" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
isDestinationInSource | |||
it "copyDirRecursive (Strict, CollectFailures), destination and source same directory" $ | |||
copyDirRecursive' "inputDir" | |||
"inputDir" | |||
Strict | |||
CollectFailures | |||
`shouldThrow` | |||
isSameFile | |||
@@ -1,205 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CopyDirRecursiveOverwriteSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import System.Exit | |||
import System.Process | |||
import Utils | |||
import Data.ByteString.UTF8 (toString) | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CopyDirRecursiveOverwriteSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "alreadyExists" | |||
createRegularFile' "wrongInput" | |||
createSymlink' "wrongInputSymL" "inputDir/" | |||
createDir' "noPerms" | |||
createDir' "noWritePerm" | |||
createDir' "inputDir" | |||
createDir' "inputDir/bar" | |||
createDir' "inputDir/foo" | |||
createRegularFile' "inputDir/foo/inputFile1" | |||
createRegularFile' "inputDir/inputFile2" | |||
createRegularFile' "inputDir/bar/inputFile3" | |||
writeFile' "inputDir/foo/inputFile1" "SDAADSdsada" | |||
writeFile' "inputDir/inputFile2" "Blahfaselgagaga" | |||
writeFile' "inputDir/bar/inputFile3" | |||
"fdfdssdffsd3223sasdasdasdadasasddasdasdasasd4" | |||
createDir' "alreadyExistsD" | |||
createDir' "alreadyExistsD/bar" | |||
createDir' "alreadyExistsD/foo" | |||
createRegularFile' "alreadyExistsD/foo/inputFile1" | |||
createRegularFile' "alreadyExistsD/inputFile2" | |||
createRegularFile' "alreadyExistsD/bar/inputFile3" | |||
writeFile' "alreadyExistsD/foo/inputFile1" "DAAsada" | |||
writeFile' "alreadyExistsD/inputFile2" "ahfaagaga" | |||
writeFile' "alreadyExistsD/bar/inputFile3" | |||
"f3223sasdasdaasdasdasasd4" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerm" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerm" | |||
deleteFile' "alreadyExists" | |||
deleteFile' "wrongInput" | |||
deleteFile' "wrongInputSymL" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerm" | |||
deleteFile' "inputDir/foo/inputFile1" | |||
deleteFile' "inputDir/inputFile2" | |||
deleteFile' "inputDir/bar/inputFile3" | |||
deleteDir' "inputDir/foo" | |||
deleteDir' "inputDir/bar" | |||
deleteDir' "inputDir" | |||
deleteFile' "alreadyExistsD/foo/inputFile1" | |||
deleteFile' "alreadyExistsD/inputFile2" | |||
deleteFile' "alreadyExistsD/bar/inputFile3" | |||
deleteDir' "alreadyExistsD/foo" | |||
deleteDir' "alreadyExistsD/bar" | |||
deleteDir' "alreadyExistsD" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.copyDirRecursive" $ do | |||
-- successes -- | |||
it "copyDirRecursive (Overwrite, FailEarly), all fine" $ do | |||
copyDirRecursive' "inputDir" | |||
"outputDir" | |||
Overwrite | |||
FailEarly | |||
removeDirIfExists "outputDir" | |||
it "copyDirRecursive (Overwrite, FailEarly), all fine and compare" $ do | |||
tmpDir' <- getRawTmpDir | |||
copyDirRecursive' "inputDir" | |||
"outputDir" | |||
Overwrite | |||
FailEarly | |||
(system $ "diff -r " | |||
++ toString tmpDir' ++ "inputDir" ++ " " | |||
++ toString tmpDir' ++ "outputDir" | |||
++ " >/dev/null") | |||
`shouldReturn` ExitSuccess | |||
removeDirIfExists "outputDir" | |||
it "copyDirRecursive (Overwrite, FailEarly), destination dir already exists" $ do | |||
tmpDir' <- getRawTmpDir | |||
(system $ "diff -r " | |||
++ toString tmpDir' ++ "inputDir" ++ " " | |||
++ toString tmpDir' ++ "alreadyExistsD" | |||
++ " >/dev/null") | |||
`shouldReturn` (ExitFailure 1) | |||
copyDirRecursive' "inputDir" | |||
"alreadyExistsD" | |||
Overwrite | |||
FailEarly | |||
(system $ "diff -r " | |||
++ toString tmpDir' ++ "inputDir" ++ " " | |||
++ toString tmpDir' ++ "alreadyExistsD" | |||
++ " >/dev/null") | |||
`shouldReturn` ExitSuccess | |||
removeDirIfExists "outputDir" | |||
-- posix failures -- | |||
it "copyDirRecursive, source directory does not exist" $ | |||
copyDirRecursive' "doesNotExist" | |||
"outputDir" | |||
Overwrite | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "copyDirRecursive, no write permission on output dir" $ | |||
copyDirRecursive' "inputDir" | |||
"noWritePerm/foo" | |||
Overwrite | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyDirRecursive, cannot open output dir" $ | |||
copyDirRecursive' "inputDir" | |||
"noPerms/foo" | |||
Overwrite | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyDirRecursive, cannot open source dir" $ | |||
copyDirRecursive' "noPerms/inputDir" | |||
"foo" | |||
Overwrite | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyDirRecursive, destination already exists and is a file" $ | |||
copyDirRecursive' "inputDir" | |||
"alreadyExists" | |||
Overwrite | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "copyDirRecursive, wrong input (regular file)" $ | |||
copyDirRecursive' "wrongInput" | |||
"outputDir" | |||
Overwrite | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "copyDirRecursive, wrong input (symlink to directory)" $ | |||
copyDirRecursive' "wrongInputSymL" | |||
"outputDir" | |||
Overwrite | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
-- custom failures | |||
it "copyDirRecursive (Overwrite, FailEarly), destination in source" $ | |||
copyDirRecursive' "inputDir" | |||
"inputDir/foo" | |||
Overwrite | |||
FailEarly | |||
`shouldThrow` | |||
isDestinationInSource | |||
it "copyDirRecursive (Overwrite, FailEarly), destination and source same directory" $ | |||
copyDirRecursive' "inputDir" | |||
"inputDir" | |||
Overwrite | |||
FailEarly | |||
`shouldThrow` | |||
isSameFile |
@@ -1,181 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CopyDirRecursiveSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import System.Exit | |||
import System.Process | |||
import Utils | |||
import Data.ByteString.UTF8 (toString) | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CopyDirRecursiveSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "alreadyExists" | |||
createRegularFile' "wrongInput" | |||
createSymlink' "wrongInputSymL" "inputDir/" | |||
createDir' "alreadyExistsD" | |||
createDir' "noPerms" | |||
createDir' "noWritePerm" | |||
createDir' "inputDir" | |||
createDir' "inputDir/bar" | |||
createDir' "inputDir/foo" | |||
createRegularFile' "inputDir/foo/inputFile1" | |||
createRegularFile' "inputDir/inputFile2" | |||
createRegularFile' "inputDir/bar/inputFile3" | |||
writeFile' "inputDir/foo/inputFile1" "SDAADSdsada" | |||
writeFile' "inputDir/inputFile2" "Blahfaselgagaga" | |||
writeFile' "inputDir/bar/inputFile3" | |||
"fdfdssdffsd3223sasdasdasdadasasddasdasdasasd4" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerm" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerm" | |||
deleteFile' "alreadyExists" | |||
deleteFile' "wrongInput" | |||
deleteFile' "wrongInputSymL" | |||
deleteDir' "alreadyExistsD" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerm" | |||
deleteFile' "inputDir/foo/inputFile1" | |||
deleteFile' "inputDir/inputFile2" | |||
deleteFile' "inputDir/bar/inputFile3" | |||
deleteDir' "inputDir/foo" | |||
deleteDir' "inputDir/bar" | |||
deleteDir' "inputDir" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.copyDirRecursive" $ do | |||
-- successes -- | |||
it "copyDirRecursive (Strict, FailEarly), all fine" $ do | |||
copyDirRecursive' "inputDir" | |||
"outputDir" | |||
Strict | |||
FailEarly | |||
removeDirIfExists "outputDir" | |||
it "copyDirRecursive (Strict, FailEarly), all fine and compare" $ do | |||
tmpDir' <- getRawTmpDir | |||
copyDirRecursive' "inputDir" | |||
"outputDir" | |||
Strict | |||
FailEarly | |||
(system $ "diff -r " | |||
++ toString tmpDir' ++ "inputDir" ++ " " | |||
++ toString tmpDir' ++ "outputDir" | |||
++ " >/dev/null") | |||
`shouldReturn` ExitSuccess | |||
removeDirIfExists "outputDir" | |||
-- posix failures -- | |||
it "copyDirRecursive (Strict, FailEarly), source directory does not exist" $ | |||
copyDirRecursive' "doesNotExist" | |||
"outputDir" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "copyDirRecursive (Strict, FailEarly), no write permission on output dir" $ | |||
copyDirRecursive' "inputDir" | |||
"noWritePerm/foo" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyDirRecursive (Strict, FailEarly), cannot open output dir" $ | |||
copyDirRecursive' "inputDir" | |||
"noPerms/foo" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyDirRecursive (Strict, FailEarly), cannot open source dir" $ | |||
copyDirRecursive' "noPerms/inputDir" | |||
"foo" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyDirRecursive (Strict, FailEarly), destination dir already exists" $ | |||
copyDirRecursive' "inputDir" | |||
"alreadyExistsD" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "copyDirRecursive (Strict, FailEarly), destination already exists and is a file" $ | |||
copyDirRecursive' "inputDir" | |||
"alreadyExists" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "copyDirRecursive (Strict, FailEarly), wrong input (regular file)" $ | |||
copyDirRecursive' "wrongInput" | |||
"outputDir" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "copyDirRecursive (Strict, FailEarly), wrong input (symlink to directory)" $ | |||
copyDirRecursive' "wrongInputSymL" | |||
"outputDir" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
-- custom failures | |||
it "copyDirRecursive (Strict, FailEarly), destination in source" $ | |||
copyDirRecursive' "inputDir" | |||
"inputDir/foo" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
isDestinationInSource | |||
it "copyDirRecursive (Strict, FailEarly), destination and source same directory" $ | |||
copyDirRecursive' "inputDir" | |||
"inputDir" | |||
Strict | |||
FailEarly | |||
`shouldThrow` | |||
isSameFile | |||
@@ -1,148 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CopyFileOverwriteSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import System.Exit | |||
import System.Process | |||
import Utils | |||
import Data.ByteString.UTF8 (toString) | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CopyFileOverwriteSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "inputFile" | |||
createRegularFile' "alreadyExists" | |||
createSymlink' "inputFileSymL" "inputFile" | |||
createDir' "alreadyExistsD" | |||
createDir' "noPerms" | |||
createRegularFile' "noPerms/inputFile" | |||
createDir' "outputDirNoWrite" | |||
createDir' "wrongInput" | |||
noPerms "noPerms" | |||
noWritableDirPerms "outputDirNoWrite" | |||
writeFile' "inputFile" "Blahfaselgagaga" | |||
writeFile' "alreadyExists" "dsaldsalkaklsdlkasksdadasl" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "outputDirNoWrite" | |||
deleteFile' "noPerms/inputFile" | |||
deleteFile' "inputFile" | |||
deleteFile' "alreadyExists" | |||
deleteFile' "inputFileSymL" | |||
deleteDir' "alreadyExistsD" | |||
deleteDir' "noPerms" | |||
deleteDir' "outputDirNoWrite" | |||
deleteDir' "wrongInput" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.copyFile" $ do | |||
-- successes -- | |||
it "copyFile (Overwrite), everything clear" $ do | |||
copyFile' "inputFile" | |||
"outputFile" | |||
Overwrite | |||
removeFileIfExists "outputFile" | |||
it "copyFile (Overwrite), output file already exists, all clear" $ do | |||
tmpDir' <- getRawTmpDir | |||
copyFile' "alreadyExists" "alreadyExists.bak" Strict | |||
copyFile' "inputFile" "alreadyExists" Overwrite | |||
(system $ "cmp -s " ++ toString tmpDir' ++ "inputFile" ++ " " | |||
++ toString tmpDir' ++ "alreadyExists") | |||
`shouldReturn` ExitSuccess | |||
removeFileIfExists "alreadyExists" | |||
copyFile' "alreadyExists.bak" "alreadyExists" Strict | |||
removeFileIfExists "alreadyExists.bak" | |||
it "copyFile (Overwrite), and compare" $ do | |||
tmpDir' <- getRawTmpDir | |||
copyFile' "inputFile" | |||
"outputFile" | |||
Overwrite | |||
(system $ "cmp -s " ++ toString tmpDir' ++ "inputFile" ++ " " | |||
++ toString tmpDir' ++ "outputFile") | |||
`shouldReturn` ExitSuccess | |||
removeFileIfExists "outputFile" | |||
-- posix failures -- | |||
it "copyFile (Overwrite), input file does not exist" $ | |||
copyFile' "noSuchFile" | |||
"outputFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "copyFile (Overwrite), no permission to write to output directory" $ | |||
copyFile' "inputFile" | |||
"outputDirNoWrite/outputFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyFile (Overwrite), cannot open output directory" $ | |||
copyFile' "inputFile" | |||
"noPerms/outputFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyFile (Overwrite), cannot open source directory" $ | |||
copyFile' "noPerms/inputFile" | |||
"outputFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyFile (Overwrite), wrong input type (symlink)" $ | |||
copyFile' "inputFileSymL" | |||
"outputFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
it "copyFile (Overwrite), wrong input type (directory)" $ | |||
copyFile' "wrongInput" | |||
"outputFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "copyFile (Overwrite), output file already exists and is a dir" $ | |||
copyFile' "inputFile" | |||
"alreadyExistsD" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
-- custom failures -- | |||
it "copyFile (Overwrite), output and input are same file" $ | |||
copyFile' "inputFile" | |||
"inputFile" | |||
Overwrite | |||
`shouldThrow` isSameFile |
@@ -1,143 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CopyFileSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import System.Exit | |||
import System.Process | |||
import Utils | |||
import Data.ByteString.UTF8 (toString) | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CopyFileSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "inputFile" | |||
createRegularFile' "alreadyExists" | |||
createSymlink' "inputFileSymL" "inputFile" | |||
createDir' "alreadyExistsD" | |||
createDir' "noPerms" | |||
createRegularFile' "noPerms/inputFile" | |||
createDir' "outputDirNoWrite" | |||
createDir' "wrongInput" | |||
noPerms "noPerms" | |||
noWritableDirPerms "outputDirNoWrite" | |||
writeFile' "inputFile" "Blahfaselgagaga" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "outputDirNoWrite" | |||
deleteFile' "noPerms/inputFile" | |||
deleteFile' "inputFile" | |||
deleteFile' "alreadyExists" | |||
deleteFile' "inputFileSymL" | |||
deleteDir' "alreadyExistsD" | |||
deleteDir' "noPerms" | |||
deleteDir' "outputDirNoWrite" | |||
deleteDir' "wrongInput" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.copyFile" $ do | |||
-- successes -- | |||
it "copyFile (Strict), everything clear" $ do | |||
copyFile' "inputFile" | |||
"outputFile" | |||
Strict | |||
removeFileIfExists "outputFile" | |||
it "copyFile (Strict), and compare" $ do | |||
tmpDir' <- getRawTmpDir | |||
copyFile' "inputFile" | |||
"outputFile" | |||
Strict | |||
(system $ "cmp -s " ++ toString tmpDir' ++ "inputFile" ++ " " | |||
++ toString tmpDir' ++ "outputFile") | |||
`shouldReturn` ExitSuccess | |||
removeFileIfExists "outputFile" | |||
-- posix failures -- | |||
it "copyFile (Strict), input file does not exist" $ | |||
copyFile' "noSuchFile" | |||
"outputFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "copyFile (Strict), no permission to write to output directory" $ | |||
copyFile' "inputFile" | |||
"outputDirNoWrite/outputFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyFile (Strict), cannot open output directory" $ | |||
copyFile' "inputFile" | |||
"noPerms/outputFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyFile (Strict), cannot open source directory" $ | |||
copyFile' "noPerms/inputFile" | |||
"outputFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "copyFile (Strict), wrong input type (symlink)" $ | |||
copyFile' "inputFileSymL" | |||
"outputFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
it "copyFile (Strict), wrong input type (directory)" $ | |||
copyFile' "wrongInput" | |||
"outputFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "copyFile (Strict), output file already exists" $ | |||
copyFile' "inputFile" | |||
"alreadyExists" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "copyFile (Strict), output file already exists and is a dir" $ | |||
copyFile' "inputFile" | |||
"alreadyExistsD" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
-- custom failures -- | |||
it "copyFile (Strict), output and input are same file" $ | |||
copyFile' "inputFile" | |||
"inputFile" | |||
Strict | |||
`shouldThrow` | |||
isSameFile |
@@ -1,69 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CreateDirIfMissingSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CreateDirIfMissingSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createDir' "alreadyExists" | |||
createDir' "noPerms" | |||
createDir' "noWritePerms" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerms" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerms" | |||
deleteDir' "alreadyExists" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerms" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.CreateDirIfMissing" $ do | |||
-- successes -- | |||
it "createDirIfMissing, all fine" $ do | |||
createDirIfMissing' "newDir" | |||
removeDirIfExists "newDir" | |||
it "createDirIfMissing, destination directory already exists" $ | |||
createDirIfMissing' "alreadyExists" | |||
-- posix failures -- | |||
it "createDirIfMissing, parent directories do not exist" $ | |||
createDirIfMissing' "some/thing/dada" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "createDirIfMissing, can't write to output directory" $ | |||
createDirIfMissing' "noWritePerms/newDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "createDirIfMissing, can't open output directory" $ | |||
createDirIfMissing' "noPerms/newDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) |
@@ -1,83 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CreateDirRecursiveSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CreateDirRecursiveSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createDir' "alreadyExists" | |||
createRegularFile' "alreadyExistsF" | |||
createDir' "noPerms" | |||
createDir' "noWritePerms" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerms" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerms" | |||
deleteDir' "alreadyExists" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerms" | |||
deleteFile' "alreadyExistsF" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.createDirRecursive" $ do | |||
-- successes -- | |||
it "createDirRecursive, all fine" $ do | |||
createDirRecursive' "newDir" | |||
deleteDir' "newDir" | |||
it "createDirRecursive with trailing path separator, all fine" $ do | |||
createDirRecursive' "newDir/foo/" | |||
deleteDir' "newDir/foo" | |||
deleteDir' "newDir" | |||
it "createDirRecursive, parent directories do not exist" $ do | |||
createDirRecursive' "some/thing/dada" | |||
deleteDir' "some/thing/dada" | |||
deleteDir' "some/thing" | |||
deleteDir' "some" | |||
it "createDirRecursive, destination directory already exists" $ | |||
createDirRecursive' "alreadyExists" | |||
-- posix failures -- | |||
it "createDirRecursive, destination already exists and is a file" $ | |||
createDirRecursive' "alreadyExistsF" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "createDirRecursive, can't write to output directory" $ | |||
createDirRecursive' "noWritePerms/newDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "createDirRecursive, can't open output directory" $ | |||
createDirRecursive' "noPerms/newDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
@@ -1,72 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CreateDirSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CreateDirSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createDir' "alreadyExists" | |||
createDir' "noPerms" | |||
createDir' "noWritePerms" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerms" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerms" | |||
deleteDir' "alreadyExists" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerms" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.createDir" $ do | |||
-- successes -- | |||
it "createDir, all fine" $ do | |||
createDir' "newDir" | |||
removeDirIfExists "newDir" | |||
-- posix failures -- | |||
it "createDir, parent directories do not exist" $ | |||
createDir' "some/thing/dada" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "createDir, can't write to output directory" $ | |||
createDir' "noWritePerms/newDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "createDir, can't open output directory" $ | |||
createDir' "noPerms/newDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "createDir, destination directory already exists" $ | |||
createDir' "alreadyExists" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
@@ -1,70 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CreateRegularFileSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CreateRegularFileSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "alreadyExists" | |||
createDir' "noPerms" | |||
createDir' "noWritePerms" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerms" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerms" | |||
deleteFile' "alreadyExists" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerms" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.createRegularFile" $ do | |||
-- successes -- | |||
it "createRegularFile, all fine" $ do | |||
createRegularFile' "newDir" | |||
removeFileIfExists "newDir" | |||
-- posix failures -- | |||
it "createRegularFile, parent directories do not exist" $ | |||
createRegularFile' "some/thing/dada" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "createRegularFile, can't write to destination directory" $ | |||
createRegularFile' "noWritePerms/newDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "createRegularFile, can't write to destination directory" $ | |||
createRegularFile' "noPerms/newDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "createRegularFile, destination file already exists" $ | |||
createRegularFile' "alreadyExists" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
@@ -1,71 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.CreateSymlinkSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "CreateSymlinkSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "alreadyExists" | |||
createDir' "noPerms" | |||
createDir' "noWritePerms" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerms" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerms" | |||
deleteFile' "alreadyExists" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerms" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.createSymlink" $ do | |||
-- successes -- | |||
it "createSymlink, all fine" $ do | |||
createSymlink' "newSymL" "alreadyExists/" | |||
removeFileIfExists "newSymL" | |||
-- posix failures -- | |||
it "createSymlink, parent directories do not exist" $ | |||
createSymlink' "some/thing/dada" "lala" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "createSymlink, can't write to destination directory" $ | |||
createSymlink' "noWritePerms/newDir" "lala" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "createSymlink, can't write to destination directory" $ | |||
createSymlink' "noPerms/newDir" "lala" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "createSymlink, destination file already exists" $ | |||
createSymlink' "alreadyExists" "lala" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
@@ -1,116 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.DeleteDirRecursiveSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import System.Posix.Files.ByteString | |||
( | |||
getSymbolicLinkStatus | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "DeleteDirRecursiveSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "file" | |||
createDir' "dir" | |||
createRegularFile' "dir/.keep" | |||
createSymlink' "dirSym" "dir/" | |||
createDir' "noPerms" | |||
createRegularFile' "noPerms/.keep" | |||
createDir' "noWritable" | |||
createRegularFile' "noWritable/.keep" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
deleteFile' "file" | |||
deleteFile' "dir/.keep" | |||
deleteDir' "dir" | |||
deleteFile' "dirSym" | |||
deleteFile' "noPerms/.keep" | |||
deleteDir' "noPerms" | |||
deleteFile' "noWritable/.keep" | |||
deleteDir' "noWritable" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.deleteDirRecursive" $ do | |||
-- successes -- | |||
it "deleteDirRecursive, empty directory, all fine" $ do | |||
createDir' "testDir" | |||
deleteDirRecursive' "testDir" | |||
getSymbolicLinkStatus "testDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "deleteDirRecursive, empty directory with null permissions, all fine" $ do | |||
createDir' "noPerms/testDir" | |||
noPerms "noPerms/testDir" | |||
deleteDirRecursive' "noPerms/testDir" | |||
it "deleteDirRecursive, non-empty directory, all fine" $ do | |||
createDir' "nonEmpty" | |||
createDir' "nonEmpty/dir1" | |||
createDir' "nonEmpty/dir2" | |||
createDir' "nonEmpty/dir2/dir3" | |||
createRegularFile' "nonEmpty/file1" | |||
createRegularFile' "nonEmpty/dir1/file2" | |||
deleteDirRecursive' "nonEmpty" | |||
getSymbolicLinkStatus "nonEmpty" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
-- posix failures -- | |||
it "deleteDirRecursive, can't open parent directory" $ do | |||
createDir' "noPerms/foo" | |||
noPerms "noPerms" | |||
(deleteDirRecursive' "noPerms/foo") | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
normalDirPerms "noPerms" | |||
deleteDir' "noPerms/foo" | |||
it "deleteDirRecursive, can't write to parent directory" $ do | |||
createDir' "noWritable/foo" | |||
noWritableDirPerms "noWritable" | |||
(deleteDirRecursive' "noWritable/foo") | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
normalDirPerms "noWritable" | |||
deleteDir' "noWritable/foo" | |||
it "deleteDirRecursive, wrong file type (symlink to directory)" $ | |||
deleteDirRecursive' "dirSym" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "deleteDirRecursive, wrong file type (regular file)" $ | |||
deleteDirRecursive' "file" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "deleteDirRecursive, directory does not exist" $ | |||
deleteDirRecursive' "doesNotExist" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
@@ -1,114 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.DeleteDirSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import System.Posix.Files.ByteString | |||
( | |||
getSymbolicLinkStatus | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "DeleteDirSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "file" | |||
createDir' "dir" | |||
createRegularFile' "dir/.keep" | |||
createSymlink' "dirSym" "dir/" | |||
createDir' "noPerms" | |||
createRegularFile' "noPerms/.keep" | |||
createDir' "noWritable" | |||
createRegularFile' "noWritable/.keep" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
deleteFile' "file" | |||
deleteFile' "dir/.keep" | |||
deleteDir' "dir" | |||
deleteFile' "dirSym" | |||
deleteFile' "noPerms/.keep" | |||
deleteDir' "noPerms" | |||
deleteFile' "noWritable/.keep" | |||
deleteDir' "noWritable" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.deleteDir" $ do | |||
-- successes -- | |||
it "deleteDir, empty directory, all fine" $ do | |||
createDir' "testDir" | |||
deleteDir' "testDir" | |||
getSymbolicLinkStatus "testDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "deleteDir, directory with null permissions, all fine" $ do | |||
createDir' "noPerms/testDir" | |||
noPerms "noPerms/testDir" | |||
deleteDir' "noPerms/testDir" | |||
getSymbolicLinkStatus "testDir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
-- posix failures -- | |||
it "deleteDir, wrong file type (symlink to directory)" $ | |||
deleteDir' "dirSym" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "deleteDir, wrong file type (regular file)" $ | |||
deleteDir' "file" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "deleteDir, directory does not exist" $ | |||
deleteDir' "doesNotExist" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "deleteDir, directory not empty" $ | |||
deleteDir' "dir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == UnsatisfiedConstraints) | |||
it "deleteDir, can't open parent directory" $ do | |||
createDir' "noPerms/foo" | |||
noPerms "noPerms" | |||
(deleteDir' "noPerms/foo") | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
normalDirPerms "noPerms" | |||
deleteDir' "noPerms/foo" | |||
it "deleteDir, can't write to parent directory, still fine" $ do | |||
createDir' "noWritable/foo" | |||
noWritableDirPerms "noWritable" | |||
(deleteDir' "noWritable/foo") | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
normalDirPerms "noWritable" | |||
deleteDir' "noWritable/foo" | |||
@@ -1,84 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.DeleteFileSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import System.Posix.Files.ByteString | |||
( | |||
getSymbolicLinkStatus | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "DeleteFileSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "foo" | |||
createSymlink' "syml" "foo" | |||
createDir' "dir" | |||
createDir' "noPerms" | |||
noPerms "noPerms" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
deleteFile' "foo" | |||
deleteFile' "syml" | |||
deleteDir' "dir" | |||
deleteDir' "noPerms" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.deleteFile" $ do | |||
-- successes -- | |||
it "deleteFile, regular file, all fine" $ do | |||
createRegularFile' "testFile" | |||
deleteFile' "testFile" | |||
getSymbolicLinkStatus "testFile" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "deleteFile, symlink, all fine" $ do | |||
recreateSymlink' "syml" | |||
"testFile" | |||
Strict | |||
deleteFile' "testFile" | |||
getSymbolicLinkStatus "testFile" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
-- posix failures -- | |||
it "deleteFile, wrong file type (directory)" $ | |||
deleteFile' "dir" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType || ioeGetErrorType e == PermissionDenied) | |||
it "deleteFile, file does not exist" $ | |||
deleteFile' "doesNotExist" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "deleteFile, can't read directory" $ | |||
deleteFile' "noPerms/blah" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
@@ -1,100 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.GetDirsFilesSpec where | |||
import Data.List | |||
( | |||
sort | |||
) | |||
import "hpath-directory" System.Posix.RawFilePath.Directory hiding (getDirsFiles') | |||
import System.Posix.FilePath | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "GetDirsFilesSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "file" | |||
createRegularFile' "Lala" | |||
createRegularFile' ".hidden" | |||
createSymlink' "syml" "Lala" | |||
createDir' "dir" | |||
createSymlink' "dirsym" "dir" | |||
createDir' "noPerms" | |||
noPerms "noPerms" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
deleteFile' "file" | |||
deleteFile' "Lala" | |||
deleteFile' ".hidden" | |||
deleteFile' "syml" | |||
deleteDir' "dir" | |||
deleteFile' "dirsym" | |||
deleteDir' "noPerms" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.getDirsFiles" $ do | |||
-- successes -- | |||
it "getDirsFiles, all fine" $ | |||
withRawTmpDir $ \p -> do | |||
let expectedFiles = [".hidden" | |||
,"Lala" | |||
,"dir" | |||
,"dirsym" | |||
,"file" | |||
,"noPerms" | |||
,"syml"] | |||
(fmap sort $ getDirsFiles p) | |||
`shouldReturn` fmap (p </>) expectedFiles | |||
-- posix failures -- | |||
it "getDirsFiles, nonexistent directory" $ | |||
getDirsFiles' "nothingHere" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "getDirsFiles, wrong file type (file)" $ | |||
getDirsFiles' "file" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InappropriateType) | |||
it "getDirsFiles, wrong file type (symlink to file)" $ | |||
getDirsFiles' "syml" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
it "getDirsFiles, wrong file type (symlink to dir)" $ | |||
getDirsFiles' "dirsym" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
it "getDirsFiles, can't open directory" $ | |||
getDirsFiles' "noPerms" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
@@ -1,88 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.GetFileTypeSpec where | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "GetFileTypeSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "regularfile" | |||
createSymlink' "symlink" "regularfile" | |||
createSymlink' "brokenSymlink" "broken" | |||
createDir' "directory" | |||
createSymlink' "symlinkD" "directory" | |||
createDir' "noPerms" | |||
noPerms "noPerms" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
deleteFile' "regularfile" | |||
deleteFile' "symlink" | |||
deleteFile' "brokenSymlink" | |||
deleteDir' "directory" | |||
deleteFile' "symlinkD" | |||
deleteDir' "noPerms" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.getFileType" $ do | |||
-- successes -- | |||
it "getFileType, regular file" $ | |||
getFileType' "regularfile" | |||
`shouldReturn` RegularFile | |||
it "getFileType, directory" $ | |||
getFileType' "directory" | |||
`shouldReturn` Directory | |||
it "getFileType, directory with null permissions" $ | |||
getFileType' "noPerms" | |||
`shouldReturn` Directory | |||
it "getFileType, symlink to file" $ | |||
getFileType' "symlink" | |||
`shouldReturn` SymbolicLink | |||
it "getFileType, symlink to directory" $ | |||
getFileType' "symlinkD" | |||
`shouldReturn` SymbolicLink | |||
it "getFileType, broken symlink" $ | |||
getFileType' "brokenSymlink" | |||
`shouldReturn` SymbolicLink | |||
-- posix failures -- | |||
it "getFileType, file does not exist" $ | |||
getFileType' "nothingHere" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "getFileType, can't open directory" $ | |||
getFileType' "noPerms/forz" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
@@ -1,126 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.MoveFileOverwriteSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "MoveFileOverwriteSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "myFile" | |||
createSymlink' "myFileL" "myFile" | |||
createDir' "alreadyExistsD" | |||
createDir' "dir" | |||
createDir' "noPerms" | |||
createDir' "noWritePerm" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerm" | |||
writeFile' "myFile" "Blahfaselgagaga" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerm" | |||
deleteFile' "myFile" | |||
deleteFile' "myFileL" | |||
deleteDir' "alreadyExistsD" | |||
deleteDir' "dir" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerm" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.moveFile" $ do | |||
-- successes -- | |||
it "moveFile (Overwrite), all fine" $ | |||
moveFile' "myFile" | |||
"movedFile" | |||
Overwrite | |||
it "moveFile (Overwrite), all fine" $ | |||
moveFile' "myFile" | |||
"dir/movedFile" | |||
Overwrite | |||
it "moveFile (Overwrite), all fine on symlink" $ | |||
moveFile' "myFileL" | |||
"movedFile" | |||
Overwrite | |||
it "moveFile (Overwrite), all fine on directory" $ | |||
moveFile' "dir" | |||
"movedFile" | |||
Overwrite | |||
it "moveFile (Overwrite), destination file already exists" $ | |||
moveFile' "myFile" | |||
"alreadyExists" | |||
Overwrite | |||
-- posix failures -- | |||
it "moveFile (Overwrite), source file does not exist" $ | |||
moveFile' "fileDoesNotExist" | |||
"movedFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "moveFile (Overwrite), can't write to destination directory" $ | |||
moveFile' "myFile" | |||
"noWritePerm/movedFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "moveFile (Overwrite), can't open destination directory" $ | |||
moveFile' "myFile" | |||
"noPerms/movedFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "moveFile (Overwrite), can't open source directory" $ | |||
moveFile' "noPerms/myFile" | |||
"movedFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
-- custom failures -- | |||
it "moveFile (Overwrite), move from file to dir" $ | |||
moveFile' "myFile" | |||
"alreadyExistsD" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "moveFile (Overwrite), source and dest are same file" $ | |||
moveFile' "myFile" | |||
"myFile" | |||
Overwrite | |||
`shouldThrow` | |||
isSameFile |
@@ -1,129 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.MoveFileSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "MoveFileSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "myFile" | |||
createSymlink' "myFileL" "myFile" | |||
createRegularFile' "alreadyExists" | |||
createDir' "alreadyExistsD" | |||
createDir' "dir" | |||
createDir' "noPerms" | |||
createDir' "noWritePerm" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerm" | |||
writeFile' "myFile" "Blahfaselgagaga" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerm" | |||
deleteFile' "myFile" | |||
deleteFile' "myFileL" | |||
deleteFile' "alreadyExists" | |||
deleteDir' "alreadyExistsD" | |||
deleteDir' "dir" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerm" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.moveFile" $ do | |||
-- successes -- | |||
it "moveFile (Strict), all fine" $ | |||
moveFile' "myFile" | |||
"movedFile" | |||
Strict | |||
it "moveFile (Strict), all fine" $ | |||
moveFile' "myFile" | |||
"dir/movedFile" | |||
Strict | |||
it "moveFile (Strict), all fine on symlink" $ | |||
moveFile' "myFileL" | |||
"movedFile" | |||
Strict | |||
it "moveFile (Strict), all fine on directory" $ | |||
moveFile' "dir" | |||
"movedFile" | |||
Strict | |||
-- posix failures -- | |||
it "moveFile (Strict), source file does not exist" $ | |||
moveFile' "fileDoesNotExist" | |||
"movedFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "moveFile (Strict), can't write to destination directory" $ | |||
moveFile' "myFile" | |||
"noWritePerm/movedFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "moveFile (Strict), can't open destination directory" $ | |||
moveFile' "myFile" | |||
"noPerms/movedFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "moveFile (Strict), can't open source directory" $ | |||
moveFile' "noPerms/myFile" | |||
"movedFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
-- custom failures -- | |||
it "moveFile (Strict), destination file already exists" $ | |||
moveFile' "myFile" | |||
"alreadyExists" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "moveFile (Strict), move from file to dir" $ | |||
moveFile' "myFile" | |||
"alreadyExistsD" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "moveFile (Strict), source and dest are same file" $ | |||
moveFile' "myFile" | |||
"myFile" | |||
Strict | |||
`shouldThrow` | |||
isSameFile |
@@ -1,85 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.ReadFileSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "ReadFileSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "fileWithContent" | |||
createRegularFile' "fileWithoutContent" | |||
createSymlink' "inputFileSymL" "fileWithContent" | |||
createDir' "alreadyExistsD" | |||
createRegularFile' "noPerms" | |||
noPerms "noPerms" | |||
createDir' "noPermsD" | |||
createRegularFile' "noPermsD/inputFile" | |||
noPerms "noPermsD" | |||
writeFile' "fileWithContent" "Blahfaselgagaga" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
deleteFile' "fileWithContent" | |||
deleteFile' "fileWithoutContent" | |||
deleteFile' "inputFileSymL" | |||
deleteDir' "alreadyExistsD" | |||
normalFilePerms "noPerms" | |||
deleteFile' "noPerms" | |||
normalDirPerms "noPermsD" | |||
deleteFile' "noPermsD/inputFile" | |||
deleteDir' "noPermsD" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.readFile" $ do | |||
-- successes -- | |||
it "readFile (Strict) file with content, everything clear" $ do | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "Blahfaselgagaga" | |||
it "readFile (Strict) symlink, everything clear" $ do | |||
out <- readFile' "inputFileSymL" | |||
out `shouldBe` "Blahfaselgagaga" | |||
it "readFile (Strict) empty file, everything clear" $ do | |||
out <- readFile' "fileWithoutContent" | |||
out `shouldBe` "" | |||
-- posix failures -- | |||
it "readFile (Strict) directory, wrong file type" $ do | |||
readFile' "alreadyExistsD" | |||
`shouldThrow` (\e -> ioeGetErrorType e == InappropriateType) | |||
it "readFile (Strict) file, no permissions" $ do | |||
readFile' "noPerms" | |||
`shouldThrow` (\e -> ioeGetErrorType e == PermissionDenied) | |||
it "readFile (Strict) file, no permissions on dir" $ do | |||
readFile' "noPermsD/inputFile" | |||
`shouldThrow` (\e -> ioeGetErrorType e == PermissionDenied) | |||
it "readFile (Strict) file, no such file" $ do | |||
readFile' "lalala" | |||
`shouldThrow` (\e -> ioeGetErrorType e == NoSuchThing) |
@@ -1,139 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.RecreateSymlinkOverwriteSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "RecreateSymlinkOverwriteSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "myFile" | |||
createSymlink' "myFileL" "myFile" | |||
createRegularFile' "alreadyExists" | |||
createDir' "alreadyExistsD" | |||
createDir' "dir" | |||
createDir' "noPerms" | |||
createDir' "noWritePerm" | |||
createDir' "alreadyExistsD2" | |||
createRegularFile' "alreadyExistsD2/lala" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerm" | |||
writeFile' "myFile" "Blahfaselgagaga" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerm" | |||
deleteFile' "myFile" | |||
deleteFile' "myFileL" | |||
deleteFile' "alreadyExists" | |||
deleteFile' "alreadyExistsD2/lala" | |||
deleteDir' "alreadyExistsD" | |||
deleteDir' "alreadyExistsD2" | |||
deleteDir' "dir" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerm" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.recreateSymlink" $ do | |||
-- successes -- | |||
it "recreateSymLink (Overwrite), all fine" $ do | |||
recreateSymlink' "myFileL" | |||
"movedFile" | |||
Overwrite | |||
removeFileIfExists "movedFile" | |||
it "recreateSymLink (Overwrite), all fine" $ do | |||
recreateSymlink' "myFileL" | |||
"dir/movedFile" | |||
Overwrite | |||
removeFileIfExists "dir/movedFile" | |||
it "recreateSymLink (Overwrite), destination file already exists" $ | |||
recreateSymlink' "myFileL" | |||
"alreadyExists" | |||
Overwrite | |||
it "recreateSymLink (Overwrite), destination already exists and is an empty dir" $ do | |||
recreateSymlink' "myFileL" | |||
"alreadyExistsD" | |||
Overwrite | |||
deleteFile' "alreadyExistsD" | |||
createDir' "alreadyExistsD" | |||
-- posix failures -- | |||
it "recreateSymLink (Overwrite), destination already exists and is a non-empty dir" $ | |||
recreateSymlink' "myFileL" | |||
"alreadyExistsD2" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == UnsatisfiedConstraints) | |||
it "recreateSymLink (Overwrite), wrong input type (file)" $ | |||
recreateSymlink' "myFile" | |||
"movedFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
it "recreateSymLink (Overwrite), wrong input type (directory)" $ | |||
recreateSymlink' "dir" | |||
"movedFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
it "recreateSymLink (Overwrite), can't write to destination directory" $ | |||
recreateSymlink' "myFileL" | |||
"noWritePerm/movedFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "recreateSymLink (Overwrite), can't open destination directory" $ | |||
recreateSymlink' "myFileL" | |||
"noPerms/movedFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "recreateSymLink (Overwrite), can't open source directory" $ | |||
recreateSymlink' "noPerms/myFileL" | |||
"movedFile" | |||
Overwrite | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
-- custom failures -- | |||
it "recreateSymLink (Overwrite), source and destination are the same file" $ | |||
recreateSymlink' "myFileL" | |||
"myFileL" | |||
Overwrite | |||
`shouldThrow` | |||
isSameFile | |||
@@ -1,130 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.RecreateSymlinkSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "RecreateSymlinkSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "myFile" | |||
createSymlink' "myFileL" "myFile" | |||
createRegularFile' "alreadyExists" | |||
createDir' "alreadyExistsD" | |||
createDir' "dir" | |||
createDir' "noPerms" | |||
createDir' "noWritePerm" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerm" | |||
writeFile' "myFile" "Blahfaselgagaga" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerm" | |||
deleteFile' "myFile" | |||
deleteFile' "myFileL" | |||
deleteFile' "alreadyExists" | |||
deleteDir' "alreadyExistsD" | |||
deleteDir' "dir" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerm" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.recreateSymlink" $ do | |||
-- successes -- | |||
it "recreateSymLink (Strict), all fine" $ do | |||
recreateSymlink' "myFileL" | |||
"movedFile" | |||
Strict | |||
removeFileIfExists "movedFile" | |||
it "recreateSymLink (Strict), all fine" $ do | |||
recreateSymlink' "myFileL" | |||
"dir/movedFile" | |||
Strict | |||
removeFileIfExists "dir/movedFile" | |||
-- posix failures -- | |||
it "recreateSymLink (Strict), wrong input type (file)" $ | |||
recreateSymlink' "myFile" | |||
"movedFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
it "recreateSymLink (Strict), wrong input type (directory)" $ | |||
recreateSymlink' "dir" | |||
"movedFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == InvalidArgument) | |||
it "recreateSymLink (Strict), can't write to destination directory" $ | |||
recreateSymlink' "myFileL" | |||
"noWritePerm/movedFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "recreateSymLink (Strict), can't open destination directory" $ | |||
recreateSymlink' "myFileL" | |||
"noPerms/movedFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "recreateSymLink (Strict), can't open source directory" $ | |||
recreateSymlink' "noPerms/myFileL" | |||
"movedFile" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "recreateSymLink (Strict), destination file already exists" $ | |||
recreateSymlink' "myFileL" | |||
"alreadyExists" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "recreateSymLink (Strict), destination already exists and is a dir" $ | |||
recreateSymlink' "myFileL" | |||
"alreadyExistsD" | |||
Strict | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
-- custom failures -- | |||
it "recreateSymLink (Strict), source and destination are the same file" $ | |||
recreateSymlink' "myFileL" | |||
"myFileL" | |||
Strict | |||
`shouldThrow` | |||
isSameFile | |||
@@ -1,117 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.RenameFileSpec where | |||
import Test.Hspec | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "RenameFileSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "myFile" | |||
createSymlink' "myFileL" "myFile" | |||
createRegularFile' "alreadyExists" | |||
createDir' "alreadyExistsD" | |||
createDir' "dir" | |||
createDir' "noPerms" | |||
createDir' "noWritePerm" | |||
noPerms "noPerms" | |||
noWritableDirPerms "noWritePerm" | |||
writeFile' "myFile" "Blahfaselgagaga" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
normalDirPerms "noPerms" | |||
normalDirPerms "noWritePerm" | |||
deleteFile' "myFile" | |||
deleteFile' "myFileL" | |||
deleteFile' "alreadyExists" | |||
deleteDir' "alreadyExistsD" | |||
deleteDir' "dir" | |||
deleteDir' "noPerms" | |||
deleteDir' "noWritePerm" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.renameFile" $ do | |||
-- successes -- | |||
it "renameFile, all fine" $ | |||
renameFile' "myFile" | |||
"renamedFile" | |||
it "renameFile, all fine" $ | |||
renameFile' "myFile" | |||
"dir/renamedFile" | |||
it "renameFile, all fine on symlink" $ | |||
renameFile' "myFileL" | |||
"renamedFile" | |||
it "renameFile, all fine on directory" $ | |||
renameFile' "dir" | |||
"renamedFile" | |||
-- posix failures -- | |||
it "renameFile, source file does not exist" $ | |||
renameFile' "fileDoesNotExist" | |||
"renamedFile" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == NoSuchThing) | |||
it "renameFile, can't write to output directory" $ | |||
renameFile' "myFile" | |||
"noWritePerm/renamedFile" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "renameFile, can't open output directory" $ | |||
renameFile' "myFile" | |||
"noPerms/renamedFile" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
it "renameFile, can't open source directory" $ | |||
renameFile' "noPerms/myFile" | |||
"renamedFile" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == PermissionDenied) | |||
-- custom failures -- | |||
it "renameFile, destination file already exists" $ | |||
renameFile' "myFile" | |||
"alreadyExists" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "renameFile, move from file to dir" $ | |||
renameFile' "myFile" | |||
"alreadyExistsD" | |||
`shouldThrow` | |||
(\e -> ioeGetErrorType e == AlreadyExists) | |||
it "renameFile, source and dest are same file" $ | |||
renameFile' "myFile" | |||
"myFile" | |||
`shouldThrow` | |||
isSameFile | |||
@@ -1,26 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.ToAbsSpec where | |||
import Test.Hspec | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
spec :: Spec | |||
spec = describe "System.Posix.RawFilePath.Directory.toAbs" $ do | |||
-- successes -- | |||
it "toAbs returns absolute paths unchanged" $ do | |||
let p1 = "/a/b/c/d" | |||
to <- toAbs p1 | |||
p1 `shouldBe` to | |||
it "toAbs returns even existing absolute paths unchanged" $ do | |||
let p1 = "/home" | |||
to <- toAbs p1 | |||
p1 `shouldBe` to | |||
@@ -1,108 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.WriteFileLSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "WriteFileLSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "fileWithContent" | |||
createRegularFile' "fileWithoutContent" | |||
createSymlink' "inputFileSymL" "fileWithContent" | |||
createDir' "alreadyExistsD" | |||
createRegularFile' "noPerms" | |||
noPerms "noPerms" | |||
createDir' "noPermsD" | |||
createRegularFile' "noPermsD/inputFile" | |||
noPerms "noPermsD" | |||
writeFile' "fileWithContent" "BLKASL" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
deleteFile' "fileWithContent" | |||
deleteFile' "fileWithoutContent" | |||
deleteFile' "inputFileSymL" | |||
deleteDir' "alreadyExistsD" | |||
normalFilePerms "noPerms" | |||
deleteFile' "noPerms" | |||
normalDirPerms "noPermsD" | |||
deleteFile' "noPermsD/inputFile" | |||
deleteDir' "noPermsD" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.WriteFileL" $ do | |||
-- successes -- | |||
it "WriteFileL file with content, everything clear" $ do | |||
writeFileL' "fileWithContent" "blahfaselllll" | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "blahfaselllll" | |||
it "WriteFileL file with content, everything clear" $ do | |||
writeFileL' "fileWithContent" "gagagaga" | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "gagagaga" | |||
it "WriteFileL file with content, everything clear" $ do | |||
writeFileL' "fileWithContent" "" | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "" | |||
it "WriteFileL file without content, everything clear" $ do | |||
writeFileL' "fileWithoutContent" "blahfaselllll" | |||
out <- readFile' "fileWithoutContent" | |||
out `shouldBe` "blahfaselllll" | |||
it "WriteFileL, everything clear" $ do | |||
writeFileL' "fileWithoutContent" "gagagaga" | |||
out <- readFile' "fileWithoutContent" | |||
out `shouldBe` "gagagaga" | |||
it "WriteFileL symlink, everything clear" $ do | |||
writeFileL' "inputFileSymL" "blahfaselllll" | |||
out <- readFile' "inputFileSymL" | |||
out `shouldBe` "blahfaselllll" | |||
it "WriteFileL symlink, everything clear" $ do | |||
writeFileL' "inputFileSymL" "gagagaga" | |||
out <- readFile' "inputFileSymL" | |||
out `shouldBe` "gagagaga" | |||
-- posix failures -- | |||
it "WriteFileL to dir, inappropriate type" $ do | |||
writeFileL' "alreadyExistsD" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == InappropriateType) | |||
it "WriteFileL, no permissions to file" $ do | |||
writeFileL' "noPerms" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == PermissionDenied) | |||
it "WriteFileL, no permissions to file" $ do | |||
writeFileL' "noPermsD/inputFile" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == PermissionDenied) | |||
it "WriteFileL, file does not exist" $ do | |||
writeFileL' "gaga" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == NoSuchThing) |
@@ -1,108 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module System.Posix.RawFilePath.Directory.WriteFileSpec where | |||
import Test.Hspec | |||
import System.IO.Error | |||
( | |||
ioeGetErrorType | |||
) | |||
import GHC.IO.Exception | |||
( | |||
IOErrorType(..) | |||
) | |||
import Utils | |||
upTmpDir :: IO () | |||
upTmpDir = do | |||
setTmpDir "WriteFileSpec" | |||
createTmpDir | |||
setupFiles :: IO () | |||
setupFiles = do | |||
createRegularFile' "fileWithContent" | |||
createRegularFile' "fileWithoutContent" | |||
createSymlink' "inputFileSymL" "fileWithContent" | |||
createDir' "alreadyExistsD" | |||
createRegularFile' "noPerms" | |||
noPerms "noPerms" | |||
createDir' "noPermsD" | |||
createRegularFile' "noPermsD/inputFile" | |||
noPerms "noPermsD" | |||
writeFile' "fileWithContent" "BLKASL" | |||
cleanupFiles :: IO () | |||
cleanupFiles = do | |||
deleteFile' "fileWithContent" | |||
deleteFile' "fileWithoutContent" | |||
deleteFile' "inputFileSymL" | |||
deleteDir' "alreadyExistsD" | |||
normalFilePerms "noPerms" | |||
deleteFile' "noPerms" | |||
normalDirPerms "noPermsD" | |||
deleteFile' "noPermsD/inputFile" | |||
deleteDir' "noPermsD" | |||
spec :: Spec | |||
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $ | |||
describe "System.Posix.RawFilePath.Directory.writeFile" $ do | |||
-- successes -- | |||
it "writeFile file with content, everything clear" $ do | |||
writeFile' "fileWithContent" "blahfaselllll" | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "blahfaselllll" | |||
it "writeFile file with content, everything clear" $ do | |||
writeFile' "fileWithContent" "gagagaga" | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "gagagaga" | |||
it "writeFile file with content, everything clear" $ do | |||
writeFile' "fileWithContent" "" | |||
out <- readFile' "fileWithContent" | |||
out `shouldBe` "" | |||
it "writeFile file without content, everything clear" $ do | |||
writeFile' "fileWithoutContent" "blahfaselllll" | |||
out <- readFile' "fileWithoutContent" | |||
out `shouldBe` "blahfaselllll" | |||
it "writeFile, everything clear" $ do | |||
writeFile' "fileWithoutContent" "gagagaga" | |||
out <- readFile' "fileWithoutContent" | |||
out `shouldBe` "gagagaga" | |||
it "writeFile symlink, everything clear" $ do | |||
writeFile' "inputFileSymL" "blahfaselllll" | |||
out <- readFile' "inputFileSymL" | |||
out `shouldBe` "blahfaselllll" | |||
it "writeFile symlink, everything clear" $ do | |||
writeFile' "inputFileSymL" "gagagaga" | |||
out <- readFile' "inputFileSymL" | |||
out `shouldBe` "gagagaga" | |||
-- posix failures -- | |||
it "writeFile to dir, inappropriate type" $ do | |||
writeFile' "alreadyExistsD" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == InappropriateType) | |||
it "writeFile, no permissions to file" $ do | |||
writeFile' "noPerms" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == PermissionDenied) | |||
it "writeFile, no permissions to file" $ do | |||
writeFile' "noPermsD/inputFile" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == PermissionDenied) | |||
it "writeFile, file does not exist" $ do | |||
writeFile' "gaga" "" | |||
`shouldThrow` (\e -> ioeGetErrorType e == NoSuchThing) |
@@ -1,293 +0,0 @@ | |||
{-# LANGUAGE OverloadedStrings #-} | |||
module Utils where | |||
import Control.Applicative | |||
( | |||
(<$>) | |||
) | |||
import Control.Monad | |||
( | |||
forM_ | |||
, void | |||
) | |||
import Control.Monad.IfElse | |||
( | |||
whenM | |||
) | |||
import qualified Data.ByteString as BS | |||
import qualified Data.ByteString.Lazy as BSL | |||
import Data.IORef | |||
( | |||
newIORef | |||
, readIORef | |||
, writeIORef | |||
, IORef | |||
) | |||
import "hpath-directory" System.Posix.RawFilePath.Directory | |||
import Prelude hiding (appendFile, readFile, writeFile) | |||
import Data.Maybe | |||
( | |||
fromJust | |||
) | |||
import System.IO.Unsafe | |||
( | |||
unsafePerformIO | |||
) | |||
import qualified System.Posix.RawFilePath.Directory.Traversals as DT | |||
import Data.ByteString | |||
( | |||
ByteString | |||
) | |||
import qualified Data.ByteString.Lazy as L | |||
import System.Posix.FilePath | |||
import System.Posix.Files.ByteString | |||
( | |||
groupExecuteMode | |||
, groupReadMode | |||
, nullFileMode | |||
, otherExecuteMode | |||
, otherReadMode | |||
, ownerExecuteMode | |||
, ownerReadMode | |||
, setFileMode | |||
, unionFileModes | |||
) | |||
baseTmpDir :: IORef (Maybe ByteString) | |||
{-# NOINLINE baseTmpDir #-} | |||
baseTmpDir = unsafePerformIO (newIORef Nothing) | |||
tmpDir :: IORef (Maybe ByteString) | |||
{-# NOINLINE tmpDir #-} | |||
tmpDir = unsafePerformIO (newIORef Nothing) | |||
----------------- | |||
--[ Utilities ]-- | |||
----------------- | |||
setTmpDir :: ByteString -> IO () | |||
{-# NOINLINE setTmpDir #-} | |||
setTmpDir bs = do | |||
tmp <- fromJust <$> readIORef baseTmpDir | |||
writeIORef tmpDir (Just (tmp `BS.append` bs)) | |||
createTmpDir :: IO () | |||
{-# NOINLINE createTmpDir #-} | |||
createTmpDir = do | |||
tmp <- fromJust <$> readIORef tmpDir | |||
void $ createDir newDirPerms tmp | |||
deleteTmpDir :: IO () | |||
{-# NOINLINE deleteTmpDir #-} | |||
deleteTmpDir = do | |||
tmp <- fromJust <$> readIORef tmpDir | |||
void $ deleteDir tmp | |||
deleteBaseTmpDir :: IO () | |||
{-# NOINLINE deleteBaseTmpDir #-} | |||
deleteBaseTmpDir = do | |||
tmp <- fromJust <$> readIORef baseTmpDir | |||
contents <- getDirsFiles tmp | |||
forM_ contents deleteDir | |||
void $ deleteDir tmp | |||
withRawTmpDir :: (ByteString -> IO a) -> IO a | |||
{-# NOINLINE withRawTmpDir #-} | |||
withRawTmpDir f = do | |||
tmp <- fromJust <$> readIORef tmpDir | |||
f tmp | |||
getRawTmpDir :: IO ByteString | |||
{-# NOINLINE getRawTmpDir #-} | |||
getRawTmpDir = withRawTmpDir (return . flip BS.append "/") | |||
withTmpDir :: ByteString -> (ByteString -> IO a) -> IO a | |||
{-# NOINLINE withTmpDir #-} | |||
withTmpDir ip f = do | |||
tmp <- fromJust <$> readIORef tmpDir | |||
let p = tmp </> ip | |||
f p | |||
withTmpDir' :: ByteString | |||
-> ByteString | |||
-> (ByteString -> ByteString -> IO a) | |||
-> IO a | |||
{-# NOINLINE withTmpDir' #-} | |||
withTmpDir' ip1 ip2 f = do | |||
tmp <- fromJust <$> readIORef tmpDir | |||
let p1 = tmp </> ip1 | |||
let p2 = tmp </> ip2 | |||
f p1 p2 | |||
removeFileIfExists :: ByteString -> IO () | |||
{-# NOINLINE removeFileIfExists #-} | |||
removeFileIfExists bs = | |||
withTmpDir bs $ \p -> whenM (doesFileExist p) (deleteFile p) | |||
removeDirIfExists :: ByteString -> IO () | |||
{-# NOINLINE removeDirIfExists #-} | |||
removeDirIfExists bs = | |||
withTmpDir bs $ \p -> whenM (doesDirectoryExist p) (deleteDirRecursive p) | |||
copyFile' :: ByteString -> ByteString -> CopyMode -> IO () | |||
{-# NOINLINE copyFile' #-} | |||
copyFile' inputFileP outputFileP cm = | |||
withTmpDir' inputFileP outputFileP (\p1 p2 -> copyFile p1 p2 cm) | |||
copyDirRecursive' :: ByteString -> ByteString | |||
-> CopyMode -> RecursiveErrorMode -> IO () | |||
{-# NOINLINE copyDirRecursive' #-} | |||
copyDirRecursive' inputDirP outputDirP cm rm = | |||
withTmpDir' inputDirP outputDirP (\p1 p2 -> copyDirRecursive p1 p2 cm rm) | |||
createDir' :: ByteString -> IO () | |||
{-# NOINLINE createDir' #-} | |||
createDir' dest = withTmpDir dest (createDir newDirPerms) | |||
createDirIfMissing' :: ByteString -> IO () | |||
{-# NOINLINE createDirIfMissing' #-} | |||
createDirIfMissing' dest = withTmpDir dest (createDirIfMissing newDirPerms) | |||
createDirRecursive' :: ByteString -> IO () | |||
{-# NOINLINE createDirRecursive' #-} | |||
createDirRecursive' dest = withTmpDir dest (createDirRecursive newDirPerms) | |||
createRegularFile' :: ByteString -> IO () | |||
{-# NOINLINE createRegularFile' #-} | |||
createRegularFile' dest = withTmpDir dest (createRegularFile newFilePerms) | |||
createSymlink' :: ByteString -> ByteString -> IO () | |||
{-# NOINLINE createSymlink' #-} | |||
createSymlink' dest sympoint = withTmpDir dest | |||
(\x -> createSymlink x sympoint) | |||
renameFile' :: ByteString -> ByteString -> IO () | |||
{-# NOINLINE renameFile' #-} | |||
renameFile' inputFileP outputFileP = | |||
withTmpDir' inputFileP outputFileP $ \i o -> do | |||
renameFile i o | |||
renameFile o i | |||
moveFile' :: ByteString -> ByteString -> CopyMode -> IO () | |||
{-# NOINLINE moveFile' #-} | |||
moveFile' inputFileP outputFileP cm = | |||
withTmpDir' inputFileP outputFileP $ \i o -> do | |||
moveFile i o cm | |||
moveFile o i Strict | |||
recreateSymlink' :: ByteString -> ByteString -> CopyMode -> IO () | |||
{-# NOINLINE recreateSymlink' #-} | |||
recreateSymlink' inputFileP outputFileP cm = | |||
withTmpDir' inputFileP outputFileP (\p1 p2 -> recreateSymlink p1 p2 cm) | |||
noWritableDirPerms :: ByteString -> IO () | |||
{-# NOINLINE noWritableDirPerms #-} | |||
noWritableDirPerms path = withTmpDir path $ \p -> | |||
setFileMode p perms | |||
where | |||
perms = ownerReadMode | |||
`unionFileModes` ownerExecuteMode | |||
`unionFileModes` groupReadMode | |||
`unionFileModes` groupExecuteMode | |||
`unionFileModes` otherReadMode | |||
`unionFileModes` otherExecuteMode | |||
noPerms :: ByteString -> IO () | |||
{-# NOINLINE noPerms #-} | |||
noPerms path = withTmpDir path $ \p -> setFileMode p nullFileMode | |||
normalDirPerms :: ByteString -> IO () | |||
{-# NOINLINE normalDirPerms #-} | |||
normalDirPerms path = | |||
withTmpDir path $ \p -> setFileMode p newDirPerms | |||
normalFilePerms :: ByteString -> IO () | |||
{-# NOINLINE normalFilePerms #-} | |||
normalFilePerms path = | |||
withTmpDir path $ \p -> setFileMode p newFilePerms | |||
getFileType' :: ByteString -> IO FileType | |||
{-# NOINLINE getFileType' #-} | |||
getFileType' path = withTmpDir path getFileType | |||
getDirsFiles' :: ByteString -> IO [ByteString] | |||
{-# NOINLINE getDirsFiles' #-} | |||
getDirsFiles' path = withTmpDir path getDirsFiles | |||
deleteFile' :: ByteString -> IO () | |||
{-# NOINLINE deleteFile' #-} | |||
deleteFile' p = withTmpDir p deleteFile | |||
deleteDir' :: ByteString -> IO () | |||
{-# NOINLINE deleteDir' #-} | |||
deleteDir' p = withTmpDir p deleteDir | |||
deleteDirRecursive' :: ByteString -> IO () | |||
{-# NOINLINE deleteDirRecursive' #-} | |||
deleteDirRecursive' p = withTmpDir p deleteDirRecursive | |||
canonicalizePath' :: ByteString -> IO ByteString | |||
{-# NOINLINE canonicalizePath' #-} | |||
canonicalizePath' p = withTmpDir p canonicalizePath | |||
writeFile' :: ByteString -> ByteString -> IO () | |||
{-# NOINLINE writeFile' #-} | |||
writeFile' ip bs = | |||
withTmpDir ip $ \p -> writeFile p Nothing bs | |||
writeFileL' :: ByteString -> BSL.ByteString -> IO () | |||
{-# NOINLINE writeFileL' #-} | |||
writeFileL' ip bs = | |||
withTmpDir ip $ \p -> writeFileL p Nothing bs | |||
appendFile' :: ByteString -> ByteString -> IO () | |||
{-# NOINLINE appendFile' #-} | |||
appendFile' ip bs = | |||
withTmpDir ip $ \p -> appendFile p bs | |||
allDirectoryContents' :: ByteString -> IO [ByteString] | |||
{-# NOINLINE allDirectoryContents' #-} | |||
allDirectoryContents' ip = | |||
withTmpDir ip $ \p -> DT.allDirectoryContents' p | |||
readFile' :: ByteString -> IO ByteString | |||
{-# NOINLINE readFile' #-} | |||
readFile' p = withTmpDir p (fmap L.toStrict . readFile) | |||
@@ -1,14 +0,0 @@ | |||
# Revision history for hpath-filepath | |||
## 0.10.4 -- 2020-01-26 | |||
* Add `takeAllParents` | |||
## 0.10.2 -- 2020-01-18 | |||
* Add `isSpecialDirectoryEntry` | |||
## 0.10.0 -- 2020-01-04 | |||
* First version. Split from 'hpath', contains only the filepath ByteString manipulation parts. |
@@ -1,30 +0,0 @@ | |||
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. |
@@ -1,29 +0,0 @@ | |||
# 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'. | |||
This package is part of the HPath suite, also check out: | |||
* [hpath](https://hackage.haskell.org/package/hpath) | |||
* [hpath-directory](https://hackage.haskell.org/package/hpath-directory) | |||
* [hpath-io](https://hackage.haskell.org/package/hpath-io) | |||
## 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 |
@@ -1,2 +0,0 @@ | |||
import Distribution.Simple | |||
main = defaultMain |
@@ -1,39 +0,0 @@ | |||
name: hpath-filepath | |||
version: 0.10.4 | |||
synopsis: ByteString based filepath manipulation | |||
description: ByteString based filepath manipulation, similar to 'filepath' package. This is POSIX only. | |||
license: BSD3 | |||
license-file: LICENSE | |||
author: Julian Ospald <hasufell@posteo.de> | |||
maintainer: Julian Ospald <hasufell@posteo.de> | |||
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 |
@@ -1,23 +0,0 @@ | |||
#!/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 | |||
cd "$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)" | |||
cabal exec doctest -- -isrc -XOverloadedStrings System.Posix.FilePath |
@@ -1,859 +0,0 @@ | |||
-- | |||
-- | |||
-- | |||
{-# LANGUAGE CPP #-} | |||
{-# LANGUAGE TupleSections #-} | |||
{-# OPTIONS_GHC -Wall #-} | |||
module System.Posix.FilePath ( | |||
-- * Separator predicates | |||
pathSeparator | |||
, isPathSeparator | |||
, searchPathSeparator | |||
, isSearchPathSeparator | |||
, extSeparator | |||
, isExtSeparator | |||
-- * $PATH methods | |||
, splitSearchPath | |||
, getSearchPath | |||
-- * Extension functions | |||
, splitExtension | |||
, takeExtension | |||
, replaceExtension | |||
, dropExtension | |||
, addExtension | |||
, hasExtension | |||
, (<.>) | |||
, splitExtensions | |||
, dropExtensions | |||
, takeExtensions | |||
, stripExtension | |||
-- * Filename\/directory functions | |||
, splitFileName | |||
, takeFileName | |||
, replaceFileName | |||
, dropFileName | |||
, takeBaseName | |||
, replaceBaseName | |||
, takeDirectory | |||
, replaceDirectory | |||
, combine | |||
, (</>) | |||
, splitPath | |||
, joinPath | |||
, splitDirectories | |||
, takeAllParents | |||
-- * Trailing slash functions | |||
, hasTrailingPathSeparator | |||
, addTrailingPathSeparator | |||
, dropTrailingPathSeparator | |||
-- * File name manipulations | |||
, normalise | |||
, makeRelative | |||
, equalFilePath | |||
, isRelative | |||
, isAbsolute | |||
, isValid | |||
, makeValid | |||
, isSpecialDirectoryEntry | |||
, isFileName | |||
, hasParentDir | |||
, hiddenFile | |||
, module System.Posix.ByteString.FilePath | |||
) where | |||
import Data.ByteString (ByteString) | |||
import qualified Data.ByteString as BS | |||
import Data.String (fromString) | |||
import System.Posix.ByteString.FilePath | |||
import qualified System.Posix.Env.ByteString as PE | |||
import Data.Maybe (isJust) | |||
import Data.Word8 | |||
#if !MIN_VERSION_bytestring(0,10,8) | |||
import qualified Data.List as L | |||
#endif | |||
import Control.Arrow (second) | |||
-- | |||
------------------------ | |||
pathSeparator :: Word8 | |||
pathSeparator = _slash | |||
-- | |||
isPathSeparator :: Word8 -> Bool | |||
isPathSeparator = (== pathSeparator) | |||
searchPathSeparator :: Word8 | |||
searchPathSeparator = _colon | |||
-- | |||
isSearchPathSeparator :: Word8 -> Bool | |||
isSearchPathSeparator = (== searchPathSeparator) | |||
extSeparator :: Word8 | |||
extSeparator = _period | |||
-- | |||
isExtSeparator :: Word8 -> Bool | |||
isExtSeparator = (== extSeparator) | |||
------------------------ | |||
-- | |||
-- | |||
splitSearchPath :: ByteString -> [RawFilePath] | |||
splitSearchPath = f | |||
where | |||
f bs = let (pre, post) = BS.break isSearchPathSeparator bs | |||
in if BS.null post | |||
then g pre | |||
else g pre ++ f (BS.tail post) | |||
g x | |||
| BS.null x = [BS.singleton _period] | |||
| otherwise = [x] | |||
getSearchPath :: IO [RawFilePath] | |||
getSearchPath = fmap (maybe [] splitSearchPath) (PE.getEnv $ fromString "PATH") | |||
------------------------ | |||
-- | |||
-- | |||
splitExtension :: RawFilePath -> (RawFilePath, ByteString) | |||
splitExtension x = if BS.null basename | |||
then (x,BS.empty) | |||
else (BS.append path (BS.init basename),BS.cons extSeparator fileExt) | |||
where | |||
(path,file) = splitFileNameRaw x | |||
(basename,fileExt) = BS.breakEnd isExtSeparator file | |||
-- | |||
takeExtension :: RawFilePath -> ByteString | |||
takeExtension = snd . splitExtension | |||
-- | |||
replaceExtension :: RawFilePath -> ByteString -> RawFilePath | |||
replaceExtension path ext = dropExtension path <.> ext | |||
-- | |||
dropExtension :: RawFilePath -> RawFilePath | |||
dropExtension = fst . splitExtension | |||
-- | |||
addExtension :: RawFilePath -> ByteString -> RawFilePath | |||
addExtension file ext | |||
| BS.null ext = file | |||
| isExtSeparator (BS.head ext) = BS.append file ext | |||
| otherwise = BS.intercalate (BS.singleton extSeparator) [file, ext] | |||
-- | |||
hasExtension :: RawFilePath -> Bool | |||
hasExtension = isJust . BS.elemIndex extSeparator . takeFileName | |||
(<.>) :: RawFilePath -> ByteString -> RawFilePath | |||
(<.>) = addExtension | |||
-- | |||
-- | |||
splitExtensions :: RawFilePath -> (RawFilePath, ByteString) | |||
splitExtensions x = if BS.null basename | |||
then (path,fileExt) | |||
else (BS.append path basename,fileExt) | |||
where | |||
(path,file) = splitFileNameRaw x | |||
(basename,fileExt) = BS.break isExtSeparator file | |||
-- | |||
dropExtensions :: RawFilePath -> RawFilePath | |||
dropExtensions = fst . splitExtensions | |||
-- | |||
takeExtensions :: RawFilePath -> ByteString | |||
takeExtensions = snd . splitExtensions | |||
-- | |||
-- | |||
-- | |||
stripExtension :: ByteString -> RawFilePath -> Maybe RawFilePath | |||
stripExtension bs path | |||
| BS.null bs = Just path | |||
| otherwise = stripSuffix' dotExt path | |||
where | |||
dotExt = if isExtSeparator $ BS.head bs | |||
then bs | |||
else extSeparator `BS.cons` bs | |||
#if MIN_VERSION_bytestring(0,10,8) | |||
stripSuffix' = BS.stripSuffix | |||
#else | |||
stripSuffix' xs ys = fmap (BS.pack . reverse) $ L.stripPrefix (reverse $ BS.unpack xs) (reverse $ BS.unpack ys) | |||
#endif | |||
------------------------ | |||
-- | |||
-- | |||
splitFileName :: RawFilePath -> (RawFilePath, RawFilePath) | |||
splitFileName x = if BS.null path | |||
then (dotSlash, file) | |||
else (path,file) | |||
where | |||
(path,file) = splitFileNameRaw x | |||
dotSlash = _period `BS.cons` (BS.singleton pathSeparator) | |||
-- | |||
takeFileName :: RawFilePath -> RawFilePath | |||
takeFileName = snd . splitFileName | |||
-- | |||
replaceFileName :: RawFilePath -> ByteString -> RawFilePath | |||
replaceFileName x y = fst (splitFileNameRaw x) </> y | |||
-- | |||
dropFileName :: RawFilePath -> RawFilePath | |||
dropFileName = fst . splitFileName | |||
-- | |||
takeBaseName :: RawFilePath -> ByteString | |||
takeBaseName = dropExtension . takeFileName | |||
-- | |||
-- | |||
replaceBaseName :: RawFilePath -> ByteString -> RawFilePath | |||
replaceBaseName path name = combineRaw dir (name <.> ext) | |||
where | |||
(dir,file) = splitFileNameRaw path | |||
ext = takeExtension file | |||
-- | |||
takeDirectory :: RawFilePath -> RawFilePath | |||
takeDirectory x = case () of | |||
() | x == BS.singleton pathSeparator -> x | |||
| BS.null res && not (BS.null file) -> file | |||
| otherwise -> res | |||
where | |||
res = fst $ BS.spanEnd isPathSeparator file | |||
file = dropFileName x | |||
-- | |||
replaceDirectory :: RawFilePath -> ByteString -> RawFilePath | |||
replaceDirectory file dir = combineRaw dir (takeFileName file) | |||
-- | |||
combine :: RawFilePath -> RawFilePath -> RawFilePath | |||
combine a b | not (BS.null b) && isPathSeparator (BS.head b) = b | |||
| otherwise = combineRaw a b | |||
(</>) :: RawFilePath -> RawFilePath -> RawFilePath | |||
(</>) = combine | |||
-- | |||
-- | |||
splitPath :: RawFilePath -> [RawFilePath] | |||
splitPath = splitter | |||
where | |||
splitter x | |||
| BS.null x = [] | |||
| otherwise = case BS.elemIndex pathSeparator x of | |||
Nothing -> [x] | |||
Just ix -> case BS.findIndex (not . isPathSeparator) $ BS.drop (ix+1) x of | |||
Nothing -> [x] | |||
Just runlen -> uncurry (:) . second splitter $ BS.splitAt (ix+1+runlen) x | |||
-- | |||
-- | |||
joinPath :: [RawFilePath] -> RawFilePath | |||
joinPath = foldr (</>) BS.empty | |||
-- | |||
splitDirectories :: RawFilePath -> [RawFilePath] | |||
splitDirectories x | |||
| BS.null x = [] | |||
| isPathSeparator (BS.head x) = let (root,rest) = BS.splitAt 1 x | |||
in root : splitter rest | |||
| otherwise = splitter x | |||
where | |||
splitter = filter (not . BS.null) . BS.split pathSeparator | |||
-- | |||
takeAllParents :: RawFilePath -> [RawFilePath] | |||
takeAllParents p | |||
| np == BS.singleton pathSeparator = [] | |||
| otherwise = takeDirectory np : takeAllParents (takeDirectory np) | |||
where | |||
np = normalise p | |||
------------------------ | |||
-- | |||
hasTrailingPathSeparator :: RawFilePath -> Bool | |||
hasTrailingPathSeparator x | |||
| BS.null x = False | |||
| otherwise = isPathSeparator $ BS.last x | |||
-- | |||
addTrailingPathSeparator :: RawFilePath -> RawFilePath | |||
addTrailingPathSeparator x = if hasTrailingPathSeparator x | |||
then x | |||
else x `BS.snoc` pathSeparator | |||
-- | |||
dropTrailingPathSeparator :: RawFilePath -> RawFilePath | |||
dropTrailingPathSeparator x | |||
| x == BS.singleton pathSeparator = x | |||
| otherwise = if hasTrailingPathSeparator x | |||
then dropTrailingPathSeparator $ BS.init x | |||
else x | |||
------------------------ | |||
-- | |||
normalise :: RawFilePath -> RawFilePath | |||
normalise filepath = | |||
result `BS.append` | |||
(if addPathSeparator | |||
then BS.singleton pathSeparator | |||
else BS.empty) | |||
where | |||
result = let n = f filepath | |||
in if BS.null n | |||
then BS.singleton _period | |||
else n | |||
addPathSeparator = isDirPath filepath && | |||
not (hasTrailingPathSeparator result) | |||
isDirPath xs = hasTrailingPathSeparator xs | |||
|| not (BS.null xs) && BS.last xs == _period | |||
&& hasTrailingPathSeparator (BS.init xs) | |||
f = joinPath . dropDots . propSep . splitDirectories | |||
propSep :: [ByteString] -> [ByteString] | |||
propSep (x:xs) | |||
| BS.all (== pathSeparator) x = BS.singleton pathSeparator : xs | |||
| otherwise = x : xs | |||
propSep [] = [] | |||
dropDots :: [ByteString] -> [ByteString] | |||
dropDots = filter (BS.singleton _period /=) | |||
-- | |||
-- | |||
makeRelative :: RawFilePath -> RawFilePath -> RawFilePath | |||
makeRelative root path | |||
| equalFilePath root path = BS.singleton _period | |||
| takeAbs root /= takeAbs path = path | |||
| otherwise = f (dropAbs root) (dropAbs path) | |||
where | |||
f x y | |||
| BS.null x = BS.dropWhile isPathSeparator y | |||
| otherwise = let (x1,x2) = g x | |||
(y1,y2) = g y | |||
in if equalFilePath x1 y1 then f x2 y2 else path | |||
g x = (BS.dropWhile isPathSeparator a, BS.dropWhile isPathSeparator b) | |||
where (a, b) = BS.break isPathSeparator $ BS.dropWhile isPathSeparator x | |||
dropAbs x = snd $ BS.span (== _slash) x | |||
takeAbs x = fst $ BS.span (== _slash) x | |||
-- | |||
-- | |||
equalFilePath :: RawFilePath -> RawFilePath -> Bool | |||
equalFilePath p1 p2 = f p1 == f p2 | |||
where | |||
f x = dropTrailingPathSeparator $ normalise x | |||
-- | |||
isRelative :: RawFilePath -> Bool | |||
isRelative = not . isAbsolute | |||
-- | |||
isAbsolute :: RawFilePath -> Bool | |||
isAbsolute x | |||
| BS.length x > 0 = isPathSeparator (BS.head x) | |||
| otherwise = False | |||
-- | |||
isValid :: RawFilePath -> Bool | |||
isValid filepath | |||
| BS.null filepath = False | |||
| _nul `BS.elem` filepath = False | |||
| otherwise = True | |||
-- | |||
-- | |||
makeValid :: RawFilePath -> RawFilePath | |||
makeValid path | |||
| BS.null path = BS.singleton _underscore | |||
| otherwise = BS.map (\x -> if x == _nul then _underscore else x) path | |||
-- | |||
isSpecialDirectoryEntry :: RawFilePath -> Bool | |||
isSpecialDirectoryEntry filepath | |||
| BS.pack [_period, _period] == filepath = True | |||
| BS.pack [_period] == filepath = True | |||
| otherwise = False | |||
-- | |||
isFileName :: RawFilePath -> Bool | |||
isFileName filepath = | |||
not (BS.singleton pathSeparator `BS.isInfixOf` filepath) && | |||
not (BS.null filepath) && | |||
not (_nul `BS.elem` filepath) | |||
-- | |||
hasParentDir :: RawFilePath -> Bool | |||
hasParentDir filepath = | |||
(pathSeparator `BS.cons` pathDoubleDot) | |||
`BS.isSuffixOf` filepath | |||
|| | |||
(BS.singleton pathSeparator | |||
`BS.append` pathDoubleDot | |||
`BS.append` BS.singleton pathSeparator) | |||
`BS.isInfixOf` filepath | |||
|| | |||
(pathDoubleDot `BS.append` BS.singleton pathSeparator) | |||
`BS.isPrefixOf` filepath | |||
where | |||
pathDoubleDot = BS.pack [_period, _period] | |||
-- | |||
hiddenFile :: RawFilePath -> Bool | |||
hiddenFile fp | |||
| fn == BS.pack [_period, _period] = False | |||
| fn == BS.pack [_period] = False | |||
| otherwise = BS.pack [extSeparator] | |||
`BS.isPrefixOf` fn | |||
where | |||
fn = takeFileName fp | |||
------------------------ | |||
splitFileNameRaw :: RawFilePath -> (RawFilePath, RawFilePath) | |||
splitFileNameRaw = BS.breakEnd isPathSeparator | |||
combineRaw :: RawFilePath -> RawFilePath -> RawFilePath | |||
combineRaw a b | BS.null a = b | |||
| BS.null b = a | |||
| isPathSeparator (BS.last a) = BS.append a b | |||
| otherwise = BS.intercalate (BS.singleton pathSeparator) [a, b] | |||
@@ -1,47 +0,0 @@ | |||
# Revision history for hpath-io | |||
## 0.13.2 -- 2020-05-08 | |||
* Add getDirsFilesStream and use streamly-posix for dircontents (#34) | |||
## 0.13.0 -- 2020-01-26 | |||
* switch to using 'hpath-bytestring' for the implementation (this is now just a wrapper module, mostly) | |||
## 0.12.0 -- 2020-01-20 | |||
* breaking API changes | |||
* RelC and Fn were removed from `hpath` | |||
* further changes to `parseAny` | |||
## 0.11.0 -- 2020-01-18 | |||
* `writeFile` not allows to set file mode and create file if it does not exist (this broke API) | |||
* added various new functions: | |||
* createDirIfMissing | |||
* writeFileL (for lazy bytestring) | |||
* isReadable | |||
* isExecutable | |||
* getModificationTime | |||
* setModificationTime | |||
* setModificationTimeHiRes | |||
* getDirsFiles' (returns filenames instead of paths) | |||
* withRawFilePath | |||
* withHandle | |||
## 0.10.1 -- 2020-01-13 | |||
* Move file check functions to HPath.IO | |||
* Add 'doesExist' | |||
* Exception handling of `doesExist`, `doesFileExist`, `doesDirectoryExist` has changed: only eNOENT is catched | |||
* Exception handling of `isWritable` has changed: just a wrapper around `access` now | |||
* switch exception handling to `safe-exceptions` | |||
* Redo file reading API (readFileEOF dropped and now using streamly under the hood, added `readFileStream`) | |||
## 0.10.0 -- 2020-01-04 | |||
* First version. Split from 'hpath', contains only the IO parts. | |||
* Now uses streamly for 'copyFile' | |||
* Fixed tmpdir in hspec |
@@ -1,30 +0,0 @@ | |||
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. |
@@ -1,27 +0,0 @@ | |||
# 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. This uses [hpath-directory](https://hackage.haskell.org/package/hpath-directory) under the hood. | |||
This package is part of the HPath suite, also check out: | |||
* [hpath](https://hackage.haskell.org/package/hpath) | |||
* [hpath-directory](https://hackage.haskell.org/package/hpath-directory) | |||
* [hpath-filepath](https://hackage.haskell.org/package/hpath-filepath) | |||
## 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. | |||
@@ -1,2 +0,0 @@ | |||
import Distribution.Simple | |||
main = defaultMain |
@@ -1,6 +0,0 @@ | |||
# TODO | |||
## Tests | |||
* `doesExist` not tested | |||
* `readFileStream` only implicitly tested by `readFile` |
@@ -1,46 +0,0 @@ | |||
name: hpath-io | |||
version: 0.13.2 | |||
synopsis: High-level IO operations on files/directories | |||
description: High-level IO operations on files/directories, utilizing type-safe Paths | |||
license: BSD3 | |||
license-file: LICENSE | |||
author: Julian Ospald <hasufell@posteo.de> | |||
maintainer: Julian Ospald <hasufell@posteo.de> | |||
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: HPath.IO | |||
build-depends: base >= 4.8 && <5 | |||
, bytestring >= 0.10.0.0 | |||
, exceptions | |||
, hpath >= 0.11 && < 0.12 | |||
, hpath-directory >= 0.13 && < 0.14 | |||
, hpath-posix >= 0.13 && < 0.14 | |||
, safe-exceptions >= 0.1 | |||
, streamly >= 0.7 | |||
, time >= 1.8 | |||
, unix >= 2.5 | |||
if !impl(ghc>=7.11) | |||
build-depends: transformers | |||
hs-source-dirs: src | |||
default-language: Haskell2010 | |||
source-repository head | |||
type: git | |||
location: https://github.com/hasufell/hpath |
@@ -1,865 +0,0 @@ | |||
-- | |||
-- | |||
-- | |||
-- | |||
{-# LANGUAGE FlexibleContexts #-} -- streamly | |||
{-# LANGUAGE PackageImports #-} | |||
module HPath.IO | |||
( | |||
-- * Types | |||
FileType(..) | |||
, RecursiveErrorMode(..) | |||
, CopyMode(..) | |||
-- * File copying | |||
, copyDirRecursive | |||
, recreateSymlink | |||
, copyFile | |||
, easyCopy | |||
-- * File deletion | |||
, deleteFile | |||
, deleteDir | |||
, deleteDirRecursive | |||
, easyDelete | |||
-- * File opening | |||
, openFile | |||
, executeFile | |||
-- * File creation | |||
, createRegularFile | |||
, createDir | |||
, createDirIfMissing | |||
, createDirRecursive | |||
, createSymlink | |||
-- * File renaming/moving | |||
, renameFile | |||
, moveFile | |||
-- * File reading | |||
, readFile | |||
, readFileStream | |||
-- * File writing | |||
, writeFile | |||
, writeFileL | |||
, appendFile | |||
-- * File permissions | |||
, RD.newFilePerms | |||
, RD.newDirPerms | |||
-- * File checks | |||
, doesExist | |||
, doesFileExist | |||
, doesDirectoryExist | |||
, isReadable | |||
, isWritable | |||
, isExecutable | |||
, canOpenDirectory | |||
-- * File times | |||
, getModificationTime | |||
, setModificationTime | |||
, setModificationTimeHiRes | |||
-- * Directory reading | |||
, getDirsFiles | |||
, getDirsFiles' | |||
, getDirsFilesStream | |||
-- * Filetype operations | |||
, getFileType | |||
-- * Others | |||
, canonicalizePath | |||
, toAbs | |||
, withRawFilePath | |||
, withHandle | |||
, module System.Posix.RawFilePath.Directory.Errors | |||
) | |||
where | |||
import Control.Exception.Safe ( MonadMask | |||
, MonadCatch | |||
, bracketOnError | |||
, finally | |||
) | |||
import Control.Monad.Catch ( MonadThrow(..) ) | |||
import Data.ByteString ( ByteString ) | |||
import Data.Traversable ( for ) | |||
import qualified Data.ByteString.Lazy as L | |||
import Data.Time.Clock | |||
import Data.Time.Clock.POSIX ( POSIXTime ) | |||
import HPath | |||
import Prelude hiding ( appendFile | |||
, readFile | |||
, writeFile | |||
) | |||
import Streamly | |||
import qualified System.IO as SIO | |||
import System.Posix.Directory.ByteString | |||
( getWorkingDirectory ) | |||
import qualified "unix" System.Posix.IO.ByteString | |||
as SPI | |||
import System.Posix.FD ( openFd ) | |||
import System.Posix.RawFilePath.Directory.Errors | |||
import System.Posix.Types ( FileMode | |||
, ProcessID | |||
, EpochTime | |||
) | |||
import qualified System.Posix.RawFilePath.Directory | |||
as RD | |||
import System.Posix.RawFilePath.Directory | |||
( FileType | |||
, RecursiveErrorMode | |||
, CopyMode | |||
) | |||
-------------------- | |||
--[ File Copying ]-- | |||
-------------------- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
copyDirRecursive :: Path b1 -- ^ source dir | |||
-> Path b2 -- ^ destination (parent dirs | |||
-- are not automatically created) | |||
-> CopyMode | |||
-> RecursiveErrorMode | |||
-> IO () | |||
copyDirRecursive (Path fromp) (Path destdirp) cm rm = | |||
RD.copyDirRecursive fromp destdirp cm rm | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
recreateSymlink :: Path b1 -- ^ the old symlink file | |||
-> Path b2 -- ^ destination file | |||
-> CopyMode | |||
-> IO () | |||
recreateSymlink (Path symsourceBS) (Path newsymBS) cm = | |||
RD.recreateSymlink symsourceBS newsymBS cm | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
copyFile :: Path b1 -- ^ source file | |||
-> Path b2 -- ^ destination file | |||
-> CopyMode | |||
-> IO () | |||
copyFile (Path from) (Path to) cm = RD.copyFile from to cm | |||
-- | |||
-- | |||
-- | |||
easyCopy :: Path b1 -> Path b2 -> CopyMode -> RecursiveErrorMode -> IO () | |||
easyCopy (Path from) (Path to) cm rm = RD.easyCopy from to cm rm | |||
--------------------- | |||
--[ File Deletion ]-- | |||
--------------------- | |||
-- | |||
-- | |||
deleteFile :: Path b -> IO () | |||
deleteFile (Path p) = RD.deleteFile p | |||
-- | |||
-- | |||
-- | |||
deleteDir :: Path b -> IO () | |||
deleteDir (Path p) = RD.deleteDir p | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
deleteDirRecursive :: Path b -> IO () | |||
deleteDirRecursive (Path p) = RD.deleteDirRecursive p | |||
-- | |||
-- | |||
easyDelete :: Path b -> IO () | |||
easyDelete (Path p) = RD.easyDelete p | |||
-------------------- | |||
--[ File Opening ]-- | |||
-------------------- | |||
openFile :: Path b -> IO ProcessID | |||
openFile (Path fp) = RD.openFile fp | |||
executeFile :: Path b -- ^ program | |||
-> [ByteString] -- ^ arguments | |||
-> IO ProcessID | |||
executeFile (Path fp) args = RD.executeFile fp args | |||
--------------------- | |||
--[ File Creation ]-- | |||
--------------------- | |||
-- | |||
-- | |||
createRegularFile :: FileMode -> Path b -> IO () | |||
createRegularFile fm (Path destBS) = RD.createRegularFile fm destBS | |||
-- | |||
-- | |||
createDir :: FileMode -> Path b -> IO () | |||
createDir fm (Path destBS) = RD.createDir fm destBS | |||
-- | |||
-- | |||
createDirIfMissing :: FileMode -> Path b -> IO () | |||
createDirIfMissing fm (Path destBS) = RD.createDirIfMissing fm destBS | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
createDirRecursive :: FileMode -> Path b -> IO () | |||
createDirRecursive fm (Path p) = RD.createDirRecursive fm p | |||
-- | |||
-- | |||
-- | |||
createSymlink :: Path b -- ^ destination file | |||
-> ByteString -- ^ path the symlink points to | |||
-> IO () | |||
createSymlink (Path destBS) sympoint = RD.createSymlink destBS sympoint | |||
---------------------------- | |||
--[ File Renaming/Moving ]-- | |||
---------------------------- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
renameFile :: Path b1 -> Path b2 -> IO () | |||
renameFile (Path from) (Path to) = RD.renameFile from to | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
-- | |||
moveFile :: Path b1 -- ^ file to move | |||
-> Path b2 -- ^ destination | |||
-> CopyMode | |||
-> IO () | |||
moveFile (Path from) (Path to) cm = RD.moveFile from to cm | |||
-------------------- | |||
--[ File Reading ]-- | |||
-------------------- | |||
-- | |||
-- | |||
-- | |||
-- | |||
readFile :: Path b -> IO L.ByteString | |||
readFile (Path path) = RD.readFile path | |||
-- | |||
-- | |||
readFileStream :: Path b -> IO (SerialT IO ByteString) | |||
readFileStream (Path fp) = RD.readFileStream fp | |||
-------------------- | |||
--[ File Writing ]-- | |||
-------------------- | |||
-- | |||
-- | |||
writeFile :: Path b | |||
-> Maybe FileMode -- ^ if Nothing, file must exist | |||
-> ByteString | |||
-> IO () | |||
writeFile (Path fp) fmode bs = RD.writeFile fp fmode bs | |||
-- | |||
-- | |||
-- | |||
writeFileL :: Path b | |||
-> Maybe FileMode -- ^ if Nothing, file must exist | |||
-> L.ByteString | |||
-> IO () | |||
writeFileL (Path fp) fmode lbs = RD.writeFileL fp fmode lbs | |||
-- | |||
-- | |||
appendFile :: Path b -> ByteString -> IO () | |||
appendFile (Path fp) bs = RD.appendFile fp bs | |||
------------------- | |||
--[ File checks ]-- | |||
------------------- | |||
-- | |||
doesExist :: Path b -> IO Bool | |||
doesExist (Path bs) = RD.doesExist bs | |||
-- | |||
doesFileExist :: Path b -> IO Bool | |||
doesFileExist (Path bs) = RD.doesFileExist bs | |||
-- | |||
doesDirectoryExist :: Path b -> IO Bool | |||
doesDirectoryExist (Path bs) = RD.doesDirectoryExist bs | |||
-- | |||
-- | |||
-- | |||
isReadable :: Path b -> IO Bool | |||
isReadable (Path bs) = RD.isReadable bs | |||
-- | |||
-- | |||
-- | |||
isWritable :: Path b -> IO Bool | |||
isWritable (Path bs) = RD.isWritable bs | |||
-- | |||
-- | |||
-- | |||
isExecutable :: Path b -> IO Bool | |||
isExecutable (Path bs) = RD.isExecutable bs | |||
canOpenDirectory :: Path b -> IO Bool | |||
canOpenDirectory (Path bs) = RD.canOpenDirectory bs | |||
------------------ | |||
--[ File times ]-- | |||
------------------ | |||
getModificationTime :: Path b -> IO UTCTime | |||
getModificationTime (Path bs) = RD.getModificationTime bs | |||
setModificationTime :: Path b -> EpochTime -> IO () | |||
setModificationTime (Path bs) t = RD.setModificationTime bs t | |||
setModificationTimeHiRes :: Path b -> POSIXTime -> IO () | |||
setModificationTimeHiRes (Path bs) t = RD.setModificationTimeHiRes bs t | |||
------------------------- | |||
--[ Directory reading ]-- | |||
------------------------- | |||
-- | |||
-- | |||
-- | |||
getDirsFiles :: Path b -- ^ dir to read | |||
-> IO [Path b] | |||
getDirsFiles p = do | |||
contents <- getDirsFiles' p | |||
pure $ fmap (p </>) contents | |||
getDirsFiles' :: Path b -- ^ dir to read | |||
-> IO [Path Rel] | |||
getDirsFiles' (Path fp) = do | |||
rawContents <- RD.getDirsFiles' fp | |||
for rawContents $ \r -> parseRel r | |||
getDirsFilesStream :: (MonadCatch m, MonadAsync m, MonadMask m) | |||
=> Path b | |||
-> IO (SerialT m (Path Rel)) | |||
getDirsFilesStream (Path fp) = do | |||
s <- RD.getDirsFilesStream fp | |||
pure (s >>= parseRel) | |||
--------------------------- | |||
--[ FileType operations ]-- | |||
--------------------------- | |||
-- | |||
-- | |||
getFileType :: Path b -> IO FileType | |||
getFileType (Path fp) = RD.getFileType fp | |||
-------------- | |||
--[ Others ]-- | |||
-------------- | |||
-- | |||
-- | |||
canonicalizePath :: Path b -> IO (Path Abs) | |||
canonicalizePath (Path l) = do | |||
nl <- RD.canonicalizePath l | |||
parseAbs nl | |||
-- | |||
toAbs :: Path b -> IO (Path Abs) | |||
toAbs (Path bs) = do | |||
let mabs = parseAbs bs :: Maybe (Path Abs) | |||
case mabs of | |||
Just a -> return a | |||
Nothing -> do | |||
cwd <- getWorkingDirectory >>= parseAbs | |||
r <- parseRel bs -- we know it must be relative now | |||
return $ cwd </> r | |||
-- | |||
-- | |||
withRawFilePath :: MonadThrow m | |||
=> ByteString | |||
-> (Either (Path Abs) (Path Rel) -> m b) | |||
-> m b | |||
withRawFilePath bs action = do | |||
path <- parseAny bs | |||
action path | |||
-- | |||
-- | |||
-- | |||
withHandle :: ByteString | |||
-> SPI.OpenMode | |||
-> ((SIO.Handle, Either (Path Abs) (Path Rel)) -> IO a) | |||
-> IO a | |||
withHandle bs mode action = do | |||
path <- parseAny bs | |||
handle <- | |||
bracketOnError (openFd bs mode [] (Just RD.newFilePerms)) (SPI.closeFd) | |||
$ SPI.fdToHandle | |||
finally (action (handle, path)) (SIO.hClose handle) |
@@ -1,14 +0,0 @@ | |||
# Revision history for hpath-posix | |||
## 0.13.2 -- 2020-04-14 | |||
* fix macOS compatibility, especially with memory bug in `fdopendir` | |||
## 0.13.1 -- 2020-02-08 | |||
* Remove unnecessary dependencies | |||
## 0.13.0 -- 2020-01-29 | |||
* First version. Released on an unsuspecting world. |
@@ -1,30 +0,0 @@ | |||
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. |
@@ -1,13 +0,0 @@ | |||
# 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-posix.svg?label=Hackage)](https://hackage.haskell.org/package/hpath-posix) [![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-posix.svg)](http://packdeps.haskellers.com/feed?needle=hpath-posix) | |||
Some low-level POSIX glue code, that is not in 'unix'. | |||
This package is part of the HPath suite, also check out: | |||
* [hpath](https://hackage.haskell.org/package/hpath) | |||
* [hpath-directory](https://hackage.haskell.org/package/hpath-directory) | |||
* [hpath-filepath](https://hackage.haskell.org/package/hpath-filepath) | |||
* [hpath-io](https://hackage.haskell.org/package/hpath-io) | |||
@@ -1,2 +0,0 @@ | |||
import Distribution.Simple | |||
main = defaultMain |
@@ -1,7 +0,0 @@ | |||
#include "dirutils.h" | |||
unsigned int | |||
__posixdir_d_type(struct dirent* d) | |||
{ | |||
return(d -> d_type); | |||
} |
@@ -1,15 +0,0 @@ | |||
#ifndef POSIXPATHS_CBITS_DIRUTILS_H | |||
#define POSIXPATHS_CBITS_DIRUTILS_H | |||
#include <stdlib.h> | |||
#include <dirent.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <fcntl.h> | |||
extern unsigned int | |||
__posixdir_d_type(struct dirent* d) | |||
; | |||
#endif |
@@ -1,48 +0,0 @@ | |||
cabal-version: >=1.10 | |||
name: hpath-posix | |||
version: 0.13.2 | |||
synopsis: Some low-level POSIX glue code, that is not in 'unix' | |||
homepage: https://github.com/hasufell/hpath | |||
bug-reports: https://github.com/hasufell/hpath/issues | |||
license: BSD3 | |||
license-file: LICENSE | |||
author: Julian Ospald <hasufell@posteo.de> | |||
maintainer: Julian Ospald <hasufell@posteo.de> | |||
copyright: Julian Ospald <hasufell@posteo.de> 2020 | |||
category: Filesystem | |||
build-type: Simple | |||
extra-source-files: CHANGELOG.md | |||
cbits/dirutils.h | |||
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 | |||
library | |||
if os(windows) | |||
build-depends: unbuildable<0 | |||
buildable: False | |||
exposed-modules: System.Posix.RawFilePath.Directory.Traversals | |||
System.Posix.Foreign | |||
System.Posix.FD | |||
-- other-modules: | |||
-- other-extensions: | |||
c-sources: cbits/dirutils.c | |||
build-depends: base >= 4.8 && <5 | |||
, bytestring >= 0.10 | |||
, hpath-filepath >= 0.10.3 | |||
, unix >= 2.5 | |||
if impl(ghc < 8.0) | |||
build-depends: | |||
fail >= 4.9 | |||
hs-source-dirs: src | |||
default-language: Haskell2010 | |||
default-extensions: PackageImports | |||
source-repository head | |||
type: git | |||
location: https://github.com/hasufell/hpath |
@@ -1,75 +0,0 @@ | |||
-- | |||
-- | |||
{-# LANGUAGE ForeignFunctionInterface #-} | |||
{-# LANGUAGE OverloadedStrings #-} | |||
{-# LANGUAGE TupleSections #-} | |||
{-# OPTIONS_GHC -Wall #-} | |||
module System.Posix.FD ( | |||
openFd | |||
) where | |||
import Foreign.C.String | |||
import Foreign.C.Types | |||
import System.Posix.Foreign | |||
import qualified System.Posix as Posix | |||
import System.Posix.ByteString.FilePath | |||
foreign import ccall unsafe "open" | |||
c_open :: CString -> CInt -> Posix.CMode -> IO CInt | |||
open_ :: CString | |||
-> Posix.OpenMode | |||
-> [Flags] | |||
-> Maybe Posix.FileMode | |||
-> IO Posix.Fd | |||
open_ str how optional_flags maybe_mode = do | |||
fd <- c_open str all_flags mode_w | |||
return (Posix.Fd fd) | |||
where | |||
all_flags = unionFlags $ optional_flags ++ [open_mode] ++ creat | |||
(creat, mode_w) = case maybe_mode of | |||
Nothing -> ([],0) | |||
Just x -> ([oCreat], x) | |||
open_mode = case how of | |||
Posix.ReadOnly -> oRdonly | |||
Posix.WriteOnly -> oWronly | |||
Posix.ReadWrite -> oRdwr | |||
-- | |||
openFd :: RawFilePath | |||
-> Posix.OpenMode | |||
-> [Flags] -- ^ status flags of @open(2)@ | |||
-> Maybe Posix.FileMode -- ^ @Just x@ => creates the file with the given modes, Nothing => the file must exist. | |||
-> IO Posix.Fd | |||
openFd name how optional_flags maybe_mode = | |||
withFilePath name $ \str -> | |||
throwErrnoPathIfMinus1Retry "openFd" name $ | |||
open_ str how optional_flags maybe_mode | |||
@@ -1,55 +0,0 @@ | |||
module System.Posix.Foreign where | |||
import Data.Bits | |||
import Data.List (foldl') | |||
import Foreign.C.Types | |||
#include <limits.h> | |||
#include <stdlib.h> | |||
#include <dirent.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <fcntl.h> | |||
newtype DirType = DirType Int deriving (Eq, Show) | |||
data Flags = Flags Int | UnsupportedFlag String deriving (Eq, Show) | |||
unFlags :: Flags -> Int | |||
unFlags (Flags i) = i | |||
unFlags (UnsupportedFlag name) = error (name ++ " is not supported on this platform") | |||
isSupported :: Flags -> Bool | |||
isSupported (Flags _) = True | |||
isSupported _ = False | |||
oCloexec :: Flags | |||
#ifdef O_CLOEXEC | |||
oCloexec = Flags #{const O_CLOEXEC} | |||
#else | |||
{-# WARNING oCloexec | |||
"This version of posix-paths was compiled without @O_CLOEXEC@ support." #-} | |||
oCloexec = UnsupportedFlag "O_CLOEXEC" | |||
#endif | |||
#{enum DirType, DirType, DT_BLK, DT_CHR, DT_DIR, DT_FIFO, DT_LNK, DT_REG, DT_SOCK, DT_UNKNOWN} | |||
#{enum Flags, Flags, O_APPEND, O_ASYNC, O_CREAT, O_DIRECTORY, O_EXCL, O_NOCTTY, O_NOFOLLOW, O_NONBLOCK, O_RDONLY, O_WRONLY, O_RDWR, O_SYNC, O_TRUNC} | |||
pathMax :: Int | |||
pathMax = #{const PATH_MAX} | |||
unionFlags :: [Flags] -> CInt | |||
unionFlags = fromIntegral . foldl' ((. unFlags) . (.|.)) 0 |
@@ -1,268 +0,0 @@ | |||
-- | |||
-- | |||
{-# LANGUAGE CApiFFI #-} | |||
{-# LANGUAGE CPP #-} | |||
{-# LANGUAGE ForeignFunctionInterface #-} | |||
{-# LANGUAGE OverloadedStrings #-} | |||
{-# LANGUAGE TupleSections #-} | |||
{-# LANGUAGE ViewPatterns #-} | |||
{-# OPTIONS_GHC -Wall #-} | |||
module System.Posix.RawFilePath.Directory.Traversals ( | |||
getDirectoryContents | |||
, getDirectoryContents' | |||
, allDirectoryContents | |||
, allDirectoryContents' | |||
, traverseDirectory | |||
, readDirEnt | |||
, packDirStream | |||
, unpackDirStream | |||
, fdOpendir | |||
, realpath | |||
) where | |||
#if __GLASGOW_HASKELL__ < 710 | |||
import Control.Applicative ((<$>)) | |||
#endif | |||
import Control.Monad | |||
import System.Posix.FilePath ((</>)) | |||
import System.Posix.Foreign | |||
import qualified System.Posix as Posix | |||
import System.IO.Error | |||
import Control.Exception | |||
import qualified Data.ByteString.Char8 as BS | |||
import System.Posix.ByteString.FilePath | |||
import System.Posix.Directory.ByteString as PosixBS | |||
import System.Posix.Files.ByteString | |||
import System.IO.Unsafe | |||
import "unix" System.Posix.IO.ByteString (closeFd) | |||
import Unsafe.Coerce (unsafeCoerce) | |||
import Foreign.C.Error | |||
import Foreign.C.String | |||
import Foreign.C.Types | |||
import Foreign.Marshal.Alloc (alloca,allocaBytes) | |||
import Foreign.Ptr | |||
import Foreign.Storable | |||
---------------------------------------------------------- | |||
-- | |||
-- | |||
allDirectoryContents :: RawFilePath -> IO [RawFilePath] | |||
allDirectoryContents topdir = do | |||
namesAndTypes <- getDirectoryContents topdir | |||
let properNames = filter ((`notElem` [".", ".."]) . snd) namesAndTypes | |||
paths <- forM properNames $ \(typ,name) -> unsafeInterleaveIO $ do | |||
let path = topdir </> name | |||
case () of | |||
() | typ == dtDir -> allDirectoryContents path | |||
| typ == dtUnknown -> do | |||
isDir <- isDirectory <$> getFileStatus path | |||
if isDir | |||
then allDirectoryContents path | |||
else return [path] | |||
| otherwise -> return [path] | |||
return (topdir : concat paths) | |||
-- | |||
allDirectoryContents' :: RawFilePath -> IO [RawFilePath] | |||
allDirectoryContents' = fmap reverse . traverseDirectory (\acc fp -> return (fp:acc)) [] | |||
-- | |||
-- | |||
traverseDirectory :: (s -> RawFilePath -> IO s) -> s -> RawFilePath -> IO s | |||
traverseDirectory act s0 topdir = toploop | |||
where | |||
toploop = do | |||
isDir <- isDirectory <$> getFileStatus topdir | |||
s' <- act s0 topdir | |||
if isDir then actOnDirContents topdir s' loop | |||
else return s' | |||
loop typ path acc = do | |||
isDir <- case () of | |||
() | typ == dtDir -> return True | |||
| typ == dtUnknown -> isDirectory <$> getFileStatus path | |||
| otherwise -> return False | |||
if isDir | |||
then act acc path >>= \acc' -> actOnDirContents path acc' loop | |||
else act acc path | |||
actOnDirContents :: RawFilePath | |||
-> b | |||
-> (DirType -> RawFilePath -> b -> IO b) | |||
-> IO b | |||
actOnDirContents pathRelToTop b f = | |||
modifyIOError ((`ioeSetFileName` (BS.unpack pathRelToTop)) . | |||
(`ioeSetLocation` "findBSTypRel")) $ | |||
bracket | |||
(openDirStream pathRelToTop) | |||
Posix.closeDirStream | |||
(\dirp -> loop dirp b) | |||
where | |||
loop dirp b' = do | |||
(typ,e) <- readDirEnt dirp | |||
if (e == "") | |||
then return b' | |||
else | |||
if (e == "." || e == "..") | |||
then loop dirp b' | |||
else f typ (pathRelToTop </> e) b' >>= loop dirp | |||
---------------------------------------------------------- | |||
type CDir = () | |||
type CDirent = () | |||
unpackDirStream :: DirStream -> Ptr CDir | |||
unpackDirStream = unsafeCoerce | |||
packDirStream :: Ptr CDir -> DirStream | |||
packDirStream = unsafeCoerce | |||
foreign import ccall unsafe "__hscore_readdir" | |||
c_readdir :: Ptr CDir -> Ptr (Ptr CDirent) -> IO CInt | |||
foreign import ccall unsafe "__hscore_free_dirent" | |||
c_freeDirEnt :: Ptr CDirent -> IO () | |||
foreign import ccall unsafe "__hscore_d_name" | |||
c_name :: Ptr CDirent -> IO CString | |||
foreign import ccall unsafe "__posixdir_d_type" | |||
c_type :: Ptr CDirent -> IO DirType | |||
foreign import capi "stdlib.h realpath" | |||
c_realpath :: CString -> CString -> IO CString | |||
foreign import capi unsafe "dirent.h fdopendir" | |||
c_fdopendir :: Posix.Fd -> IO (Ptr CDir) | |||
---------------------------------------------------------- | |||
readDirEnt :: DirStream -> IO (DirType, RawFilePath) | |||
readDirEnt (unpackDirStream -> dirp) = | |||
alloca $ \ptr_dEnt -> loop ptr_dEnt | |||
where | |||
loop ptr_dEnt = do | |||
resetErrno | |||
r <- c_readdir dirp ptr_dEnt | |||
if (r == 0) | |||
then do | |||
dEnt <- peek ptr_dEnt | |||
if (dEnt == nullPtr) | |||
then return (dtUnknown,BS.empty) | |||
else do | |||
dName <- c_name dEnt >>= peekFilePath | |||
dType <- c_type dEnt | |||
c_freeDirEnt dEnt | |||
return (dType, dName) | |||
else do | |||
errno <- getErrno | |||
if (errno == eINTR) | |||
then loop ptr_dEnt | |||
else do | |||
let (Errno eo) = errno | |||
if (eo == 0) | |||
then return (dtUnknown,BS.empty) | |||
else throwErrno "readDirEnt" | |||
getDirectoryContents :: RawFilePath -> IO [(DirType, RawFilePath)] | |||
getDirectoryContents path = | |||
modifyIOError ((`ioeSetFileName` (BS.unpack path)) . | |||
(`ioeSetLocation` "System.Posix.RawFilePath.Directory.Traversals.getDirectoryContents")) $ | |||
bracket | |||
(PosixBS.openDirStream path) | |||
PosixBS.closeDirStream | |||
_dirloop | |||
fdOpendir :: Posix.Fd -> IO DirStream | |||
fdOpendir fd = | |||
packDirStream <$> throwErrnoIfNull "fdOpendir" (c_fdopendir fd) | |||
-- | |||
getDirectoryContents' :: Posix.Fd -> IO [(DirType, RawFilePath)] | |||
getDirectoryContents' fd = do | |||
dirstream <- fdOpendir fd `catchIOError` \e -> do | |||
closeFd fd | |||
ioError e | |||
-- closeDirStream closes the filedescriptor | |||
finally (_dirloop dirstream) (PosixBS.closeDirStream dirstream) | |||
_dirloop :: DirStream -> IO [(DirType, RawFilePath)] | |||
{-# INLINE _dirloop #-} | |||
_dirloop dirp = do | |||
t@(_typ,e) <- readDirEnt dirp | |||
if BS.null e then return [] else do | |||
es <- _dirloop dirp | |||
return (t:es) | |||
-- | |||
realpath :: RawFilePath -> IO RawFilePath | |||
realpath inp = | |||
allocaBytes pathMax $ \tmp -> do | |||
void $ BS.useAsCString inp $ \cstr -> throwErrnoIfNull "realpath" $ c_realpath cstr tmp | |||
BS.packCString tmp |
@@ -1,89 +0,0 @@ | |||
0.11.0 | |||
* Many API breaking changes | |||
* Remove RelC and Fn, because they complicate API/break semantics (see #29) | |||
* Redo 'parseAny' | |||
* Unexpose HPath.Internal | |||
* Don't preserve trailing path separators (if you need to pass something to a C function that way, do it manually) | |||
* Added `rooPath`, `isRootPath`, `getAllComponents`, `getAllComponentsAfterRoot` | |||
0.10.2 | |||
* Add `parseAny` and the related QuasiQuoter | |||
0.10.1 | |||
* Add quasi quoters for hpath | |||
0.10.0 | |||
* split packages, this one now just contains the type-safe Path wrappers | |||
0.9.2 | |||
* fix build with ghc-7.6 | |||
* raise required bytestring version | |||
* Tighten base bound to prevent building before GHC 7.6 (by George Wilson) | |||
0.9.1 | |||
* fix build with ghc-7.8 and 7.10 | |||
0.9.0 | |||
* don't force "Path Abs" anymore in IO module, abstract more over Path types | |||
* add 'toAbs' | |||
0.8.1 | |||
* add 'readFile', 'readFileEOF', 'writeFile' and 'appendFile' | |||
0.8.0 | |||
* 'copyDirRecursiveOverwrite', 'copyFileOverwrite', 'easyCopyOverwrite' and 'moveFileOverwrite' have been removed, instead use the versions without the *Overwrite suffix and pass in 'Strict' (for default behavior) or 'Overwrite' as the CopyMode argument | |||
* introduced a new 'RecursiveErrorMode' type to allow controlling recursive behavior of 'copyDirRecursive' (use 'FailEarly' for default behavior) | |||
* 'createRegularFile' and 'createDir' now take FileMode as a parameter (also see 'newFilePerms' and 'newDirPerms') | |||
* various documentation fixes | |||
* improved reliability of tests | |||
0.7.5: | |||
* relicense to BSD3 | |||
0.7.3: | |||
* don't expose HPath.Internal | |||
0.7.2: | |||
* fix tests, so they work with the sdist tarball too | |||
* added the following function to HPath.IO: createSymlink | |||
0.7.1: | |||
* various cleanups and documentation improvements | |||
* added the following functions to System.Posix.FilePath: splitSearchPath, getSearchPath, stripExtension, makeRelative, makeValid | |||
0.7.0: | |||
* use 'sendfile' from 'simple-sendfile' in _copyFile and do read/write as a fallback only | |||
* add isFileName, hasParentDir, hiddenFile to System.Posix.FilePath | |||
* add our own openFd version for more control | |||
* small documentation improvements | |||
* add a getDirectoryContents' version that works on Fd | |||
* lift version constraints in benchmark | |||
* remove fpToString and userStringToFP, use Data.ByteString.UTF8 directly instead | |||
0.6.0: | |||
* fixes 'throwDestinationInSource' to be more reliable. | |||
* removes some unused HPathIOException constructors | |||
* consistently provide exception constructor identifiers | |||
* be less harsh when non-supported file types get passed to our functions, possibly ignoring them | |||
* minor cleanups | |||
0.5.9: | |||
* Adds our posix-paths fork and a lot of IO operations. | |||
0.5.8: | |||
* First version of the fork. | |||
0.5.7: | |||
* Fix haddock problem. | |||
0.5.6: | |||
* Reject only .. and . | |||
0.5.5: | |||
* Use filepath's isValid function for additional sanity checks | |||
0.5.4: | |||
* Disable parsing of path consisting only of "." | |||
* Add NFData instance for Path | |||
* Some typo/docs improvements | |||
* Add standard headers to modules | |||
0.5.3: | |||
* Added conversion functions. | |||
0.2.0: | |||
* Rename parentAbs to simply parent. | |||
* Add dirname. | |||
0.3.0: | |||
* Removed Generic instance. | |||
0.4.0: | |||
* Implemented stricter parsing, disabling use of "..". | |||
* Made stripDir generic over MonadThrow | |||
0.5.0: | |||
* Fix stripDir p p /= Nothing bug. | |||
0.5.2: | |||
* Removed unused DeriveGeneric. |
@@ -1,30 +0,0 @@ | |||
Copyright (c) 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: | |||
1. Redistributions of source code must retain the above copyright | |||
notice, this list of conditions and the following disclaimer. | |||
2. 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. | |||
3. Neither the name of the author nor the names of his contributors | |||
may be used to endorse or promote products derived from this software | |||
without specific prior written permission. | |||
THIS SOFTWARE IS PROVIDED BY THE 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 AUTHORS 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. |
@@ -1,40 +0,0 @@ | |||
# 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. | |||
This package is part of the HPath suite, also check out: | |||
* [hpath-directory](https://hackage.haskell.org/package/hpath-directory) | |||
* [hpath-filepath](https://hackage.haskell.org/package/hpath-filepath) | |||
* [hpath-io](https://hackage.haskell.org/package/hpath-io) | |||
## 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... | |||
* 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 | |||
* 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` |