-----------------------------------------------------------------------------
-- |
-- License     :  BSD-3-Clause
-- Maintainer  :  Oleg Grenrus <oleg.grenrus@iki.fi>
--
-- The Github Repo Contents API, as documented at
-- <https://developer.github.com/v3/repos/contents/>
module GitHub.Endpoints.Repos.Contents (
    -- * Querying contents
    contentsFor,
    contentsFor',
    contentsForR,
    readmeFor,
    readmeFor',
    readmeForR,
    archiveFor,
    archiveFor',
    archiveForR,

    -- ** Create
    createFile,
    createFileR,

    -- ** Update
    updateFile,
    updateFileR,

    -- ** Delete
    deleteFile,
    deleteFileR,

    module GitHub.Data
    ) where

import GitHub.Data
import GitHub.Internal.Prelude
import GitHub.Request
import Prelude ()

import Data.Maybe (maybeToList)
import qualified Data.Text.Encoding as TE
import Network.URI (URI)

-- | The contents of a file or directory in a repo, given the repo owner, name, and path to the file
--
-- > contentsFor "thoughtbot" "paperclip" "README.md"
contentsFor :: Name Owner -> Name Repo -> Text -> Maybe Text -> IO (Either Error Content)
contentsFor :: Name Owner
-> Name Repo -> Text -> Maybe Text -> IO (Either Error Content)
contentsFor = Maybe Auth
-> Name Owner
-> Name Repo
-> Text
-> Maybe Text
-> IO (Either Error Content)
contentsFor' Maybe Auth
forall a. Maybe a
Nothing

-- | The contents of a file or directory in a repo, given the repo owner, name, and path to the file
-- With Authentication
--
-- > contentsFor' (Just $ BasicAuth "github-username" "github-password") "thoughtbot" "paperclip" "README.md" Nothing
contentsFor' :: Maybe Auth ->  Name Owner -> Name Repo -> Text -> Maybe Text -> IO (Either Error Content)
contentsFor' :: Maybe Auth
-> Name Owner
-> Name Repo
-> Text
-> Maybe Text
-> IO (Either Error Content)
contentsFor' auth :: Maybe Auth
auth user :: Name Owner
user repo :: Name Repo
repo path :: Text
path ref :: Maybe Text
ref =
    Maybe Auth
-> GenRequest 'MtJSON 'RO Content -> IO (Either Error Content)
forall am (mt :: MediaType *) a.
(AuthMethod am, ParseResponse mt a) =>
Maybe am -> GenRequest mt 'RO a -> IO (Either Error a)
executeRequestMaybe Maybe Auth
auth (GenRequest 'MtJSON 'RO Content -> IO (Either Error Content))
-> GenRequest 'MtJSON 'RO Content -> IO (Either Error Content)
forall a b. (a -> b) -> a -> b
$ Name Owner
-> Name Repo
-> Text
-> Maybe Text
-> GenRequest 'MtJSON 'RO Content
forall (k :: RW).
Name Owner -> Name Repo -> Text -> Maybe Text -> Request k Content
contentsForR Name Owner
user Name Repo
repo Text
path Maybe Text
ref

contentsForR
    :: Name Owner
    -> Name Repo
    -> Text            -- ^ file or directory
    -> Maybe Text      -- ^ Git commit
    -> Request k Content
contentsForR :: Name Owner -> Name Repo -> Text -> Maybe Text -> Request k Content
contentsForR user :: Name Owner
user repo :: Name Repo
repo path :: Text
path ref :: Maybe Text
ref =
    Paths -> QueryString -> Request k Content
forall (mt :: RW) a. Paths -> QueryString -> Request mt a
query ["repos", Name Owner -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Owner
user, Name Repo -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Repo
repo, "contents", Text
path] QueryString
qs
  where
    qs :: QueryString
qs =  QueryString -> (Text -> QueryString) -> Maybe Text -> QueryString
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\r :: Text
r -> [("ref", ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString)
-> (Text -> ByteString) -> Text -> Maybe ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
TE.encodeUtf8 (Text -> Maybe ByteString) -> Text -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ Text
r)]) Maybe Text
ref

-- | The contents of a README file in a repo, given the repo owner and name
--
-- > readmeFor "thoughtbot" "paperclip"
readmeFor :: Name Owner -> Name Repo -> IO (Either Error Content)
readmeFor :: Name Owner -> Name Repo -> IO (Either Error Content)
readmeFor = Maybe Auth -> Name Owner -> Name Repo -> IO (Either Error Content)
readmeFor' Maybe Auth
forall a. Maybe a
Nothing

-- | The contents of a README file in a repo, given the repo owner and name
-- With Authentication
--
-- > readmeFor' (Just $ BasicAuth "github-username" "github-password") "thoughtbot" "paperclip"
readmeFor' :: Maybe Auth -> Name Owner -> Name Repo -> IO (Either Error Content)
readmeFor' :: Maybe Auth -> Name Owner -> Name Repo -> IO (Either Error Content)
readmeFor' auth :: Maybe Auth
auth user :: Name Owner
user repo :: Name Repo
repo =
    Maybe Auth
-> GenRequest 'MtJSON 'RO Content -> IO (Either Error Content)
forall am (mt :: MediaType *) a.
(AuthMethod am, ParseResponse mt a) =>
Maybe am -> GenRequest mt 'RO a -> IO (Either Error a)
executeRequestMaybe Maybe Auth
auth (GenRequest 'MtJSON 'RO Content -> IO (Either Error Content))
-> GenRequest 'MtJSON 'RO Content -> IO (Either Error Content)
forall a b. (a -> b) -> a -> b
$ Name Owner -> Name Repo -> GenRequest 'MtJSON 'RO Content
forall (k :: RW). Name Owner -> Name Repo -> Request k Content
readmeForR Name Owner
user Name Repo
repo

readmeForR :: Name Owner -> Name Repo -> Request k Content
readmeForR :: Name Owner -> Name Repo -> Request k Content
readmeForR user :: Name Owner
user repo :: Name Repo
repo =
    Paths -> QueryString -> Request k Content
forall (mt :: RW) a. Paths -> QueryString -> Request mt a
query ["repos", Name Owner -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Owner
user, Name Repo -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Repo
repo, "readme"] []

-- | The archive of a repo, given the repo owner, name, and archive type
--
-- > archiveFor "thoughtbot" "paperclip" ArchiveFormatTarball Nothing
archiveFor :: Name Owner -> Name Repo -> ArchiveFormat -> Maybe Text -> IO (Either Error URI)
archiveFor :: Name Owner
-> Name Repo
-> ArchiveFormat
-> Maybe Text
-> IO (Either Error URI)
archiveFor = Maybe Auth
-> Name Owner
-> Name Repo
-> ArchiveFormat
-> Maybe Text
-> IO (Either Error URI)
archiveFor' Maybe Auth
forall a. Maybe a
Nothing

-- | The archive of a repo, given the repo owner, name, and archive type
-- With Authentication
--
-- > archiveFor' (Just $ BasicAuth "github-username" "github-password") "thoughtbot" "paperclip" ArchiveFormatTarball Nothing
archiveFor' :: Maybe Auth ->  Name Owner -> Name Repo -> ArchiveFormat -> Maybe Text -> IO (Either Error URI)
archiveFor' :: Maybe Auth
-> Name Owner
-> Name Repo
-> ArchiveFormat
-> Maybe Text
-> IO (Either Error URI)
archiveFor' auth :: Maybe Auth
auth user :: Name Owner
user repo :: Name Repo
repo path :: ArchiveFormat
path ref :: Maybe Text
ref =
    Maybe Auth
-> GenRequest 'MtRedirect 'RO URI -> IO (Either Error URI)
forall am (mt :: MediaType *) a.
(AuthMethod am, ParseResponse mt a) =>
Maybe am -> GenRequest mt 'RO a -> IO (Either Error a)
executeRequestMaybe Maybe Auth
auth (GenRequest 'MtRedirect 'RO URI -> IO (Either Error URI))
-> GenRequest 'MtRedirect 'RO URI -> IO (Either Error URI)
forall a b. (a -> b) -> a -> b
$ Name Owner
-> Name Repo
-> ArchiveFormat
-> Maybe Text
-> GenRequest 'MtRedirect 'RO URI
forall (rw :: RW).
Name Owner
-> Name Repo
-> ArchiveFormat
-> Maybe Text
-> GenRequest 'MtRedirect rw URI
archiveForR Name Owner
user Name Repo
repo ArchiveFormat
path Maybe Text
ref

-- | Get archive link.
-- See <https://developer.github.com/v3/repos/contents/#get-archive-link>
archiveForR
    :: Name Owner
    -> Name Repo
    -> ArchiveFormat   -- ^ The type of archive to retrieve
    -> Maybe Text      -- ^ Git commit
    -> GenRequest 'MtRedirect rw URI
archiveForR :: Name Owner
-> Name Repo
-> ArchiveFormat
-> Maybe Text
-> GenRequest 'MtRedirect rw URI
archiveForR user :: Name Owner
user repo :: Name Repo
repo format :: ArchiveFormat
format ref :: Maybe Text
ref = Paths -> QueryString -> GenRequest 'MtRedirect rw URI
forall (mt :: MediaType *) (rw :: RW) a.
Paths -> QueryString -> GenRequest mt rw a
Query Paths
path []
  where
    path :: Paths
path = ["repos", Name Owner -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Owner
user, Name Repo -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Repo
repo, ArchiveFormat -> Text
forall a. IsPathPart a => a -> Text
toPathPart ArchiveFormat
format] Paths -> Paths -> Paths
forall a. Semigroup a => a -> a -> a
<> Maybe Text -> Paths
forall a. Maybe a -> [a]
maybeToList Maybe Text
ref

-- | Create a file.
createFile
    :: Auth
    -> Name Owner      -- ^ owner
    -> Name Repo       -- ^ repository name
    -> CreateFile
    -> IO (Either Error ContentResult)
createFile :: Auth
-> Name Owner
-> Name Repo
-> CreateFile
-> IO (Either Error ContentResult)
createFile auth :: Auth
auth user :: Name Owner
user repo :: Name Repo
repo body :: CreateFile
body =
    Auth
-> GenRequest 'MtJSON 'RW ContentResult
-> IO (Either Error ContentResult)
forall am (mt :: MediaType *) a (rw :: RW).
(AuthMethod am, ParseResponse mt a) =>
am -> GenRequest mt rw a -> IO (Either Error a)
executeRequest Auth
auth (GenRequest 'MtJSON 'RW ContentResult
 -> IO (Either Error ContentResult))
-> GenRequest 'MtJSON 'RW ContentResult
-> IO (Either Error ContentResult)
forall a b. (a -> b) -> a -> b
$ Name Owner
-> Name Repo -> CreateFile -> GenRequest 'MtJSON 'RW ContentResult
createFileR Name Owner
user Name Repo
repo CreateFile
body

-- | Create a file.
-- See <https://developer.github.com/v3/repos/contents/#create-a-file>
createFileR
    :: Name Owner
    -> Name Repo
    -> CreateFile
    -> Request 'RW ContentResult
createFileR :: Name Owner
-> Name Repo -> CreateFile -> GenRequest 'MtJSON 'RW ContentResult
createFileR user :: Name Owner
user repo :: Name Repo
repo body :: CreateFile
body =
    CommandMethod
-> Paths -> ByteString -> GenRequest 'MtJSON 'RW ContentResult
forall a. CommandMethod -> Paths -> ByteString -> Request 'RW a
command CommandMethod
Put ["repos", Name Owner -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Owner
user, Name Repo -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Repo
repo, "contents", CreateFile -> Text
createFilePath CreateFile
body] (CreateFile -> ByteString
forall a. ToJSON a => a -> ByteString
encode CreateFile
body)

-- | Update a file.
updateFile
    :: Auth
    -> Name Owner      -- ^ owner
    -> Name Repo       -- ^ repository name
    -> UpdateFile
    -> IO (Either Error ContentResult)
updateFile :: Auth
-> Name Owner
-> Name Repo
-> UpdateFile
-> IO (Either Error ContentResult)
updateFile auth :: Auth
auth user :: Name Owner
user repo :: Name Repo
repo body :: UpdateFile
body =
    Auth
-> GenRequest 'MtJSON 'RW ContentResult
-> IO (Either Error ContentResult)
forall am (mt :: MediaType *) a (rw :: RW).
(AuthMethod am, ParseResponse mt a) =>
am -> GenRequest mt rw a -> IO (Either Error a)
executeRequest Auth
auth (GenRequest 'MtJSON 'RW ContentResult
 -> IO (Either Error ContentResult))
-> GenRequest 'MtJSON 'RW ContentResult
-> IO (Either Error ContentResult)
forall a b. (a -> b) -> a -> b
$ Name Owner
-> Name Repo -> UpdateFile -> GenRequest 'MtJSON 'RW ContentResult
updateFileR Name Owner
user Name Repo
repo UpdateFile
body

-- | Update a file.
-- See <https://developer.github.com/v3/repos/contents/#update-a-file>
updateFileR
    :: Name Owner
    -> Name Repo
    -> UpdateFile
    -> Request 'RW ContentResult
updateFileR :: Name Owner
-> Name Repo -> UpdateFile -> GenRequest 'MtJSON 'RW ContentResult
updateFileR user :: Name Owner
user repo :: Name Repo
repo body :: UpdateFile
body =
    CommandMethod
-> Paths -> ByteString -> GenRequest 'MtJSON 'RW ContentResult
forall a. CommandMethod -> Paths -> ByteString -> Request 'RW a
command CommandMethod
Put ["repos", Name Owner -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Owner
user, Name Repo -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Repo
repo, "contents", UpdateFile -> Text
updateFilePath UpdateFile
body] (UpdateFile -> ByteString
forall a. ToJSON a => a -> ByteString
encode UpdateFile
body)

-- | Delete a file.
deleteFile
    :: Auth
    -> Name Owner      -- ^ owner
    -> Name Repo       -- ^ repository name
    -> DeleteFile
    -> IO (Either Error ())
deleteFile :: Auth
-> Name Owner -> Name Repo -> DeleteFile -> IO (Either Error ())
deleteFile auth :: Auth
auth user :: Name Owner
user repo :: Name Repo
repo body :: DeleteFile
body =
    Auth -> GenRequest 'MtUnit 'RW () -> IO (Either Error ())
forall am (mt :: MediaType *) a (rw :: RW).
(AuthMethod am, ParseResponse mt a) =>
am -> GenRequest mt rw a -> IO (Either Error a)
executeRequest Auth
auth (GenRequest 'MtUnit 'RW () -> IO (Either Error ()))
-> GenRequest 'MtUnit 'RW () -> IO (Either Error ())
forall a b. (a -> b) -> a -> b
$ Name Owner -> Name Repo -> DeleteFile -> GenRequest 'MtUnit 'RW ()
deleteFileR Name Owner
user Name Repo
repo DeleteFile
body

-- | Delete a file.
-- See <https://developer.github.com/v3/repos/contents/#delete-a-file>
deleteFileR
    :: Name Owner
    -> Name Repo
    -> DeleteFile
    -> GenRequest 'MtUnit 'RW ()
deleteFileR :: Name Owner -> Name Repo -> DeleteFile -> GenRequest 'MtUnit 'RW ()
deleteFileR user :: Name Owner
user repo :: Name Repo
repo body :: DeleteFile
body =
    CommandMethod -> Paths -> ByteString -> GenRequest 'MtUnit 'RW ()
forall (mt :: MediaType *) a.
CommandMethod -> Paths -> ByteString -> GenRequest mt 'RW a
Command CommandMethod
Delete ["repos", Name Owner -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Owner
user, Name Repo -> Text
forall a. IsPathPart a => a -> Text
toPathPart Name Repo
repo, "contents", DeleteFile -> Text
deleteFilePath DeleteFile
body] (DeleteFile -> ByteString
forall a. ToJSON a => a -> ByteString
encode DeleteFile
body)