aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/program/aedifex/repository/remote.lux
blob: fd0d65d6ff578364b7b6ca72780f4b7e472fa9b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
(.module:
  [lux #*
   [ffi (#+ import:)]
   [abstract
    [monad (#+ do)]]
   [control
    ["." io (#+ IO)]
    ["." try]
    ["." exception (#+ exception:)]]
   [data
    ["." binary]
    ["." text
     ["%" format (#+ format)]]]
   [math
    [number
     ["n" nat]]]
   [tool
    [compiler
     ["." version]
     ["." language #_
      ["#/." lux #_
       ["#" version]]]]]
   [world
    [net (#+ URL)
     [uri (#+ URI)]]]]
  ["." //
   ["#." identity (#+ Identity)]
   ["/#" // #_
    ["#." artifact (#+ Version Artifact)
     [extension (#+ Extension)]]]])

(type: #export Address
  URL)

(import: java/lang/String)

(import: java/lang/AutoCloseable
  ["#::."
   (close [] #io #try void)])

(import: java/io/InputStream)

(import: java/io/OutputStream
  ["#::."
   (flush [] #io #try void)
   (write [[byte]] #io #try void)])

(import: java/net/URLConnection
  ["#::."
   (setDoOutput [boolean] #io #try void)
   (setRequestProperty [java/lang/String java/lang/String] #io #try void)
   (getInputStream [] #io #try java/io/InputStream)
   (getOutputStream [] #io #try java/io/OutputStream)])

(import: java/net/HttpURLConnection
  ["#::."
   (setRequestMethod [java/lang/String] #io #try void)
   (getResponseCode [] #io #try int)])

(import: java/net/URL
  ["#::."
   (new [java/lang/String])
   (openConnection [] #io #try java/net/URLConnection)])

(import: java/io/BufferedInputStream
  ["#::."
   (new [java/io/InputStream])
   (read [[byte] int int] #io #try int)])

(exception: #export (no_credentials {address Address})
  (exception.report
   ["Address" (%.text address)]))

(exception: #export (deployment_failure {code Int})
  (exception.report
   ["Code" (%.int code)]))

(def: #export (uri version_template artifact extension)
  (-> Version Artifact Extension URI)
  (format (///artifact.uri version_template artifact) extension))

(def: buffer_size
  (n.* 512 1,024))

(def: user_agent
  (format "LuxAedifex/" (version.format language/lux.version)))

(structure: #export (repository identity address)
  (All [s] (-> (Maybe Identity) Address (//.Repository IO)))

  (def: (download uri)
    (do {! (try.with io.monad)}
      [connection (|> (format address uri)
                      java/net/URL::new
                      java/net/URL::openConnection)
       #let [connection (:coerce java/net/HttpURLConnection connection)]
       _ (java/net/HttpURLConnection::setRequestMethod "GET" connection)
       _ (java/net/URLConnection::setRequestProperty "User-Agent" ..user_agent connection)
       input (|> connection
                 java/net/URLConnection::getInputStream
                 (\ ! map (|>> java/io/BufferedInputStream::new)))
       #let [buffer (binary.create ..buffer_size)]
       output (loop [output (\ binary.monoid identity)]
                (do !
                  [bytes_read (java/io/BufferedInputStream::read buffer +0 (.int ..buffer_size) input)]
                  (case bytes_read
                    -1 (do !
                         [_ (java/lang/AutoCloseable::close input)]
                         (wrap output))
                    +0 (recur output)
                    _ (if (n.= ..buffer_size bytes_read)
                        (recur (\ binary.monoid compose output buffer))
                        (do !
                          [chunk (\ io.monad wrap (binary.slice 0 (dec (.nat bytes_read)) buffer))]
                          (recur (\ binary.monoid compose output chunk)))))))]
      (wrap output)))

  (def: (upload uri content)
    (case identity
      #.None
      (\ io.monad wrap (exception.throw ..no_credentials [address]))
      
      (#.Some [user password])
      (do (try.with io.monad)
        [connection (|> (format address uri)
                        java/net/URL::new
                        java/net/URL::openConnection)
         #let [connection (:coerce java/net/HttpURLConnection connection)]
         _ (java/net/HttpURLConnection::setRequestMethod "PUT" connection)
         _ (java/net/URLConnection::setDoOutput true connection)
         _ (java/net/URLConnection::setRequestProperty "Authorization" (//identity.basic_auth user password) connection)
         stream (java/net/URLConnection::getOutputStream connection)
         _ (java/io/OutputStream::write content stream)
         _ (java/io/OutputStream::flush stream)
         _ (java/lang/AutoCloseable::close stream)
         code (java/net/HttpURLConnection::getResponseCode connection)]
        (case code
          +201 (wrap [])
          _ (\ io.monad wrap (exception.throw ..deployment_failure [code]))))))
  )