Hello community, here is the log from the commit of package ghc-zip-archive for openSUSE:Factory checked in at 2018-05-30 12:16:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-zip-archive (Old) and /work/SRC/openSUSE:Factory/.ghc-zip-archive.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-zip-archive" Wed May 30 12:16:11 2018 rev:10 rq:607959 version:0.3.2.4 Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-zip-archive/ghc-zip-archive.changes 2017-07-06 00:03:58.709405162 +0200 +++ /work/SRC/openSUSE:Factory/.ghc-zip-archive.new/ghc-zip-archive.changes 2018-05-30 12:28:01.104782987 +0200 @@ -1,0 +2,20 @@ +Mon May 14 17:02:11 UTC 2018 - psim...@suse.com + +- Update zip-archive to version 0.3.2.4. + * Use createSymbolicLink instead of createFileLink in tests. This allows + us to lower the directory lower bound (#40). + + * Fixes for handling of symbolic links (#39, Tommaso Piazza). + + * Fixes for symbolic link tests, and additional tests. + + * Add ZipOption to preserve symbolic links (#37, Tommaso Piazza). + Add OptPreserveSymbolicLinks constructor to ZipOption. If this option + is set, symbolic links will be preserved. Symbolic links are not + supported on Windows. + + * Require binary >= 0.6 (#36). + + * Improve exit handling in zip-archive program. + +------------------------------------------------------------------- Old: ---- zip-archive-0.3.1.1.tar.gz New: ---- zip-archive-0.3.2.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-zip-archive.spec ++++++ --- /var/tmp/diff_new_pack.mslXzy/_old 2018-05-30 12:28:01.808758131 +0200 +++ /var/tmp/diff_new_pack.mslXzy/_new 2018-05-30 12:28:01.808758131 +0200 @@ -1,7 +1,7 @@ # # spec file for package ghc-zip-archive # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,12 +19,12 @@ %global pkg_name zip-archive %bcond_with tests Name: ghc-%{pkg_name} -Version: 0.3.1.1 +Version: 0.3.2.4 Release: 0 Summary: Library for creating and modifying zip archives License: BSD-3-Clause -Group: Development/Languages/Other -Url: https://hackage.haskell.org/package/%{pkg_name} +Group: Development/Libraries/Haskell +URL: https://hackage.haskell.org/package/%{pkg_name} Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz BuildRequires: ghc-Cabal-devel BuildRequires: ghc-array-devel @@ -42,7 +42,7 @@ BuildRequires: ghc-time-devel BuildRequires: ghc-unix-devel BuildRequires: ghc-zlib-devel -BuildRoot: %{_tmppath}/%{name}-%{version}-build +BuildRequires: unzip %if %{with tests} BuildRequires: ghc-HUnit-devel BuildRequires: ghc-process-devel @@ -55,7 +55,7 @@ %package devel Summary: Haskell %{pkg_name} library development files -Group: Development/Libraries/Other +Group: Development/Libraries/Haskell Requires: %{name} = %{version}-%{release} Requires: ghc-compiler = %{ghc_version} Requires(post): ghc-compiler = %{ghc_version} @@ -83,11 +83,9 @@ %ghc_pkg_recache %files -f %{name}.files -%defattr(-,root,root,-) -%doc LICENSE +%license LICENSE %files devel -f %{name}-devel.files -%defattr(-,root,root,-) %doc README.markdown changelog %changelog ++++++ zip-archive-0.3.1.1.tar.gz -> zip-archive-0.3.2.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zip-archive-0.3.1.1/Main.hs new/zip-archive-0.3.2.4/Main.hs --- old/zip-archive-0.3.1.1/Main.hs 2017-06-04 13:08:55.000000000 +0200 +++ new/zip-archive-0.3.2.4/Main.hs 2018-01-22 21:11:33.000000000 +0100 @@ -44,6 +44,14 @@ , Option ['h'] ["help"] (NoArg Help) "help" ] +quit :: Bool -> String -> IO a +quit failure msg = do + hPutStr stderr msg + _ <- exitWith $ if failure + then ExitFailure 1 + else ExitSuccess + return undefined + main :: IO () main = do argv <- getArgs @@ -53,9 +61,10 @@ (o, _, _) | Version `elem` o -> do putStrLn ("version " ++ showVersion version) exitWith ExitSuccess - (o, _, _) | Help `elem` o -> error $ usageInfo header options + (o, _, _) | Help `elem` o -> quit False $ usageInfo header options (o, (a:as), []) -> return (o, a:as) - (_, _, errs) -> error $ concat errs ++ "\n" ++ usageInfo header options + (_, [], []) -> quit True $ usageInfo header options + (_, _, errs) -> quit True $ concat errs ++ "\n" ++ usageInfo header options let verbosity = if Quiet `elem` opts then [] else [OptVerbose] let debug = Debug `elem` opts let cmd = case filter (`notElem` [Quiet, Help, Version, Debug]) opts of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zip-archive-0.3.1.1/Setup.hs new/zip-archive-0.3.2.4/Setup.hs --- old/zip-archive-0.3.1.1/Setup.hs 2017-06-04 13:52:37.000000000 +0200 +++ new/zip-archive-0.3.2.4/Setup.hs 2018-02-12 19:12:13.000000000 +0100 @@ -1,2 +1,8 @@ import Distribution.Simple -main = defaultMain +import Distribution.Simple.Program + +main :: IO () +main = defaultMainWithHooks simpleUserHooks + { hookedPrograms = [ simpleProgram "unzip" + ] + } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zip-archive-0.3.1.1/changelog new/zip-archive-0.3.2.4/changelog --- old/zip-archive-0.3.1.1/changelog 2017-06-19 10:39:30.000000000 +0200 +++ new/zip-archive-0.3.2.4/changelog 2018-02-21 23:27:59.000000000 +0100 @@ -1,3 +1,33 @@ +zip-archive 0.3.2.4 + + * Make build-tools stanza conditional on non-windows. Closes #44. + +zip-archive 0.3.2.3 + + * Use custom-setup stanza and specify build-tools. Closes #41. + +zip-archive 0.3.2.2 + + * Use createSymbolicLink instead of createFileLink in tests. This allows + us to lower the directory lower bound (#40). + +zip-archive 0.3.2.1 + + * Fixes for handling of symbolic links (#39, Tommaso Piazza). + + * Fixes for symbolic link tests, and additional tests. + +zip-archive 0.3.2 + + * Add ZipOption to preserve symbolic links (#37, Tommaso Piazza). + Add OptPreserveSymbolicLinks constructor to ZipOption. If this option + is set, symbolic links will be preserved. Symbolic links are not + supported on Windows. + + * Require binary >= 0.6 (#36). + + * Improve exit handling in zip-archive program. + zip-archive 0.3.1.1 * readEntry: Read file as a strict ByteString. This avoids diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zip-archive-0.3.1.1/src/Codec/Archive/Zip.hs new/zip-archive-0.3.2.4/src/Codec/Archive/Zip.hs --- old/zip-archive-0.3.1.1/src/Codec/Archive/Zip.hs 2017-06-19 10:31:55.000000000 +0200 +++ new/zip-archive-0.3.2.4/src/Codec/Archive/Zip.hs 2018-01-22 21:12:49.000000000 +0100 @@ -48,10 +48,18 @@ , findEntryByPath , fromEntry , toEntry +#ifndef _WINDOWS + , isEntrySymbolicLink + , symbolicLinkEntryTarget + , entryCMode +#endif -- * IO functions for working with zip archives , readEntry , writeEntry +#ifndef _WINDOWS + , writeSymbolicLinkEntry +#endif , addFilesToArchive , extractFilesFromArchive @@ -65,8 +73,9 @@ import Data.Binary import Data.Binary.Get import Data.Binary.Put -import Data.List ( nub, find, intercalate ) +import Data.List ( nub, find, intercalate, partition) import Data.Data (Data) +import Data.Maybe (fromJust) import Data.Typeable (Typeable) import Text.Printf import System.FilePath @@ -81,12 +90,14 @@ import Control.Applicative #endif #ifndef _WINDOWS -import System.Posix.Files ( setFileTimes, setFileMode, fileMode, getFileStatus ) +import System.Posix.Files ( setFileTimes, setFileMode, fileMode, getSymbolicLinkStatus, symbolicLinkMode, readSymbolicLink, isSymbolicLink, unionFileModes, createSymbolicLink ) +import System.Posix.Types ( CMode(..) ) #endif -- from bytestring import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as B +import qualified Data.ByteString.Lazy.Char8 as C (pack, unpack) -- text import qualified Data.Text.Lazy as TL @@ -155,6 +166,7 @@ | OptVerbose -- ^ Print information to stderr | OptDestination FilePath -- ^ Directory in which to extract | OptLocation FilePath Bool -- ^ Where to place file when adding files and whether to append current path + | OptPreserveSymbolicLinks -- ^ Preserve symbolic links as such. This option is ignored on Windows. deriving (Read, Show, Eq) data ZipException = @@ -252,17 +264,34 @@ readEntry :: [ZipOption] -> FilePath -> IO Entry readEntry opts path = do isDir <- doesDirectoryExist path - -- make sure directories end in / and deal with the OptLocation option +#ifdef _WINDOWS + let isSymLink = False +#else + fs <- getSymbolicLinkStatus path + let isSymLink = isSymbolicLink fs +#endif + -- make sure directories end in / and deal with the OptLocation option let path' = let p = path ++ (case reverse path of ('/':_) -> "" - _ | isDir -> "/" + _ | isDir && not isSymLink -> "/" + _ | isDir && isSymLink -> "" | otherwise -> "") in (case [(l,a) | OptLocation l a <- opts] of ((l,a):_) -> if a then l </> p else l </> takeFileName p _ -> p) - contents <- if isDir - then return B.empty - else B.fromStrict <$> S.readFile path + contents <- +#ifndef _WINDOWS + if isSymLink + then do + linkTarget <- readSymbolicLink path + return $ C.pack linkTarget + else +#endif + if isDir + then + return B.empty + else + B.fromStrict <$> S.readFile path #if MIN_VERSION_directory(1,2,0) modEpochTime <- fmap (floor . utcTimeToPOSIXSeconds) $ getModificationTime path @@ -275,7 +304,11 @@ #ifdef _WINDOWS return $ entry #else - do fm <- fmap fileMode $ getFileStatus path + do + let fm = if isSymLink + then unionFileModes symbolicLinkMode (fileMode fs) + else fileMode fs + let modes = fromIntegral $ shiftL (toInteger fm) 16 return $ entry { eExternalFileAttributes = modes, eVersionMadeBy = versionMadeBy } @@ -319,20 +352,62 @@ #ifndef _WINDOWS let modes = fromIntegral $ shiftR (eExternalFileAttributes entry) 16 when (eVersionMadeBy entry .&. 0xFF00 == 0x0300 && - modes /= 0) $ setFileMode path modes + modes /= 0) $ setFileMode path modes #endif - -- Note that last modified times are supported only for POSIX, not for -- Windows. setFileTimeStamp path (eLastModified entry) +#ifndef _WINDOWS +-- | Write an 'Entry' representing a symbolic link to a file. +-- If the 'Entry' does not represent a symbolic link or +-- the options do not contain 'OptPreserveSymbolicLinks`, this +-- function behaves like `writeEntry`. +writeSymbolicLinkEntry :: [ZipOption] -> Entry -> IO () +writeSymbolicLinkEntry opts entry = do + if OptPreserveSymbolicLinks `notElem` opts + then writeEntry opts entry + else do + if (isEntrySymbolicLink entry) + then do + let prefixPath = case [d | OptDestination d <- opts] of + (x:_) -> x + _ -> "" + let targetPath = fromJust . symbolicLinkEntryTarget $ entry + let symlinkPath = prefixPath </> eRelativePath entry + when (OptVerbose `elem` opts) $ do + hPutStrLn stderr $ "linking " ++ symlinkPath ++ " to " ++ targetPath + createSymbolicLink targetPath symlinkPath + else writeEntry opts entry + + +-- | Get the target of a 'Entry' representing a symbolic link. This might fail +-- if the 'Entry' does not represent a symbolic link +symbolicLinkEntryTarget :: Entry -> Maybe FilePath +symbolicLinkEntryTarget entry | isEntrySymbolicLink entry = Just . C.unpack $ fromEntry entry + | otherwise = Nothing + +-- | Check if an 'Entry' represents a symbolic link +isEntrySymbolicLink :: Entry -> Bool +isEntrySymbolicLink entry = entryCMode entry .&. symbolicLinkMode == symbolicLinkMode + +-- | Get the 'eExternalFileAttributes' of an 'Entry' as a 'CMode' a.k.a. 'FileMode' +entryCMode :: Entry -> CMode +entryCMode entry = CMode (fromIntegral $ shiftR (eExternalFileAttributes entry) 16) +#endif + -- | Add the specified files to an 'Archive'. If 'OptRecursive' is specified, --- recursively add files contained in directories. If 'OptVerbose' is specified, +-- recursively add files contained in directories. if 'OptPreserveSymbolicLinks' +-- is specified, don't recurse into it. If 'OptVerbose' is specified, -- print messages to stderr. addFilesToArchive :: [ZipOption] -> Archive -> [FilePath] -> IO Archive addFilesToArchive opts archive files = do filesAndChildren <- if OptRecursive `elem` opts +#ifdef _WINDOWS then mapM getDirectoryContentsRecursive files >>= return . nub . concat +#else + then mapM (getDirectoryContentsRecursive' opts) files >>= return . nub . concat +#endif else return files entries <- mapM (readEntry opts) filesAndChildren return $ foldr addEntryToArchive archive entries @@ -342,8 +417,17 @@ -- Note that the last-modified time is set correctly only in POSIX, -- not in Windows. extractFilesFromArchive :: [ZipOption] -> Archive -> IO () -extractFilesFromArchive opts archive = - mapM_ (writeEntry opts) $ zEntries archive +extractFilesFromArchive opts archive = do + if OptPreserveSymbolicLinks `elem` opts + then do +#ifdef _WINDOWS + mapM_ (writeEntry opts) $ zEntries archive +#else + let (symbolicLinkEntries, nonSymbolicLinkEntries) = partition isEntrySymbolicLink $ zEntries archive + mapM_ (writeEntry opts) $ nonSymbolicLinkEntries + mapM_ (writeSymbolicLinkEntry opts) $ symbolicLinkEntries +#endif + else mapM_ (writeEntry opts) $ zEntries archive -------------------------------------------------------------------------------- -- Internal functions for reading and writing zip binary format. @@ -426,18 +510,38 @@ (TOD epochsecs _) = addToClockTime timeSinceEpoch (TOD 0 0) in epochsecs +#ifndef _WINDOWS +getDirectoryContentsRecursive' :: [ZipOption] -> FilePath -> IO [FilePath] +getDirectoryContentsRecursive' opts path = do + if OptPreserveSymbolicLinks `elem` opts + then do + isDir <- doesDirectoryExist path + if isDir + then do + isSymLink <- fmap isSymbolicLink $ getSymbolicLinkStatus path + if isSymLink + then return [path] + else getDirectoryContentsRecursivelyBy (getDirectoryContentsRecursive' opts) path + else return [path] + else getDirectoryContentsRecursive path +#endif + getDirectoryContentsRecursive :: FilePath -> IO [FilePath] getDirectoryContentsRecursive path = do isDir <- doesDirectoryExist path if isDir - then do + then getDirectoryContentsRecursivelyBy getDirectoryContentsRecursive path + else return [path] + +getDirectoryContentsRecursivelyBy :: (FilePath -> IO [FilePath]) -> FilePath -> IO [FilePath] +getDirectoryContentsRecursivelyBy exploreMethod path = do contents <- getDirectoryContents path let contents' = map (path </>) $ filter (`notElem` ["..","."]) contents - children <- mapM getDirectoryContentsRecursive contents' + children <- mapM exploreMethod contents' if path == "." then return (concat children) else return (path : concat children) - else return [path] + setFileTimeStamp :: FilePath -> Integer -> IO () setFileTimeStamp file epochtime = do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zip-archive-0.3.1.1/tests/test-zip-archive.hs new/zip-archive-0.3.2.4/tests/test-zip-archive.hs --- old/zip-archive-0.3.1.1/tests/test-zip-archive.hs 2017-06-19 10:17:27.000000000 +0200 +++ new/zip-archive-0.3.2.4/tests/test-zip-archive.hs 2018-02-12 19:09:05.000000000 +0100 @@ -4,17 +4,21 @@ -- runghc Test.hs import Codec.Archive.Zip -import System.Directory +import Control.Applicative +import System.Directory hiding (isSymbolicLink) import Test.HUnit.Base import Test.HUnit.Text import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy as BL -import Control.Applicative import System.Exit import System.IO.Temp (withTempDirectory) #ifndef _WINDOWS +import System.FilePath.Posix import System.Posix.Files +import System.Process (rawSystem) +#else +import System.FilePath.Windows #endif -- define equality for Archives so timestamps aren't distinguished if they @@ -25,6 +29,23 @@ && (all id $ zipWith (\x y -> x { eLastModified = eLastModified x `div` 2 } == y { eLastModified = eLastModified y `div` 2 }) (zEntries a1) (zEntries a2)) +#ifndef _WINDOWS + +createTestDirectoryWithSymlinks :: FilePath -> FilePath -> IO FilePath +createTestDirectoryWithSymlinks prefixDir baseDir = do + let testDir = prefixDir </> baseDir + createDirectoryIfMissing True testDir + createDirectoryIfMissing True (testDir </> "1") + writeFile (testDir </> "1/file.txt") "hello" + cwd <- getCurrentDirectory + createSymbolicLink (cwd </> testDir </> "1/file.txt") (testDir </> "link_to_file") + createSymbolicLink (cwd </> testDir </> "1") (testDir </> "link_to_directory") + return testDir + +#endif + + + main :: IO Counts main = withTempDirectory "." "test-zip-archive." $ \tmpDir -> do res <- runTestTT $ TestList $ map (\f -> f tmpDir) @@ -37,6 +58,9 @@ , testExtractFiles #ifndef _WINDOWS , testExtractFilesWithPosixAttrs + , testArchiveExtractSymlinks + , testExtractExternalZipWithSymlinks + , testArchiveAndUnzip #endif ] exitWith $ case (failures res + errors res) of @@ -46,8 +70,8 @@ testReadWriteArchive :: FilePath -> Test testReadWriteArchive tmpDir = TestCase $ do archive <- addFilesToArchive [OptRecursive] emptyArchive ["LICENSE", "src"] - BL.writeFile (tmpDir ++ "/test1.zip") $ fromArchive archive - archive' <- toArchive <$> BL.readFile (tmpDir ++ "/test1.zip") + BL.writeFile (tmpDir </> "test1.zip") $ fromArchive archive + archive' <- toArchive <$> BL.readFile (tmpDir </> "test1.zip") assertEqual "for writing and reading test1.zip" archive archive' assertEqual "for writing and reading test1.zip" archive archive' @@ -69,9 +93,14 @@ BL.empty (fromEntry f) testFromToArchive :: FilePath -> Test -testFromToArchive _tmpDir = TestCase $ do - archive <- addFilesToArchive [OptRecursive] emptyArchive ["LICENSE", "src"] - assertEqual "for (toArchive $ fromArchive archive)" archive (toArchive $ fromArchive archive) +testFromToArchive tmpDir = TestCase $ do + archive1 <- addFilesToArchive [OptRecursive] emptyArchive ["LICENSE", "src"] + assertEqual "for (toArchive $ fromArchive archive)" archive1 (toArchive $ fromArchive archive1) +#ifndef _WINDOWS + testDir <- createTestDirectoryWithSymlinks tmpDir "test_dir_with_symlinks" + archive2 <- addFilesToArchive [OptRecursive, OptPreserveSymbolicLinks] emptyArchive [testDir] + assertEqual "for (toArchive $ fromArchive archive)" archive2 (toArchive $ fromArchive archive2) +#endif testReadWriteEntry :: FilePath -> Test testReadWriteEntry tmpDir = TestCase $ do @@ -79,16 +108,26 @@ setCurrentDirectory tmpDir writeEntry [] entry setCurrentDirectory ".." - entry' <- readEntry [] (tmpDir ++ "/zip-archive.cabal") + entry' <- readEntry [] (tmpDir </> "zip-archive.cabal") let entry'' = entry' { eRelativePath = eRelativePath entry, eLastModified = eLastModified entry } assertEqual "for readEntry -> writeEntry -> readEntry" entry entry'' testAddFilesOptions :: FilePath -> Test -testAddFilesOptions _tmpDir = TestCase $ do +testAddFilesOptions tmpDir = TestCase $ do archive1 <- addFilesToArchive [OptVerbose] emptyArchive ["LICENSE", "src"] archive2 <- addFilesToArchive [OptRecursive, OptVerbose] archive1 ["LICENSE", "src"] assertBool "for recursive and nonrecursive addFilesToArchive" (length (filesInArchive archive1) < length (filesInArchive archive2)) +#ifndef _WINDOWS + testDir <- createTestDirectoryWithSymlinks tmpDir "test_dir_with_symlinks2" + archive3 <- addFilesToArchive [OptVerbose, OptRecursive] emptyArchive [testDir] + archive4 <- addFilesToArchive [OptVerbose, OptRecursive, OptPreserveSymbolicLinks] emptyArchive [testDir] + mapM_ putStrLn $ filesInArchive archive3 + mapM_ putStrLn $ filesInArchive archive4 + assertBool "for recursive and recursive by preserving symlinks addFilesToArchive" + (length (filesInArchive archive4) < length (filesInArchive archive3)) +#endif + testDeleteEntries :: FilePath -> Test testDeleteEntries _tmpDir = TestCase $ do @@ -99,33 +138,88 @@ testExtractFiles :: FilePath -> Test testExtractFiles tmpDir = TestCase $ do - createDirectory (tmpDir ++ "/dir1") - createDirectory (tmpDir ++ "/dir1/dir2") + createDirectory (tmpDir </> "dir1") + createDirectory (tmpDir </> "dir1/dir2") let hiMsg = BS.pack "hello there" let helloMsg = BS.pack "Hello there. This file is very long. Longer than 31 characters." - BS.writeFile (tmpDir ++ "/dir1/hi") hiMsg - BS.writeFile (tmpDir ++ "/dir1/dir2/hello") helloMsg - archive <- addFilesToArchive [OptRecursive] emptyArchive [(tmpDir ++ "/dir1")] - removeDirectoryRecursive (tmpDir ++ "/dir1") + BS.writeFile (tmpDir </> "dir1/hi") hiMsg + BS.writeFile (tmpDir </> "dir1/dir2/hello") helloMsg + archive <- addFilesToArchive [OptRecursive] emptyArchive [(tmpDir </> "dir1")] + removeDirectoryRecursive (tmpDir </> "dir1") extractFilesFromArchive [OptVerbose] archive - hi <- BS.readFile (tmpDir ++ "/dir1/hi") - hello <- BS.readFile (tmpDir ++ "/dir1/dir2/hello") - assertEqual ("contents of " ++ tmpDir ++ "/dir1/hi") hiMsg hi - assertEqual ("contents of " ++ tmpDir ++ "/dir1/dir2/hello") helloMsg hello + hi <- BS.readFile (tmpDir </> "dir1/hi") + hello <- BS.readFile (tmpDir </> "dir1/dir2/hello") + assertEqual ("contents of " </> tmpDir </> "dir1/hi") hiMsg hi + assertEqual ("contents of " </> tmpDir </> "dir1/dir2/hello") helloMsg hello #ifndef _WINDOWS + testExtractFilesWithPosixAttrs :: FilePath -> Test testExtractFilesWithPosixAttrs tmpDir = TestCase $ do - createDirectory (tmpDir ++ "/dir3") + createDirectory (tmpDir </> "dir3") let hiMsg = "hello there" - writeFile (tmpDir ++ "/dir3/hi") hiMsg + writeFile (tmpDir </> "dir3/hi") hiMsg let perms = unionFileModes ownerReadMode $ unionFileModes ownerWriteMode ownerExecuteMode - setFileMode (tmpDir ++ "/dir3/hi") perms - archive <- addFilesToArchive [OptRecursive] emptyArchive [(tmpDir ++ "/dir3")] - removeDirectoryRecursive (tmpDir ++ "/dir3") + setFileMode (tmpDir </> "dir3/hi") perms + archive <- addFilesToArchive [OptRecursive] emptyArchive [(tmpDir </> "dir3")] + removeDirectoryRecursive (tmpDir </> "dir3") extractFilesFromArchive [OptVerbose] archive - hi <- readFile (tmpDir ++ "/dir3/hi") - fm <- fmap fileMode $ getFileStatus (tmpDir ++ "/dir3/hi") + hi <- readFile (tmpDir </> "dir3/hi") + fm <- fmap fileMode $ getFileStatus (tmpDir </> "dir3/hi") assertEqual "file modes" perms (intersectFileModes perms fm) - assertEqual ("contents of " ++ tmpDir ++ "/dir3/hi") hiMsg hi + assertEqual ("contents of " </> tmpDir </> "dir3/hi") hiMsg hi + +testArchiveExtractSymlinks :: FilePath -> Test +testArchiveExtractSymlinks tmpDir = TestCase $ do + testDir <- createTestDirectoryWithSymlinks tmpDir "test_dir_with_symlinks3" + let locationDir = "location_dir" + archive <- addFilesToArchive [OptRecursive, OptPreserveSymbolicLinks, OptLocation locationDir True] emptyArchive [testDir] + removeDirectoryRecursive testDir + let destination = "test_dest" + extractFilesFromArchive [OptPreserveSymbolicLinks, OptDestination destination] archive + isDirSymlink <- pathIsSymbolicLink (destination </> locationDir </> testDir </> "link_to_directory") + isFileSymlink <- pathIsSymbolicLink (destination </> locationDir </> testDir </> "link_to_file") + assertBool "Symbolic link to directory is preserved" isDirSymlink + assertBool "Symbolic link to file is preserved" isFileSymlink + removeDirectoryRecursive destination + +testExtractExternalZipWithSymlinks :: FilePath -> Test +testExtractExternalZipWithSymlinks tmpDir = TestCase $ do + archive <- toArchive <$> BL.readFile "tests/zip_with_symlinks.zip" + extractFilesFromArchive [OptPreserveSymbolicLinks, OptDestination tmpDir] archive + let zipRootDir = "zip_test_dir_with_symlinks" + symlinkDir = tmpDir </> zipRootDir </> "symlink_to_dir_1" + symlinkFile = tmpDir </> zipRootDir </> "symlink_to_file_1" + isDirSymlink <- pathIsSymbolicLink symlinkDir + targetDirExists <- doesDirectoryExist symlinkDir + isFileSymlink <- pathIsSymbolicLink symlinkFile + targetFileExists <- doesFileExist symlinkFile + assertBool "Symbolic link to directory is preserved" isDirSymlink + assertBool "Target directory exists" targetDirExists + assertBool "Symbolic link to file is preserved" isFileSymlink + assertBool "Target file exists" targetFileExists + removeDirectoryRecursive tmpDir + +testArchiveAndUnzip :: FilePath -> Test +testArchiveAndUnzip tmpDir = TestCase $ do + let dir = "test_dir_with_symlinks4" + testDir <- createTestDirectoryWithSymlinks tmpDir dir + archive <- addFilesToArchive [OptRecursive, OptPreserveSymbolicLinks] emptyArchive [testDir] + removeDirectoryRecursive testDir + let zipFile = tmpDir </> "testUnzip.zip" + BL.writeFile zipFile $ fromArchive archive + ec <- rawSystem "unzip" [zipFile] + assertBool "unzip succeeds" $ ec == ExitSuccess + let symlinkDir = testDir </> "link_to_directory" + symlinkFile = testDir </> "link_to_file" + isDirSymlink <- pathIsSymbolicLink symlinkDir + targetDirExists <- doesDirectoryExist symlinkDir + isFileSymlink <- pathIsSymbolicLink symlinkFile + targetFileExists <- doesFileExist symlinkFile + assertBool "Symbolic link to directory is preserved" isDirSymlink + assertBool "Target directory exists" targetDirExists + assertBool "Symbolic link to file is preserved" isFileSymlink + assertBool "Target file exists" targetFileExists + removeDirectoryRecursive tmpDir + #endif Binary files old/zip-archive-0.3.1.1/tests/zip_with_symlinks.zip and new/zip-archive-0.3.2.4/tests/zip_with_symlinks.zip differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zip-archive-0.3.1.1/zip-archive.cabal new/zip-archive-0.3.2.4/zip-archive.cabal --- old/zip-archive-0.3.1.1/zip-archive.cabal 2017-06-19 09:47:36.000000000 +0200 +++ new/zip-archive-0.3.2.4/zip-archive.cabal 2018-02-21 23:27:40.000000000 +0100 @@ -1,23 +1,24 @@ Name: zip-archive -Version: 0.3.1.1 +Version: 0.3.2.4 Cabal-Version: >= 1.10 -Build-type: Simple +Build-type: Custom Synopsis: Library for creating and modifying zip archives. Description: The zip-archive library provides functions for creating, modifying, and extracting files from zip archives. Category: Codec -Tested-with: GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.2 +Tested-with: GHC == 7.8.2, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2 License: BSD3 License-file: LICENSE Homepage: http://github.com/jgm/zip-archive Author: John MacFarlane Maintainer: j...@berkeley.edu -Extra-Source-Files: changelog, - README.markdown, - tests/test4.zip, - tests/test4/a.txt, - tests/test4/b.bin, +Extra-Source-Files: changelog + README.markdown + tests/test4.zip + tests/test4/a.txt + tests/test4/b.bin "tests/test4/c/with spaces.txt" + tests/zip_with_symlinks.zip Source-repository head type: git @@ -35,7 +36,7 @@ Build-depends: base >= 3 && < 5, pretty, containers else Build-depends: base < 3 - Build-depends: binary >= 0.5, zlib, filepath, bytestring >= 0.10.0, + Build-depends: binary >= 0.6, zlib, filepath, bytestring >= 0.10.0, array, mtl, text >= 0.11, old-time, digest >= 0.0.0.1, directory, time Exposed-modules: Codec.Archive.Zip @@ -46,6 +47,10 @@ cpp-options: -D_WINDOWS else Build-depends: unix + Build-tools: unzip + +custom-setup + setup-depends: base, Cabal Executable zip-archive if flag(executable) @@ -65,8 +70,8 @@ Main-Is: test-zip-archive.hs Hs-Source-Dirs: tests Build-Depends: base >= 4.2 && < 5, - directory, bytestring >= 0.9.0, process, time, old-time, - HUnit, zip-archive, temporary + directory >= 1.3, bytestring >= 0.9.0, process, time, old-time, + HUnit, zip-archive, temporary, filepath Default-Language: Haskell98 Ghc-Options: -Wall if os(windows)