@@ -6,6 +6,7 @@ import gleam/http/response
66import gleam/httpc
77import gleam/io
88import gleam/json
9+ import gleam/option . { type Option , None , Some }
910import gleam/result
1011import gleam/string
1112
@@ -28,11 +29,21 @@ pub type GitHubResponse {
2829 GitHubFileResponse ( content : String , encoding : String , sha : String , size : Int )
2930}
3031
32+ /// The required fields to create a new file in a GitHub repo.
33+ /// Message is the commit message
34+ /// Content is the base64 encoded text content of the file
35+ pub type GitHubFile {
36+ GitHubFile ( message : String , content : String )
37+ }
38+
3139pub fn repos_url ( config : GitHubConfig ) -> String {
3240 config . base_url <> "/repos"
3341}
3442
35- pub fn read_file (
43+ /// Get a file object from a GitHub repository at the given path
44+ /// Path should be a '/' separated String, e.g:
45+ /// 'foo/bar/baz'
46+ pub fn get_file (
3647 config : GitHubConfig ,
3748 path : String ,
3849) -> Result ( response . Response ( String ) , GitStoreError ) {
@@ -46,10 +57,15 @@ pub fn read_file(
4657 <> "/"
4758 <> path
4859
49- request ( config , http . Get , url )
60+ request ( config , http . Get , url , None )
5061}
5162
52- fn request ( config : GitHubConfig , method : http . Method , endpoint : String ) {
63+ fn request (
64+ config : GitHubConfig ,
65+ method : http . Method ,
66+ endpoint : String ,
67+ json_body : Option ( String ) ,
68+ ) {
5369 use req <- result . try (
5470 request . to ( endpoint )
5571 |> result . map_error ( fn ( _ ) {
@@ -62,6 +78,7 @@ fn request(config: GitHubConfig, method: http.Method, endpoint: String) {
6278 |> request . set_header ( "Authorization" , "Bearer " <> config . token )
6379 |> request . set_header ( "Accept" , "application/vnd.github+json" )
6480 |> request . set_header ( "User-Agent" , "GitStore-Gleam" )
81+ |> utils . set_json ( json_body )
6582 |> request . set_method ( method )
6683 |> httpc . send ( )
6784
@@ -72,18 +89,30 @@ fn request(config: GitHubConfig, method: http.Method, endpoint: String) {
7289 } )
7390}
7491
92+ /// Parse the JSON data from file.body, converting the base64 encoded content
93+ /// into a String
7594fn file_from_json (
7695 json_string : String ,
7796) -> Result ( GitHubResponse , json . DecodeError ) {
97+ logging . log ( logging . Debug , json_string )
7898 let file_decoder = {
7999 use content <- decode . field (
80100 "content" ,
81101 decode . then ( decode . string , fn ( item ) {
82102 let decoded =
83- item |> bit_array . base64_decode |> result . try ( bit_array . to_string )
103+ item
104+ |> string . replace ( "\n " , "" )
105+ |> bit_array . base64_decode
106+ |> result . try ( bit_array . to_string )
84107 case decoded {
85108 Ok ( str ) -> decode . success ( str )
86- Error ( _ ) -> decode . failure ( "" , "A base64 encoded String" )
109+ Error ( _ ) -> {
110+ logging . log (
111+ logging . Error ,
112+ "Failed to decode expected base64 string: " <> item ,
113+ )
114+ decode . failure ( "" , "A base64 encoded String" )
115+ }
87116 }
88117 } ) ,
89118 )
@@ -95,15 +124,47 @@ fn file_from_json(
95124 json . parse ( json_string , using : file_decoder )
96125}
97126
127+ fn file_to_json ( file : GitHubFile ) -> String {
128+ json . object ( [
129+ # ( "message" , json . string ( file . message ) ) ,
130+ # ( "content" , json . string ( file . content ) ) ,
131+ ] )
132+ |> json . to_string
133+ }
134+
135+ fn create_file ( config : GitHubConfig , filename : String , content : String ) {
136+ let url =
137+ utils . build_path ( config . base_url , [
138+ "repos" ,
139+ config . owner ,
140+ config . repo ,
141+ "contents" ,
142+ ] )
143+ <> "/"
144+ <> filename
145+ let content =
146+ content
147+ |> bit_array . from_string
148+ |> bit_array . base64_encode ( True )
149+ let file = GitHubFile ( "add: " <> filename , content : )
150+ let res = request ( config , http . Put , url , Some ( file |> file_to_json ) )
151+ logging . log ( logging . Debug , "Writing file: " <> string . inspect ( res ) )
152+ }
153+
98154pub fn main ( ) -> Nil {
99155 logging . configure ( )
156+ logging . set_level ( logging . Debug )
100157 let owner = envoy . get ( "GITHUB_OWNER" ) |> result . unwrap ( "" )
101158 let repo = envoy . get ( "GITHUB_REPO" ) |> result . unwrap ( "" )
102159 let token = envoy . get ( "GITHUB_TOKEN" ) |> result . unwrap ( "" )
103160 let base_url =
104161 envoy . get ( "GITHUB_BASE_URL" ) |> result . unwrap ( "https://api.github.com" )
105162 let config = GithubConfig ( owner , repo , token , base_url )
106- let file = read_file ( config , "README.md" ) |> result . unwrap ( response . new ( 400 ) )
163+ logging . log ( logging . Debug , config |> string . inspect )
164+ let file = get_file ( config , "README.md" ) |> result . unwrap ( response . new ( 400 ) )
165+ echo file_from_json ( file . body )
166+ let new_file = create_file ( config , "test" , "foo bar baz" )
167+ let file = get_file ( config , "test" ) |> result . unwrap ( response . new ( 400 ) )
107168 echo file_from_json ( file . body )
108169 io . println ( "Hello from git_store!" )
109170}
0 commit comments