{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}

-- | Provides 'PathData' for use with the FreeDesktopOrg backend.
module Charon.Backend.Fdo.PathData
  ( -- * PathData
    PathData (..),
    toPathData,
    toCorePathData,
    toCorePathDataDirectorySizes,
    fromCorePathData,
  )
where

import Charon.Backend.Default.Trash qualified as Trash
import Charon.Backend.Default.Utils qualified as Default.Utils
import Charon.Backend.Fdo.DirectorySizes (DirectorySizesEntry)
import Charon.Backend.Fdo.Utils qualified as Fdo.Utils
import Charon.Class.Serial (Serial (..), decodeUnit)
import Charon.Data.PathData qualified as PathData
import Charon.Data.PathType (PathTypeW)
import Charon.Data.Paths
  ( PathI (MkPathI),
    PathIndex
      ( TrashEntryFileName,
        TrashEntryOriginalPath,
        TrashHome
      ),
  )
import Charon.Data.Timestamp (Timestamp)
import Charon.Prelude
import Charon.Utils qualified as U
import Charon.Utils qualified as Utils
import Data.ByteString.Char8 qualified as C8
import Data.HashMap.Strict qualified as HMap
import Data.HashSet qualified as Set
import Effects.FileSystem.PathReader qualified as PR
import Numeric.Algebra (ASemigroup ((.+.)))
import Numeric.Literal.Integer (FromInteger (afromInteger))

-- | Data for an Fdo path. Maintains an invariant that the original path is not
-- the root nor is it empty.
data PathData = UnsafePathData
  { -- | The path to be used in the trash directory.
    PathData -> PathI 'TrashEntryFileName
fileName :: PathI TrashEntryFileName,
    -- | The original path on the file system.
    PathData -> PathI 'TrashEntryOriginalPath
originalPath :: PathI TrashEntryOriginalPath,
    -- | Time this entry was created.
    PathData -> Timestamp
created :: Timestamp
  }
  deriving stock (PathData -> PathData -> Bool
(PathData -> PathData -> Bool)
-> (PathData -> PathData -> Bool) -> Eq PathData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PathData -> PathData -> Bool
== :: PathData -> PathData -> Bool
$c/= :: PathData -> PathData -> Bool
/= :: PathData -> PathData -> Bool
Eq, (forall x. PathData -> Rep PathData x)
-> (forall x. Rep PathData x -> PathData) -> Generic PathData
forall x. Rep PathData x -> PathData
forall x. PathData -> Rep PathData x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PathData -> Rep PathData x
from :: forall x. PathData -> Rep PathData x
$cto :: forall x. Rep PathData x -> PathData
to :: forall x. Rep PathData x -> PathData
Generic, Int -> PathData -> ShowS
[PathData] -> ShowS
PathData -> String
(Int -> PathData -> ShowS)
-> (PathData -> String) -> ([PathData] -> ShowS) -> Show PathData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PathData -> ShowS
showsPrec :: Int -> PathData -> ShowS
$cshow :: PathData -> String
show :: PathData -> String
$cshowList :: [PathData] -> ShowS
showList :: [PathData] -> ShowS
Show)
  deriving anyclass (Eq PathData
Eq PathData =>
(Int -> PathData -> Int) -> (PathData -> Int) -> Hashable PathData
Int -> PathData -> Int
PathData -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> PathData -> Int
hashWithSalt :: Int -> PathData -> Int
$chash :: PathData -> Int
hash :: PathData -> Int
Hashable, PathData -> ()
(PathData -> ()) -> NFData PathData
forall a. (a -> ()) -> NFData a
$crnf :: PathData -> ()
rnf :: PathData -> ()
NFData)

makeFieldLabelsNoPrefix ''PathData

-- | For a given filepath, attempts to capture the following data:
--
-- * Canonical path.
-- * Unique name to be used in the trash directory.
-- * File/directory type.
toPathData ::
  ( HasCallStack,
    MonadCatch m,
    MonadLoggerNS m,
    MonadPathReader m
  ) =>
  Timestamp ->
  PathI TrashHome ->
  PathI TrashEntryOriginalPath ->
  m (PathData, PathTypeW)
toPathData :: forall (m :: * -> *).
(HasCallStack, MonadCatch m, MonadLoggerNS m, MonadPathReader m) =>
Timestamp
-> PathI 'TrashHome
-> PathI 'TrashEntryOriginalPath
-> m (PathData, PathTypeW)
toPathData Timestamp
currTime PathI 'TrashHome
trashHome PathI 'TrashEntryOriginalPath
origPath = Text -> m (PathData, PathTypeW) -> m (PathData, PathTypeW)
forall (m :: * -> *) a. MonadLoggerNS m => Text -> m a -> m a
addNamespace Text
"toPathData" (m (PathData, PathTypeW) -> m (PathData, PathTypeW))
-> m (PathData, PathTypeW) -> m (PathData, PathTypeW)
forall a b. (a -> b) -> a -> b
$ do
  (PathI 'TrashEntryFileName
fileName', PathI 'TrashEntryOriginalPath
originalPath', PathTypeW
pathType) <- PathI 'TrashHome
-> PathI 'TrashEntryOriginalPath
-> m (PathI 'TrashEntryFileName, PathI 'TrashEntryOriginalPath,
      PathTypeW)
forall (m :: * -> *).
(HasCallStack, MonadCatch m, MonadLoggerNS m, MonadPathReader m) =>
PathI 'TrashHome
-> PathI 'TrashEntryOriginalPath
-> m (PathI 'TrashEntryFileName, PathI 'TrashEntryOriginalPath,
      PathTypeW)
Default.Utils.getPathInfo PathI 'TrashHome
trashHome PathI 'TrashEntryOriginalPath
origPath

  (PathData, PathTypeW) -> m (PathData, PathTypeW)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    ( UnsafePathData
        { $sel:fileName:UnsafePathData :: PathI 'TrashEntryFileName
fileName = PathI 'TrashEntryFileName
fileName',
          $sel:originalPath:UnsafePathData :: PathI 'TrashEntryOriginalPath
originalPath = PathI 'TrashEntryOriginalPath
originalPath',
          $sel:created:UnsafePathData :: Timestamp
created = Timestamp
currTime
        },
      PathTypeW
pathType
    )

instance Serial PathData where
  type DecodeExtra PathData = PathI TrashEntryFileName

  encode :: PathData -> Either String ByteString
  encode :: PathData -> Either String ByteString
encode PathData
pd =
    case (PathI 'TrashEntryOriginalPath -> Either String ByteString
forall a. Serial a => a -> Either String ByteString
encode (PathData
pd PathData
-> Optic' A_Lens NoIx PathData (PathI 'TrashEntryOriginalPath)
-> PathI 'TrashEntryOriginalPath
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData (PathI 'TrashEntryOriginalPath)
#originalPath), Timestamp -> Either String ByteString
forall a. Serial a => a -> Either String ByteString
encode (PathData
pd PathData -> Optic' A_Lens NoIx PathData Timestamp -> Timestamp
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData Timestamp
#created)) of
      (Right ByteString
opath, Right ByteString
created) ->
        ByteString -> Either String ByteString
forall a b. b -> Either a b
Right
          (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
C8.unlines
            [ ByteString
Item [ByteString]
"[Trash Info]",
              ByteString
"Path=" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString -> ByteString
U.percentEncode ByteString
opath,
              ByteString
"DeletionDate=" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
created
            ]
      (Left String
ex, Either String ByteString
_) -> String -> Either String ByteString
forall a b. a -> Either a b
Left String
ex
      (Either String ByteString
_, Left String
ex) -> String -> Either String ByteString
forall a b. a -> Either a b
Left String
ex

  decode :: PathI TrashEntryFileName -> ByteString -> Either String PathData
  decode :: PathI 'TrashEntryFileName -> ByteString -> Either String PathData
decode PathI 'TrashEntryFileName
name ByteString
bs = do
    HashMap ByteString ByteString
mp <- HashSet ByteString
-> ByteString -> Either String (HashMap ByteString ByteString)
Default.Utils.parseTrashInfoMap HashSet ByteString
expectedKeys ByteString
bs

    PathI 'TrashEntryOriginalPath
originalPath <- ByteString -> Either String (PathI 'TrashEntryOriginalPath)
forall a.
(DecodeExtra a ~ (), Serial a) =>
ByteString -> Either String a
decodeUnit (ByteString -> Either String (PathI 'TrashEntryOriginalPath))
-> (ByteString -> ByteString)
-> ByteString
-> Either String (PathI 'TrashEntryOriginalPath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
U.percentDecode (ByteString -> Either String (PathI 'TrashEntryOriginalPath))
-> Either String ByteString
-> Either String (PathI 'TrashEntryOriginalPath)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ByteString
-> HashMap ByteString ByteString -> Either String ByteString
forall b. ByteString -> HashMap ByteString b -> Either String b
Default.Utils.lookup ByteString
"Path" HashMap ByteString ByteString
mp
    Timestamp
created <- ByteString -> Either String Timestamp
forall a.
(DecodeExtra a ~ (), Serial a) =>
ByteString -> Either String a
decodeUnit (ByteString -> Either String Timestamp)
-> Either String ByteString -> Either String Timestamp
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ByteString
-> HashMap ByteString ByteString -> Either String ByteString
forall b. ByteString -> HashMap ByteString b -> Either String b
Default.Utils.lookup ByteString
"DeletionDate" HashMap ByteString ByteString
mp

    PathData -> Either String PathData
forall a b. b -> Either a b
Right
      (PathData -> Either String PathData)
-> PathData -> Either String PathData
forall a b. (a -> b) -> a -> b
$ UnsafePathData
        { $sel:fileName:UnsafePathData :: PathI 'TrashEntryFileName
fileName = PathI 'TrashEntryFileName
name,
          PathI 'TrashEntryOriginalPath
$sel:originalPath:UnsafePathData :: PathI 'TrashEntryOriginalPath
originalPath :: PathI 'TrashEntryOriginalPath
originalPath,
          Timestamp
$sel:created:UnsafePathData :: Timestamp
created :: Timestamp
created
        }
    where
      expectedKeys :: HashSet ByteString
expectedKeys = [ByteString] -> HashSet ByteString
forall a. (Eq a, Hashable a) => [a] -> HashSet a
Set.fromList [ByteString
Item [ByteString]
"Path", ByteString
Item [ByteString]
"DeletionDate"]

toCorePathData ::
  ( HasCallStack,
    MonadAsync m,
    MonadCatch m,
    MonadLoggerNS m,
    MonadPathReader m,
    MonadPosixCompat m,
    MonadTerminal m
  ) =>
  PathI TrashHome ->
  PathData ->
  m PathData.PathData
toCorePathData :: forall (m :: * -> *).
(HasCallStack, MonadAsync m, MonadCatch m, MonadLoggerNS m,
 MonadPathReader m, MonadPosixCompat m, MonadTerminal m) =>
PathI 'TrashHome -> PathData -> m PathData
toCorePathData PathI 'TrashHome
trashHome PathData
pd = Text -> m PathData -> m PathData
forall (m :: * -> *) a. MonadLoggerNS m => Text -> m a -> m a
addNamespace Text
"toCorePathData" (m PathData -> m PathData) -> m PathData -> m PathData
forall a b. (a -> b) -> a -> b
$ do
  $(logDebug) (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"PathData: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PathData -> Text
forall a. Show a => a -> Text
showt PathData
pd
  PathTypeW
pathType <- PathI 'TrashHome -> PathData -> m PathTypeW
forall k a (m :: * -> *).
(Is k A_Getter,
 LabelOptic' "fileName" k a (PathI 'TrashEntryFileName),
 HasCallStack, MonadCatch m, MonadPathReader m) =>
PathI 'TrashHome -> a -> m PathTypeW
Default.Utils.pathDataToType PathI 'TrashHome
trashHome PathData
pd

  Bytes 'B Natural
size <- OsPath -> m (Bytes 'B Natural)
forall (m :: * -> *).
(HasCallStack, MonadAsync m, MonadCatch m, MonadLoggerNS m,
 MonadPathReader m, MonadPosixCompat m, MonadTerminal m) =>
OsPath -> m (Bytes 'B Natural)
Utils.getPathSize OsPath
path

  PathData -> m PathData
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    (PathData -> m PathData) -> PathData -> m PathData
forall a b. (a -> b) -> a -> b
$ PathData.UnsafePathData
      { PathTypeW
pathType :: PathTypeW
$sel:pathType:UnsafePathData :: PathTypeW
pathType,
        $sel:fileName:UnsafePathData :: PathI 'TrashEntryFileName
fileName = PathData
pd PathData
-> Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
-> PathI 'TrashEntryFileName
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
#fileName,
        $sel:originalPath:UnsafePathData :: PathI 'TrashEntryOriginalPath
originalPath = PathData
pd PathData
-> Optic' A_Lens NoIx PathData (PathI 'TrashEntryOriginalPath)
-> PathI 'TrashEntryOriginalPath
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData (PathI 'TrashEntryOriginalPath)
#originalPath,
        Bytes 'B Natural
size :: Bytes 'B Natural
$sel:size:UnsafePathData :: Bytes 'B Natural
size,
        $sel:created:UnsafePathData :: Timestamp
created = PathData
pd PathData -> Optic' A_Lens NoIx PathData Timestamp -> Timestamp
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData Timestamp
#created
      }
  where
    MkPathI OsPath
path = PathI 'TrashHome
-> PathI 'TrashEntryFileName -> PathI 'TrashEntryPath
Trash.getTrashPath PathI 'TrashHome
trashHome (PathData
pd PathData
-> Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
-> PathI 'TrashEntryFileName
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
#fileName)

toCorePathDataDirectorySizes ::
  ( HasCallStack,
    MonadAsync m,
    MonadCatch m,
    MonadLoggerNS m,
    MonadPathReader m,
    MonadPosixCompat m,
    MonadTerminal m
  ) =>
  HashMap ByteString DirectorySizesEntry ->
  PathI TrashHome ->
  PathData ->
  m PathData.PathData
toCorePathDataDirectorySizes :: forall (m :: * -> *).
(HasCallStack, MonadAsync m, MonadCatch m, MonadLoggerNS m,
 MonadPathReader m, MonadPosixCompat m, MonadTerminal m) =>
HashMap ByteString DirectorySizesEntry
-> PathI 'TrashHome -> PathData -> m PathData
toCorePathDataDirectorySizes HashMap ByteString DirectorySizesEntry
dsizeMap PathI 'TrashHome
trashHome PathData
pd = Text -> m PathData -> m PathData
forall (m :: * -> *) a. MonadLoggerNS m => Text -> m a -> m a
addNamespace Text
"toCorePathDataDirectorySizes" (m PathData -> m PathData) -> m PathData -> m PathData
forall a b. (a -> b) -> a -> b
$ do
  $(logDebug) (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"PathData: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PathData -> Text
forall a. Show a => a -> Text
showt PathData
pd
  PathTypeW
pathType <- PathI 'TrashHome -> PathData -> m PathTypeW
forall k a (m :: * -> *).
(Is k A_Getter,
 LabelOptic' "fileName" k a (PathI 'TrashEntryFileName),
 HasCallStack, MonadCatch m, MonadPathReader m) =>
PathI 'TrashHome -> a -> m PathTypeW
Default.Utils.pathDataToType PathI 'TrashHome
trashHome PathData
pd

  Bytes 'B Natural
size <- case PathTypeW
pathType PathTypeW -> Optic' An_Iso NoIx PathTypeW PathType -> PathType
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' An_Iso NoIx PathTypeW PathType
#unPathTypeW of
    PathType
PathTypeFile -> Integer -> Bytes 'B Natural
forall a. (FromInteger a, HasCallStack) => Integer -> a
afromInteger (Integer -> Bytes 'B Natural) -> m Integer -> m (Bytes 'B Natural)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OsPath -> m Integer
forall (m :: * -> *).
(MonadPathReader m, HasCallStack) =>
OsPath -> m Integer
PR.getFileSize OsPath
path
    PathType
PathTypeOther -> Integer -> Bytes 'B Natural
forall a. (FromInteger a, HasCallStack) => Integer -> a
afromInteger (Integer -> Bytes 'B Natural) -> m Integer -> m (Bytes 'B Natural)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OsPath -> m Integer
forall (m :: * -> *).
(MonadPathReader m, HasCallStack) =>
OsPath -> m Integer
PR.getFileSize OsPath
path
    PathType
PathTypeDirectory -> do
      ByteString
name <- PathData -> m ByteString
forall (m :: * -> *) pd k.
(HasCallStack, Is k A_Getter,
 LabelOptic' "fileName" k pd (PathI 'TrashEntryFileName),
 MonadThrow m) =>
pd -> m ByteString
Fdo.Utils.percentEncodeFileName PathData
pd
      case ByteString
-> HashMap ByteString DirectorySizesEntry
-> Maybe DirectorySizesEntry
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HMap.lookup ByteString
name HashMap ByteString DirectorySizesEntry
dsizeMap of
        Just DirectorySizesEntry
entry -> do
          Natural
dirSize <- forall a b. (Integral a, Num b) => a -> b
fromIntegral @_ @Natural (Integer -> Natural) -> m Integer -> m Natural
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OsPath -> m Integer
forall (m :: * -> *).
(MonadPathReader m, HasCallStack) =>
OsPath -> m Integer
PR.getFileSize OsPath
path
          -- directorysizes does not include the directory itself, so we have
          -- to add it back
          Bytes 'B Natural -> m (Bytes 'B Natural)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bytes 'B Natural -> m (Bytes 'B Natural))
-> Bytes 'B Natural -> m (Bytes 'B Natural)
forall a b. (a -> b) -> a -> b
$ Natural -> Bytes 'B Natural
forall (s :: Size) n. n -> Bytes s n
MkBytes Natural
dirSize Bytes 'B Natural -> Bytes 'B Natural -> Bytes 'B Natural
forall s. ASemigroup s => s -> s -> s
.+. DirectorySizesEntry
entry DirectorySizesEntry
-> Optic' A_Lens NoIx DirectorySizesEntry (Bytes 'B Natural)
-> Bytes 'B Natural
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx DirectorySizesEntry (Bytes 'B Natural)
#size
        Maybe DirectorySizesEntry
Nothing -> OsPath -> m (Bytes 'B Natural)
forall (m :: * -> *).
(HasCallStack, MonadAsync m, MonadCatch m, MonadLoggerNS m,
 MonadPathReader m, MonadPosixCompat m, MonadTerminal m) =>
OsPath -> m (Bytes 'B Natural)
Utils.getPathSize OsPath
path
    PathType
PathTypeSymbolicLink -> OsPath -> m (Bytes 'B Natural)
forall (m :: * -> *).
(HasCallStack, MonadPosixCompat m, MonadThrow m) =>
OsPath -> m (Bytes 'B Natural)
Utils.getSymLinkSize OsPath
path

  PathData -> m PathData
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    (PathData -> m PathData) -> PathData -> m PathData
forall a b. (a -> b) -> a -> b
$ PathData.UnsafePathData
      { PathTypeW
$sel:pathType:UnsafePathData :: PathTypeW
pathType :: PathTypeW
pathType,
        $sel:fileName:UnsafePathData :: PathI 'TrashEntryFileName
fileName = PathData
pd PathData
-> Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
-> PathI 'TrashEntryFileName
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
#fileName,
        $sel:originalPath:UnsafePathData :: PathI 'TrashEntryOriginalPath
originalPath = PathData
pd PathData
-> Optic' A_Lens NoIx PathData (PathI 'TrashEntryOriginalPath)
-> PathI 'TrashEntryOriginalPath
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData (PathI 'TrashEntryOriginalPath)
#originalPath,
        Bytes 'B Natural
$sel:size:UnsafePathData :: Bytes 'B Natural
size :: Bytes 'B Natural
size,
        $sel:created:UnsafePathData :: Timestamp
created = PathData
pd PathData -> Optic' A_Lens NoIx PathData Timestamp -> Timestamp
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData Timestamp
#created
      }
  where
    MkPathI OsPath
path = PathI 'TrashHome
-> PathI 'TrashEntryFileName -> PathI 'TrashEntryPath
Trash.getTrashPath PathI 'TrashHome
trashHome (PathData
pd PathData
-> Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
-> PathI 'TrashEntryFileName
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
#fileName)

fromCorePathData ::
  PathData.PathData ->
  PathData
fromCorePathData :: PathData -> PathData
fromCorePathData PathData
pd =
  UnsafePathData
    { $sel:fileName:UnsafePathData :: PathI 'TrashEntryFileName
fileName = PathData
pd PathData
-> Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
-> PathI 'TrashEntryFileName
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData (PathI 'TrashEntryFileName)
#fileName,
      $sel:originalPath:UnsafePathData :: PathI 'TrashEntryOriginalPath
originalPath = PathData
pd PathData
-> Optic' A_Lens NoIx PathData (PathI 'TrashEntryOriginalPath)
-> PathI 'TrashEntryOriginalPath
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData (PathI 'TrashEntryOriginalPath)
#originalPath,
      $sel:created:UnsafePathData :: Timestamp
created = PathData
pd PathData -> Optic' A_Lens NoIx PathData Timestamp -> Timestamp
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx PathData Timestamp
#created
    }