module Network.IPFS.Add ( addRaw , addFile , addPath , addDir ) where import Network.IPFS.Local.Class as IPFS import Network.IPFS.Prelude hiding (link) import Data.ByteString.Lazy.Char8 as CL import qualified System.FilePath.Glob as Glob import qualified RIO.ByteString.Lazy as Lazy import RIO.Directory import RIO.FilePath import qualified RIO.List as List import qualified Network.IPFS.Internal.UTF8 as UTF8 import Network.IPFS.Add.Error as IPFS.Add import Network.IPFS.DAG.Link as DAG.Link import Network.IPFS.DAG.Node.Types as DAG import Network.IPFS.Types as IPFS import Network.IPFS.DAG as DAG addRaw :: MonadLocalIPFS m => Lazy.ByteString -> m (Either IPFS.Add.Error IPFS.CID) addRaw :: forall (m :: * -> *). MonadLocalIPFS m => ByteString -> m (Either Error CID) addRaw ByteString raw = forall (m :: * -> *). MonadLocalIPFS m => [Opt] -> ByteString -> m (Either Error ByteString) IPFS.runLocal [Opt "add", Opt "-HQ"] ByteString raw forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case Right ByteString result -> case ByteString -> [ByteString] CL.lines ByteString result of [Item [ByteString] cid] -> forall (m :: * -> *) a. Monad m => a -> m a return forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. b -> Either a b Right forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> CID mkCID forall b c a. (b -> c) -> (a -> b) -> a -> c . Natural -> Text -> Text UTF8.stripN Natural 1 forall b c a. (b -> c) -> (a -> b) -> a -> c . ByteString -> Text decodeUtf8Lenient forall a b. (a -> b) -> a -> b $ ByteString -> ByteString Lazy.toStrict Item [ByteString] cid [ByteString] bad -> forall (m :: * -> *) a. Monad m => a -> m a return forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. a -> Either a b Left forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> Error UnexpectedOutput forall a b. (a -> b) -> a -> b $ forall a. Show a => a -> Text UTF8.textShow [ByteString] bad Left Error err -> forall (m :: * -> *) a. Monad m => a -> m a return forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. a -> Either a b Left forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> Error UnknownAddErr forall a b. (a -> b) -> a -> b $ forall a. Show a => a -> Text UTF8.textShow Error err addFile :: MonadLocalIPFS m => Lazy.ByteString -> IPFS.Name -> m (Either IPFS.Add.Error (IPFS.SparseTree, IPFS.CID)) addFile :: forall (m :: * -> *). MonadLocalIPFS m => ByteString -> Name -> m (Either Error (SparseTree, CID)) addFile ByteString raw Name name = forall (m :: * -> *). MonadLocalIPFS m => [Opt] -> ByteString -> m (Either Error ByteString) IPFS.runLocal [Opt] opts ByteString raw forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case Right ByteString result -> case ByteString -> [ByteString] CL.lines ByteString result of [Item [ByteString] inner, Item [ByteString] outer] -> let sparseTree :: SparseTree sparseTree = Map Tag SparseTree -> SparseTree Directory [(CID -> Tag Hash CID rootCID, SparseTree fileWrapper)] fileWrapper :: SparseTree fileWrapper = Map Tag SparseTree -> SparseTree Directory [(Tag fileName, CID -> SparseTree Content CID fileCID)] rootCID :: CID rootCID = Text -> CID CID forall b c a. (b -> c) -> (a -> b) -> a -> c . ByteString -> Text decodeUtf8Lenient forall a b. (a -> b) -> a -> b $ ByteString -> ByteString Lazy.toStrict Item [ByteString] outer fileCID :: CID fileCID = Text -> CID CID forall b c a. (b -> c) -> (a -> b) -> a -> c . Natural -> Text -> Text UTF8.stripN Natural 1 forall b c a. (b -> c) -> (a -> b) -> a -> c . ByteString -> Text decodeUtf8Lenient forall a b. (a -> b) -> a -> b $ ByteString -> ByteString Lazy.toStrict Item [ByteString] inner fileName :: Tag fileName = Name -> Tag Key Name name in forall (m :: * -> *) a. Monad m => a -> m a return forall a b. (a -> b) -> a -> b $ forall a b. b -> Either a b Right (SparseTree sparseTree, CID rootCID) [ByteString] bad -> forall (m :: * -> *) a. Monad m => a -> m a return forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. a -> Either a b Left forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> Error UnexpectedOutput forall a b. (a -> b) -> a -> b $ forall a. Show a => a -> Text UTF8.textShow [ByteString] bad Left Error err -> forall (m :: * -> *) a. Monad m => a -> m a return forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. a -> Either a b Left forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> Error UnknownAddErr forall a b. (a -> b) -> a -> b $ forall a. Show a => a -> Text UTF8.textShow Error err where opts :: [Opt] opts = [ Opt "add" , Opt "-wq" , Opt "--stdin-name" , Name -> Opt unName Name name ] addPath :: MonadLocalIPFS m => FilePath -> m (Either IPFS.Add.Error CID) addPath :: forall (m :: * -> *). MonadLocalIPFS m => Opt -> m (Either Error CID) addPath Opt path = forall (m :: * -> *). MonadLocalIPFS m => [Opt] -> ByteString -> m (Either Error ByteString) IPFS.runLocal [Opt "add", Opt "-HQ", Opt path] ByteString "" forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= forall (f :: * -> *) a. Applicative f => a -> f a pure forall b c a. (b -> c) -> (a -> b) -> a -> c . \case Right ByteString result -> case ByteString -> [ByteString] CL.lines ByteString result of [Item [ByteString] cid] -> forall a b. b -> Either a b Right forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> CID mkCID forall b c a. (b -> c) -> (a -> b) -> a -> c . Natural -> Text -> Text UTF8.stripN Natural 1 forall a b. (a -> b) -> a -> b $ forall a. Show a => a -> Text UTF8.textShow Item [ByteString] cid [ByteString] bad -> forall a b. a -> Either a b Left forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> Error UnexpectedOutput forall a b. (a -> b) -> a -> b $ forall a. Show a => a -> Text UTF8.textShow [ByteString] bad Left Error err -> forall a b. a -> Either a b Left forall b c a. (b -> c) -> (a -> b) -> a -> c . Text -> Error UnknownAddErr forall a b. (a -> b) -> a -> b $ forall a. Show a => a -> Text UTF8.textShow Error err addDir :: ( MonadIO m , MonadLocalIPFS m ) => IPFS.Ignored -> FilePath -> m (Either IPFS.Add.Error IPFS.CID) addDir :: forall (m :: * -> *). (MonadIO m, MonadLocalIPFS m) => Ignored -> Opt -> m (Either Error CID) addDir Ignored ignored Opt path = forall (m :: * -> *). MonadIO m => Opt -> m Bool doesFileExist Opt path forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case Bool True -> forall (m :: * -> *). MonadLocalIPFS m => Opt -> m (Either Error CID) addPath Opt path Bool False -> forall (m :: * -> *). (MonadIO m, MonadLocalIPFS m) => Ignored -> Opt -> m (Either Error CID) walkDir Ignored ignored Opt path walkDir :: ( MonadIO m , MonadLocalIPFS m ) => IPFS.Ignored -> FilePath -> m (Either IPFS.Add.Error IPFS.CID) walkDir :: forall (m :: * -> *). (MonadIO m, MonadLocalIPFS m) => Ignored -> Opt -> m (Either Error CID) walkDir Ignored ignored Opt path = do [Opt] files <- forall (m :: * -> *). MonadIO m => Opt -> m [Opt] listDirectory Opt path let toAdd :: [Opt] toAdd = Ignored -> [Opt] -> [Opt] removeIgnored Ignored ignored [Opt] files reducer :: Either Error Node -> Opt -> m (Either Error Node) reducer = forall (m :: * -> *). (MonadIO m, MonadLocalIPFS m) => Opt -> Ignored -> Either Error Node -> Opt -> m (Either Error Node) foldResults Opt path Ignored ignored seed :: Either a Node seed = forall a b. b -> Either a b Right forall a b. (a -> b) -> a -> b $ Node { $sel:dataBlock:Node :: Text dataBlock = Text "CAE=" , $sel:links:Node :: [Link] links = [] } forall (t :: * -> *) (m :: * -> *) b a. (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b foldM Either Error Node -> Opt -> m (Either Error Node) reducer forall {a}. Either a Node seed [Opt] toAdd forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case Left Error err -> forall (m :: * -> *) a. Monad m => a -> m a return forall a b. (a -> b) -> a -> b $ forall a b. a -> Either a b Left Error err Right Node node -> forall (m :: * -> *). MonadLocalIPFS m => Node -> m (Either Error CID) DAG.putNode Node node foldResults :: ( MonadIO m , MonadLocalIPFS m ) => FilePath -> IPFS.Ignored -> Either IPFS.Add.Error Node -> FilePath -> m (Either IPFS.Add.Error Node) foldResults :: forall (m :: * -> *). (MonadIO m, MonadLocalIPFS m) => Opt -> Ignored -> Either Error Node -> Opt -> m (Either Error Node) foldResults Opt _ Ignored _ (Left Error err) Opt _ = forall (m :: * -> *) a. Monad m => a -> m a return forall a b. (a -> b) -> a -> b $ forall a b. a -> Either a b Left Error err foldResults Opt path Ignored ignored (Right Node node) Opt filename = do forall (m :: * -> *). (MonadIO m, MonadLocalIPFS m) => Ignored -> Opt -> m (Either Error CID) addDir Ignored ignored (Opt path Opt -> Opt -> Opt </> Opt filename) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case Left Error err -> forall (m :: * -> *) a. Monad m => a -> m a return forall a b. (a -> b) -> a -> b $ forall a b. a -> Either a b Left Error err Right CID cid -> forall (m :: * -> *). MonadLocalIPFS m => CID -> Name -> m (Either Error Link) DAG.Link.create CID cid (Opt -> Name IPFS.Name Opt filename) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \case Left Error err -> forall (m :: * -> *) a. Monad m => a -> m a return forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. a -> Either a b Left forall a b. (a -> b) -> a -> b $ Error -> Error RecursiveAddErr Error err Right Link link -> forall (m :: * -> *) a. Monad m => a -> m a return forall a b. (a -> b) -> a -> b $ forall a b. b -> Either a b Right Node node { $sel:links:Node :: [Link] links = Link linkforall a. a -> [a] -> [a] : Node -> [Link] links Node node } removeIgnored :: IPFS.Ignored -> [FilePath] -> [FilePath] removeIgnored :: Ignored -> [Opt] -> [Opt] removeIgnored Ignored ignored [Opt] files = forall a. (a -> Bool) -> [a] -> [a] List.filter (Bool -> Bool not forall b c a. (b -> c) -> (a -> b) -> a -> c . Ignored -> Opt -> Bool matchesAny Ignored ignored) [Opt] files matchesAny :: IPFS.Ignored -> FilePath -> Bool matchesAny :: Ignored -> Opt -> Bool matchesAny Ignored globs Opt path = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool List.any (\Pattern x -> Pattern -> Opt -> Bool Glob.match Pattern x Opt path) Ignored globs