From 048eaa14522fdbdf84ae0cb3215e75db9af83f5e Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov <mikhail.glushenkov@gmail.com> Date: Thu, 9 May 2013 22:22:59 +0200 Subject: [PATCH] Avoid the timestamp check for `add-source --snapshot` dependencies. Snapshot deps now behave more like `cabal-dev add-source`. Implemented by adding a BuildTreeRefType field to the BuildRef index entry. Fixes #1321. --- .../Distribution/Client/IndexUtils.hs | 71 +++++++---- cabal-install/Distribution/Client/Sandbox.hs | 18 +-- .../Distribution/Client/Sandbox/Index.hs | 111 ++++++++++++------ .../Distribution/Client/Sandbox/Timestamp.hs | 6 +- cabal-install/Distribution/Client/Tar.hs | 13 ++ 5 files changed, 150 insertions(+), 69 deletions(-) diff --git a/cabal-install/Distribution/Client/IndexUtils.hs b/cabal-install/Distribution/Client/IndexUtils.hs index 3a57e619ec..9a2c463578 100644 --- a/cabal-install/Distribution/Client/IndexUtils.hs +++ b/cabal-install/Distribution/Client/IndexUtils.hs @@ -20,6 +20,8 @@ module Distribution.Client.IndexUtils ( parsePackageIndex, readRepoIndex, updateRepoIndexCache, + + BuildTreeRefType(..), refTypeFromTypeCode, typeCodeFromRefType ) where import qualified Distribution.Client.Tar as Tar @@ -189,8 +191,8 @@ readRepoIndex verbosity repo mode = packageInfoId = pkgid, packageDescription = packageDesc pkgEntry, packageSource = case pkgEntry of - NormalPackage _ _ _ _ -> RepoTarballPackage repo pkgid Nothing - BuildTreeRef _ _ path _ -> LocalUnpackedPackage path, + NormalPackage _ _ _ _ -> RepoTarballPackage repo pkgid Nothing + BuildTreeRef _ _ _ path _ -> LocalUnpackedPackage path, packageDescrOverride = case pkgEntry of NormalPackage _ _ pkgtxt _ -> Just pkgtxt _ -> Nothing @@ -250,17 +252,33 @@ whenCacheOutOfDate origFile cacheFile action = do -- | An index entry is either a normal package, or a local build tree reference. data PackageEntry = NormalPackage PackageId GenericPackageDescription ByteString BlockNo - | BuildTreeRef PackageId GenericPackageDescription FilePath BlockNo + | BuildTreeRef BuildTreeRefType + PackageId GenericPackageDescription FilePath BlockNo + +-- | A build tree reference is either a link or a snapshot. +data BuildTreeRefType = SnapshotRef | LinkRef + deriving Eq + +refTypeFromTypeCode :: Tar.TypeCode -> BuildTreeRefType +refTypeFromTypeCode t + | t == Tar.buildTreeRefTypeCode = LinkRef + | t == Tar.buildTreeSnapshotTypeCode = SnapshotRef + | otherwise = + error "Distribution.Client.IndexUtils.refTypeFromTypeCode: unknown type code" + +typeCodeFromRefType :: BuildTreeRefType -> Tar.TypeCode +typeCodeFromRefType LinkRef = Tar.buildTreeRefTypeCode +typeCodeFromRefType SnapshotRef = Tar.buildTreeSnapshotTypeCode type MkPackageEntry = IO PackageEntry instance Package PackageEntry where - packageId (NormalPackage pkgid _ _ _) = pkgid - packageId (BuildTreeRef pkgid _ _ _) = pkgid + packageId (NormalPackage pkgid _ _ _) = pkgid + packageId (BuildTreeRef _ pkgid _ _ _) = pkgid packageDesc :: PackageEntry -> GenericPackageDescription -packageDesc (NormalPackage _ descr _ _) = descr -packageDesc (BuildTreeRef _ descr _ _) = descr +packageDesc (NormalPackage _ descr _ _) = descr +packageDesc (BuildTreeRef _ _ descr _ _) = descr -- | Read a compressed \"00-index.tar.gz\" file into a 'PackageIndex'. -- @@ -332,12 +350,13 @@ extractPkg entry blockNo = case Tar.entryContent entry of _ -> Nothing Tar.OtherEntryType typeCode content _ - | typeCode == Tar.buildTreeRefTypeCode -> + | Tar.isBuildTreeRefTypeCode typeCode -> Just $ do let path = byteStringToFilePath content cabalFile <- findPackageDesc path descr <- PackageDesc.Parse.readPackageDescription normal cabalFile - return $ BuildTreeRef (packageId descr) descr path blockNo + return $ BuildTreeRef (refTypeFromTypeCode typeCode) (packageId descr) + descr path blockNo _ -> Nothing @@ -375,8 +394,8 @@ updatePackageIndexCacheFile indexFile cacheFile = do [ CachePreference pref | pref <- prefs ] ++ [ CachePackageId pkgid blockNo | (NormalPackage pkgid _ _ blockNo) <- pkgs ] - ++ [ CacheBuildTreeRef blockNo - | (BuildTreeRef _ _ _ blockNo) <- pkgs] + ++ [ CacheBuildTreeRef refType blockNo + | (BuildTreeRef refType _ _ _ blockNo) <- pkgs] data ReadPackageIndexMode = ReadPackageIndexStrict | ReadPackageIndexLazyIO @@ -430,14 +449,14 @@ packageIndexFromCache mkPkg hnd entrs mode = accum mempty [] entrs pkgtxt blockno) accum (srcpkg:srcpkgs) prefs entries - accum srcpkgs prefs (CacheBuildTreeRef blockno : entries) = do + accum srcpkgs prefs (CacheBuildTreeRef refType blockno : entries) = do -- We have to read the .cabal file eagerly here because we can't cache the -- package id for build tree references - the user might edit the .cabal -- file after the reference was added to the index. path <- liftM byteStringToFilePath . getEntryContent $ blockno pkg <- do cabalFile <- findPackageDesc path PackageDesc.Parse.readPackageDescription normal cabalFile - let srcpkg = mkPkg (BuildTreeRef (packageId pkg) pkg path blockno) + let srcpkg = mkPkg (BuildTreeRef refType (packageId pkg) pkg path blockno) accum (srcpkg:srcpkgs) prefs entries accum srcpkgs prefs (CachePreference pref : entries) = @@ -457,7 +476,7 @@ packageIndexFromCache mkPkg hnd entrs mode = accum mempty [] entrs case Tar.entryContent e of Tar.NormalFile _ size -> return size Tar.OtherEntryType typecode _ size - | typecode == Tar.buildTreeRefTypeCode + | Tar.isBuildTreeRefTypeCode typecode -> return size _ -> interror "unexpected tar entry type" _ -> interror "could not read tar file entry" @@ -482,9 +501,9 @@ packageIndexFromCache mkPkg hnd entrs mode = accum mempty [] entrs type BlockNo = Int data IndexCacheEntry = CachePackageId PackageId BlockNo - | CacheBuildTreeRef BlockNo + | CacheBuildTreeRef BuildTreeRefType BlockNo | CachePreference Dependency - deriving (Eq, Show) + deriving (Eq) readIndexCacheEntry :: BSS.ByteString -> Maybe IndexCacheEntry readIndexCacheEntry = \line -> @@ -496,10 +515,12 @@ readIndexCacheEntry = \line -> (Just pkgname, Just pkgver, Just blockno) -> Just (CachePackageId (PackageIdentifier pkgname pkgver) blockno) _ -> Nothing - [key, blocknostr] | key == buildTreeRefKey -> - case parseBlockNo blocknostr of - Just blockno -> Just (CacheBuildTreeRef blockno) - _ -> Nothing + [key, typecodestr, blocknostr] | key == buildTreeRefKey -> + case (parseRefType typecodestr, parseBlockNo blocknostr) of + (Just refType, Just blockno) + -> Just (CacheBuildTreeRef refType blockno) + _ -> Nothing + (key: remainder) | key == preferredVersionKey -> fmap CachePreference (simpleParse (BSS.unpack (BSS.unwords remainder))) _ -> Nothing @@ -527,12 +548,20 @@ readIndexCacheEntry = \line -> Just (blockno, remainder) | BSS.null remainder -> Just blockno _ -> Nothing + parseRefType str = + case BSS.uncons str of + Just (typeCode, remainder) + | BSS.null remainder && Tar.isBuildTreeRefTypeCode typeCode + -> Just (refTypeFromTypeCode typeCode) + _ -> Nothing + showIndexCacheEntry :: IndexCacheEntry -> String showIndexCacheEntry entry = case entry of CachePackageId pkgid b -> "pkg: " ++ display (packageName pkgid) ++ " " ++ display (packageVersion pkgid) ++ " b# " ++ show b - CacheBuildTreeRef b -> "build-tree-ref: " ++ show b + CacheBuildTreeRef t b -> "build-tree-ref: " ++ (typeCodeFromRefType t:" ") + ++ show b CachePreference dep -> "pref-ver: " ++ display dep readIndexCache :: BSS.ByteString -> [IndexCacheEntry] diff --git a/cabal-install/Distribution/Client/Sandbox.hs b/cabal-install/Distribution/Client/Sandbox.hs index ae18b62793..8ce48b0abb 100644 --- a/cabal-install/Distribution/Client/Sandbox.hs +++ b/cabal-install/Distribution/Client/Sandbox.hs @@ -46,6 +46,7 @@ import Distribution.Client.Sandbox.Timestamp ( maybeAddCompilerTimestampRecord , withModifiedDeps ) import Distribution.Client.Config ( SavedConfig(..), loadConfig ) import Distribution.Client.Dependency ( foldProgress ) +import Distribution.Client.IndexUtils ( BuildTreeRefType(..) ) import Distribution.Client.Install ( InstallArgs, makeInstallContext, makeInstallPlan, @@ -288,8 +289,10 @@ sandboxDelete verbosity _sandboxFlags globalFlags = do removeDirectoryRecursive sandboxDir -- Common implementation of 'sandboxAddSource' and 'sandboxAddSourceSnapshot'. -doAddSource :: Verbosity -> [FilePath] -> FilePath -> PackageEnvironment -> IO () -doAddSource verbosity buildTreeRefs sandboxDir pkgEnv = do +doAddSource :: Verbosity -> [FilePath] -> FilePath -> PackageEnvironment + -> BuildTreeRefType + -> IO () +doAddSource verbosity buildTreeRefs sandboxDir pkgEnv refType = do let savedConfig = pkgEnvSavedConfig pkgEnv indexFile <- tryGetIndexFilePath savedConfig @@ -303,7 +306,7 @@ doAddSource verbosity buildTreeRefs sandboxDir pkgEnv = do -- FIXME: path canonicalisation is done in addBuildTreeRefs, but we do it -- twice because of the timestamps file. buildTreeRefs' <- mapM tryCanonicalizePath buildTreeRefs - Index.addBuildTreeRefs verbosity indexFile buildTreeRefs' + Index.addBuildTreeRefs verbosity indexFile buildTreeRefs' refType return buildTreeRefs' -- | Entry point for the 'cabal sandbox add-source' command. @@ -315,7 +318,7 @@ sandboxAddSource verbosity buildTreeRefs sandboxFlags globalFlags = do if fromFlagOrDefault False (sandboxSnapshot sandboxFlags) then sandboxAddSourceSnapshot verbosity buildTreeRefs sandboxDir pkgEnv - else doAddSource verbosity buildTreeRefs sandboxDir pkgEnv + else doAddSource verbosity buildTreeRefs sandboxDir pkgEnv LinkRef -- | Entry point for the 'cabal sandbox add-source --snapshot' command. sandboxAddSourceSnapshot :: Verbosity -> [FilePath] -> FilePath @@ -360,7 +363,7 @@ sandboxAddSourceSnapshot verbosity buildTreeRefs sandboxDir pkgEnv = do return targetDir -- Once the packages are copied, just 'add-source' them as usual. - doAddSource verbosity snapshots sandboxDir pkgEnv + doAddSource verbosity snapshots sandboxDir pkgEnv SnapshotRef -- | Entry point for the 'cabal sandbox delete-source' command. sandboxDeleteSource :: Verbosity -> [FilePath] -> SandboxFlags -> GlobalFlags @@ -385,7 +388,8 @@ sandboxListSources verbosity _sandboxFlags globalFlags = do (globalConfigFile globalFlags) indexFile <- tryGetIndexFilePath (pkgEnvSavedConfig pkgEnv) - refs <- Index.listBuildTreeRefs verbosity Index.ListIgnored indexFile + refs <- Index.listBuildTreeRefs verbosity + Index.ListIgnored Index.LinksAndSnapshots indexFile when (null refs) $ notice verbosity $ "Index file '" ++ indexFile ++ "' has no references to local build trees." @@ -477,7 +481,7 @@ reinstallAddSourceDeps verbosity config configFlags' configExFlags { configDistPref = Flag (sandboxBuildDir sandboxDir) } indexFile <- tryGetIndexFilePath config buildTreeRefs <- Index.listBuildTreeRefs verbosity - Index.DontListIgnored indexFile + Index.DontListIgnored Index.OnlyLinks indexFile retVal <- newIORef NoDepsReinstalled unless (null buildTreeRefs) $ do diff --git a/cabal-install/Distribution/Client/Sandbox/Index.hs b/cabal-install/Distribution/Client/Sandbox/Index.hs index c4f4d39eb5..8c1038650c 100644 --- a/cabal-install/Distribution/Client/Sandbox/Index.hs +++ b/cabal-install/Distribution/Client/Sandbox/Index.hs @@ -11,7 +11,7 @@ module Distribution.Client.Sandbox.Index ( createEmpty, addBuildTreeRefs, removeBuildTreeRefs, - ListIgnoredBuildTreeRefs(..), + ListIgnoredBuildTreeRefs(..), RefTypesToList(..), listBuildTreeRefs, validateIndexPath, @@ -19,7 +19,10 @@ module Distribution.Client.Sandbox.Index ( ) where import qualified Distribution.Client.Tar as Tar -import Distribution.Client.IndexUtils ( getSourcePackagesStrict ) +import Distribution.Client.IndexUtils ( BuildTreeRefType(..) + , refTypeFromTypeCode + , typeCodeFromRefType + , getSourcePackagesStrict ) import Distribution.Client.PackageIndex ( allPackages ) import Distribution.Client.Types ( Repo(..), LocalRepo(..) , SourcePackageDb(..) @@ -33,7 +36,7 @@ import Distribution.Verbosity ( Verbosity ) import qualified Data.ByteString.Lazy as BS import Control.Exception ( evaluate ) import Control.Monad ( liftM, unless ) -import Data.List ( (\\), nub ) +import Data.List ( (\\), intersect, nub ) import Data.Maybe ( catMaybes ) import System.Directory ( createDirectoryIfMissing, doesDirectoryExist, doesFileExist, @@ -43,55 +46,56 @@ import System.IO ( IOMode(..), SeekMode(..) , hSeek, withBinaryFile ) -- | A reference to a local build tree. -newtype BuildTreeRef = BuildTreeRef { - buildTreePath :: FilePath +data BuildTreeRef = BuildTreeRef { + buildTreeRefType :: !BuildTreeRefType, + buildTreePath :: !FilePath } defaultIndexFileName :: FilePath defaultIndexFileName = "00-index.tar" -- | Given a path, ensure that it refers to a local build tree. -buildTreeRefFromPath :: FilePath -> IO (Maybe BuildTreeRef) -buildTreeRefFromPath dir = do +buildTreeRefFromPath :: BuildTreeRefType -> FilePath -> IO (Maybe BuildTreeRef) +buildTreeRefFromPath refType dir = do dirExists <- doesDirectoryExist dir unless dirExists $ die $ "directory '" ++ dir ++ "' does not exist" _ <- findPackageDesc dir - return . Just $ BuildTreeRef { buildTreePath = dir } + return . Just $ BuildTreeRef refType dir -- | Given a tar archive entry, try to parse it as a local build tree reference. -readBuildTreePath :: Tar.Entry -> Maybe FilePath -readBuildTreePath entry = case Tar.entryContent entry of +readBuildTreeRef :: Tar.Entry -> Maybe BuildTreeRef +readBuildTreeRef entry = case Tar.entryContent entry of (Tar.OtherEntryType typeCode bs size) - | (typeCode == Tar.buildTreeRefTypeCode) - && (size == BS.length bs) -> Just $ byteStringToFilePath bs + | (Tar.isBuildTreeRefTypeCode typeCode) + && (size == BS.length bs) -> Just $! BuildTreeRef + (refTypeFromTypeCode typeCode) + (byteStringToFilePath bs) | otherwise -> Nothing _ -> Nothing -- | Given a sequence of tar archive entries, extract all references to local -- build trees. -readBuildTreePaths :: Tar.Entries -> [FilePath] -readBuildTreePaths = +readBuildTreeRefs :: Tar.Entries -> [BuildTreeRef] +readBuildTreeRefs = catMaybes - . Tar.foldrEntries (\e r -> readBuildTreePath e : r) + . Tar.foldrEntries (\e r -> readBuildTreeRef e : r) [] error -- | Given a path to a tar archive, extract all references to local build trees. -readBuildTreePathsFromFile :: FilePath -> IO [FilePath] -readBuildTreePathsFromFile = liftM (readBuildTreePaths . Tar.read) - . BS.readFile +readBuildTreeRefsFromFile :: FilePath -> IO [BuildTreeRef] +readBuildTreeRefsFromFile = liftM (readBuildTreeRefs . Tar.read) . BS.readFile --- | Given a local build tree, serialise it to a tar archive entry. +-- | Given a local build tree ref, serialise it to a tar archive entry. writeBuildTreeRef :: BuildTreeRef -> Tar.Entry -writeBuildTreeRef lbt = Tar.simpleEntry tarPath content +writeBuildTreeRef (BuildTreeRef refType path) = Tar.simpleEntry tarPath content where bs = filePathToByteString path - path = buildTreePath lbt - -- fromRight can't fail because the path is shorter than 255 characters. - tarPath = fromRight $ Tar.toTarPath True tarPath' -- Provide a filename for tools that treat custom entries as ordinary files. tarPath' = "local-build-tree-reference" - content = Tar.OtherEntryType Tar.buildTreeRefTypeCode bs (BS.length bs) + -- fromRight can't fail because the path is shorter than 255 characters. + tarPath = fromRight $ Tar.toTarPath True tarPath' + content = Tar.OtherEntryType (typeCodeFromRefType refType) bs (BS.length bs) -- TODO: Move this to D.C.Utils? fromRight (Left err) = error err @@ -123,15 +127,16 @@ createEmpty verbosity path = do BS.writeFile path zeros -- | Add given local build tree references to the index. -addBuildTreeRefs :: Verbosity -> FilePath -> [FilePath] -> IO () -addBuildTreeRefs _ _ [] = +addBuildTreeRefs :: Verbosity -> FilePath -> [FilePath] -> BuildTreeRefType + -> IO () +addBuildTreeRefs _ _ [] _ = error "Distribution.Client.Sandbox.Index.addBuildTreeRefs: unexpected" -addBuildTreeRefs verbosity path l' = do +addBuildTreeRefs verbosity path l' refType = do checkIndexExists path l <- liftM nub . mapM tryCanonicalizePath $ l' - treesInIndex <- readBuildTreePathsFromFile path + treesInIndex <- fmap (map buildTreePath) (readBuildTreeRefsFromFile path) -- Add only those paths that aren't already in the index. - treesToAdd <- mapM buildTreeRefFromPath (l \\ treesInIndex) + treesToAdd <- mapM (buildTreeRefFromPath refType) (l \\ treesInIndex) let entries = map writeBuildTreeRef (catMaybes treesToAdd) unless (null entries) $ do offset <- @@ -162,9 +167,12 @@ removeBuildTreeRefs verbosity path l' = do debug verbosity $ "Successfully renamed '" ++ tmpFile ++ "' to '" ++ path ++ "'" where - p l entry = case readBuildTreePath entry of - Nothing -> True - (Just pth) -> pth `notElem` l + p l entry = case readBuildTreeRef entry of + Nothing -> True + -- FIXME: removing snapshot deps is done with `delete-source + -- .cabal-sandbox/snapshots/$SNAPSHOT_NAME`. Perhaps we also want to + -- support removing snapshots by providing the original path. + (Just (BuildTreeRef _ pth)) -> pth `notElem` l -- | A build tree ref can become ignored if the user later adds a build tree ref -- with the same package ID. We display ignored build tree refs when the user @@ -172,14 +180,44 @@ removeBuildTreeRefs verbosity path l' = do -- 'reinstallAddSourceDeps'. data ListIgnoredBuildTreeRefs = ListIgnored | DontListIgnored +-- | Which types of build tree refs should be listed? +data RefTypesToList = OnlySnapshots | OnlyLinks | LinksAndSnapshots + -- | List the local build trees that are referred to from the index. -listBuildTreeRefs :: Verbosity -> ListIgnoredBuildTreeRefs -> FilePath +listBuildTreeRefs :: Verbosity -> ListIgnoredBuildTreeRefs -> RefTypesToList + -> FilePath -> IO [FilePath] -listBuildTreeRefs verbosity listIgnored path = do +listBuildTreeRefs verbosity listIgnored refTypesToList path = do checkIndexExists path buildTreeRefs <- case listIgnored of DontListIgnored -> do + paths <- listWithoutIgnored + case refTypesToList of + LinksAndSnapshots -> return paths + _ -> do + allPathsFiltered <- fmap (map buildTreePath . filter predicate) + listWithIgnored + _ <- evaluate (length allPathsFiltered) + return (paths `intersect` allPathsFiltered) + + ListIgnored -> fmap (map buildTreePath . filter predicate) listWithIgnored + + _ <- evaluate (length buildTreeRefs) + return buildTreeRefs + + where + predicate :: BuildTreeRef -> Bool + predicate = case refTypesToList of + OnlySnapshots -> (==) SnapshotRef . buildTreeRefType + OnlyLinks -> (==) LinkRef . buildTreeRefType + LinksAndSnapshots -> const True + + listWithIgnored :: IO [BuildTreeRef] + listWithIgnored = readBuildTreeRefsFromFile $ path + + listWithoutIgnored :: IO [FilePath] + listWithoutIgnored = do let repo = Repo { repoKind = Right LocalRepo , repoLocalDir = takeDirectory path } pkgIndex <- fmap packageIndex @@ -187,11 +225,6 @@ listBuildTreeRefs verbosity listIgnored path = do return [ pkgPath | (LocalUnpackedPackage pkgPath) <- map packageSource . allPackages $ pkgIndex ] - ListIgnored -> readBuildTreePathsFromFile path - - _ <- evaluate (length buildTreeRefs) - return buildTreeRefs - -- | Check that the package index file exists and exit with error if it does not. checkIndexExists :: FilePath -> IO () diff --git a/cabal-install/Distribution/Client/Sandbox/Timestamp.hs b/cabal-install/Distribution/Client/Sandbox/Timestamp.hs index 3b4e77d884..0e7729cc1a 100644 --- a/cabal-install/Distribution/Client/Sandbox/Timestamp.hs +++ b/cabal-install/Distribution/Client/Sandbox/Timestamp.hs @@ -41,7 +41,8 @@ import Distribution.Version (Version (..), orLaterVersion) import Distribution.Client.Sandbox.Index - (ListIgnoredBuildTreeRefs (..), listBuildTreeRefs) + (ListIgnoredBuildTreeRefs (DontListIgnored), RefTypesToList(OnlyLinks) + ,listBuildTreeRefs) import Distribution.Client.SetupWrapper (SetupScriptOptions (..), defaultSetupScriptOptions, setupWrapper) @@ -141,7 +142,8 @@ maybeAddCompilerTimestampRecord :: Verbosity -> FilePath -> FilePath -> IO () maybeAddCompilerTimestampRecord verbosity sandboxDir indexFile compId platform = do - buildTreeRefs <- listBuildTreeRefs verbosity DontListIgnored indexFile + buildTreeRefs <- listBuildTreeRefs verbosity DontListIgnored OnlyLinks + indexFile withTimestampFile sandboxDir $ \timestampRecords -> do let key = timestampRecordKey compId platform case lookup key timestampRecords of diff --git a/cabal-install/Distribution/Client/Tar.hs b/cabal-install/Distribution/Client/Tar.hs index ead2dfbc20..9dd546fbc5 100644 --- a/cabal-install/Distribution/Client/Tar.hs +++ b/cabal-install/Distribution/Client/Tar.hs @@ -40,6 +40,8 @@ module Distribution.Client.Tar ( TypeCode, Format(..), buildTreeRefTypeCode, + buildTreeSnapshotTypeCode, + isBuildTreeRefTypeCode, entrySizeInBlocks, entrySizeInBytes, @@ -159,6 +161,17 @@ data Entry = Entry { buildTreeRefTypeCode :: TypeCode buildTreeRefTypeCode = 'C' +-- | Type code for the local build tree snapshot entry type. +buildTreeSnapshotTypeCode :: TypeCode +buildTreeSnapshotTypeCode = 'S' + +-- | Is this a type code for a build tree reference? +isBuildTreeRefTypeCode :: TypeCode -> Bool +isBuildTreeRefTypeCode typeCode + | (typeCode == buildTreeRefTypeCode + || typeCode == buildTreeSnapshotTypeCode) = True + | otherwise = False + -- | Native 'FilePath' of the file or directory within the archive. -- entryPath :: Entry -> FilePath -- GitLab