Skip to content

Commit 588cdff

Browse files
committed
Online install and update.
Fixes #9
1 parent 1c30217 commit 588cdff

File tree

1 file changed

+155
-2
lines changed

1 file changed

+155
-2
lines changed

MDX2JSON/Installer.cls.xml

Lines changed: 155 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<Class name="MDX2JSON.Installer">
44
<TimeCreated>63481,77165.410085</TimeCreated>
55

6-
<XData name="Manifest">
6+
<XData name="Install">
77
<Description>
88
See generated code in zsetup+1^MDX2JSON.Installer.1
99
todo add optional parameter WEBAPP to Alter web app name if it needs to have another then namespace name</Description>
@@ -21,7 +21,14 @@ todo add optional parameter WEBAPP to Alter web app name if it needs to have ano
2121
</If>
2222
2323
<Namespace Name="${Namespace}" Create="no">
24+
<IfDef Var="SourceDir">
25+
<Log Text="SourceDir defined - offline install from ${SourceDir}" Level="0"/>
2426
<Import File="${SourceDir}"/>
27+
</IfDef>
28+
<IfNotDef Var="SourceDir">
29+
<Log Text="SourceDir undefined - online install from GitHub" Level="0"/>
30+
<RunInstall Class="MDX2JSON.Installer" Method="DownloadFromGitHub"/>
31+
</IfNotDef>
2532
<If Condition='(##class(Security.Applications).Exists("/"_"${Namespace}")=0)'>
2633
<Log Text="Creating web application /${Namespace}" Level="0"/>
2734
<!-- This method creates conflits with web-server. Kept for reference purposes. See ##class(%EnsembleMgr).createPortalApp()
@@ -63,7 +70,7 @@ do ##class(MDX2JSON.Installer).setup(.pVars)</Description>
6370
<CodeMode>objectgenerator</CodeMode>
6471
<FormalSpec><![CDATA[&pVars,pLogLevel:%Integer=0,pInstaller:%Installer.Installer]]></FormalSpec>
6572
<ReturnType>%Status</ReturnType>
66-
<Implementation><![CDATA[ Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "Manifest")
73+
<Implementation><![CDATA[ Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "Install")
6774
]]></Implementation>
6875
</Method>
6976

@@ -84,5 +91,151 @@ do ##class(MDX2JSON.Installer).setup(.pVars)</Description>
8491
quit $$$OK
8592
]]></Implementation>
8693
</Method>
94+
95+
<Method name="DownloadFromGitHub">
96+
<ClassMethod>1</ClassMethod>
97+
<FormalSpec>pVars,pLogLevel,tInstaller</FormalSpec>
98+
<ReturnType>%Status</ReturnType>
99+
<Implementation><![CDATA[
100+
Set Namespace=tInstaller.Evaluate("${Namespace}")
101+
Do tInstaller.PushNS("%SYS")
102+
Set tSC = ..Update(Namespace, "intersystems-ru", "Cache-MDX2JSON", "master")
103+
Do tInstaller.PopNS()
104+
If $$$ISERR(tSC) Throw ##class(%Installer.Exception).CreateFromStatus(tSC)
105+
quit $$$OK
106+
]]></Implementation>
107+
</Method>
108+
109+
<Method name="Update">
110+
<Description><![CDATA[
111+
Downloads and compiles GitHub repository.<br>
112+
<b>Owner</b> - The name of the repository owner.<br>
113+
<b>Repository</b> - The name of the repository.<br>
114+
<b>Branch</b> - The name of the commit/branch/tag. If skipped the repository’s default branch (usually master) would be used.<br>
115+
<b>Username</b> - GitHub user, who has access to repository. Optional for public repositories.<br>
116+
<b>Password</b> - GitHub password, corresponding to Username. Optional for public repositories.<br>
117+
Note, that with Username, you can make up to 5,000 requests per hour.
118+
For unauthenticated requests, the rate limit allows to make up to 60 requests per hour.
119+
Unauthenticated requests are associated with an IP address.<br>
120+
<b>Namespace</b> - Namespace, where to download and compile repository.<br>
121+
122+
For example in the repository: https://github.com/intersystems-ru/Cache-MDX2JSON<br>
123+
Owner - intersystems-ru, Repository - Cache-MDX2JSON.<br> ]]></Description>
124+
<ClassMethod>1</ClassMethod>
125+
<FormalSpec>Namespace=$Namespace,Owner:%String="intersystems-ru",Repository:%String="Cache-MDX2JSON",Branch:%String,Username:%String,Password:%String</FormalSpec>
126+
<ReturnType>%Status</ReturnType>
127+
<Implementation><![CDATA[
128+
Set namespace = $Namespace
129+
Set SSLConfig = "GitHub"
130+
131+
Zn "%SYS"
132+
Do:'##class(Security.SSLConfigs).Exists(SSLConfig) ##class(Security.SSLConfigs).Create(SSLConfig)
133+
134+
Set req=##class(%Net.HttpRequest).%New()
135+
Set req.Https=1
136+
Set req.SSLConfiguration=SSLConfig
137+
Set req.Server="api.github.com"
138+
Set req.Location = "repos/" _ Owner _ "/" _ Repository _ "/contents" // as described in https://developer.github.com/v3/repos/
139+
Do:$d(Branch) req.SetParam("ref",Branch) // if omitted the repository’s default branch (usually master) would be used
140+
Do req.SetHeader("Accept","application/vnd.github.v3+json") // we want to receive API v3
141+
142+
If ($d(Username) && $d(Password)) { // supply Username and Passwor, if both are provided. GitHub accept Basic Auth
143+
Set req.Username = Username // https://developer.github.com/v3/auth/
144+
Set req.Password = Password
145+
}
146+
147+
Set links = ##class(%ListOfDataTypes).%New()
148+
Set st = ..ProcessDirectory("",req,.links)
149+
Return:$$$ISERR(st) st
150+
151+
Zn Namespace
152+
Set st = ..DownloadFiles(links,req,.list)
153+
Set st2 = $system.OBJ.CompileList(.list)
154+
Zn namespace
155+
156+
Return $$$ADDSC(st, st2)
157+
]]></Implementation>
158+
</Method>
159+
160+
<Method name="ProcessDirectory">
161+
<Description><![CDATA[
162+
Process one directory of GitHub repository. Recursive.<br>
163+
<b>Path</b> -Internal repository path. Root is empty string<br>
164+
<b>Request</b> - Authenticated/Set %Net.HttpRequest object.<br>
165+
<b>Links</b> - List of links to raw files (which satisfy <b>IsCacheFile</b> conditions) from repository.<br>]]></Description>
166+
<ClassMethod>1</ClassMethod>
167+
<FormalSpec><![CDATA[Path:%String="",Request:%Net.HttpRequest,&Links:%ListOfDataTypes]]></FormalSpec>
168+
<ReturnType>%Status</ReturnType>
169+
<Implementation><![CDATA[
170+
Set location = Request.Location
171+
Set Request.Location = Request.Location _ Path
172+
173+
Set st = Request.Get()
174+
Return:$$$ISERR(st) st
175+
Return:(Request.HttpResponse.StatusCode = 404) $$$ERROR($$$GeneralError,"Repository doesn't exist OR you don't have access")
176+
Return:((Request.HttpResponse.StatusCode = 403) && (Request.HttpResponse.GetHeader("X-RATELIMIT-REMAINING")=0)) $$$ERROR($$$GeneralError,"API rate limit exceeded. Try logging in.")
177+
Return:(Request.HttpResponse.StatusCode '= 200) $$$ERROR($$$GCMHTTPStatus,Request.HttpResponse.StatusCode," expected 200")
178+
179+
#dim objects As List of %ZEN.proxyObject
180+
#dim obj As %ZEN.proxyObject
181+
Set st = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(Request.HttpResponse.Data,,.objects,1)
182+
Return:$$$ISERR(st) st
183+
184+
For i = 1:1:objects.Count() {
185+
Set obj = objects.GetAt(i)
186+
If (obj.type = "dir") {
187+
Set st = ..ProcessDirectory("/"_obj.name,Request,.Links)
188+
Return:$$$ISERR(st) st
189+
} ElseIf (obj.type = "file") {
190+
Do:..IsCacheFile(obj) Links.Insert(obj."download_url")
191+
} Else {
192+
// obj.type = "symlink" or obj.type = "submodule"
193+
}
194+
}
195+
Set Request.Location = location // to keep track of where in the repository tree we are
196+
Return $$$OK
197+
]]></Implementation>
198+
</Method>
199+
200+
<Method name="IsCacheFile">
201+
<Description>
202+
Check that incoming file is the one you need.</Description>
203+
<ClassMethod>1</ClassMethod>
204+
<FormalSpec>File:%ZEN.proxyObject</FormalSpec>
205+
<ReturnType>%Boolean</ReturnType>
206+
<Implementation><![CDATA[
207+
Set extensions = ",xml,cls,csp,csr,mac,int,bas,inc,gbl,prj,obj,pkg,gof,"
208+
Return:($L(File.name,".")=1) 0 //no extension
209+
Set File.Extension = $P(File.name,".",$L(File.name,"."))
210+
Return $F(extensions,","_File.Extension_",")
211+
]]></Implementation>
212+
</Method>
213+
214+
<Method name="DownloadFiles">
215+
<Description><![CDATA[
216+
Download list of files on https://raw.githubusercontent.com/ server.<br>
217+
<b>Links</b> - List of links to raw files.<br>
218+
<b>Request</b> - Authenticated/Set %Net.HttpRequest object.<br>
219+
<b>loadedlist</b> - Returns an array of the items loaded. ]]></Description>
220+
<ClassMethod>1</ClassMethod>
221+
<FormalSpec>Links:%ListOfDataTypes,Request:%Net.HttpRequest,*Items</FormalSpec>
222+
<ReturnType>%Status</ReturnType>
223+
<Implementation><![CDATA[
224+
Kill Items
225+
Set Request.Server = "raw.githubusercontent.com"
226+
Set st = $$$OK
227+
228+
For i = 1:1:Links.Count() {
229+
Set streq = Request.Get($e(Links.GetAt(i),35,*)) // Remove "https://raw.githubusercontent.com/" from URL.
230+
Set:$$$ISERR(streq) st=$$$ADDSC(st, streq)
231+
Set stload = $system.OBJ.LoadStream(Request.HttpResponse.Data,"",.error,.items)
232+
Set:$$$ISERR(stload) st=$$$ADDSC(st, stload)
233+
Merge Items = items
234+
}
235+
236+
Set Request.Server="api.github.com"
237+
Return st
238+
]]></Implementation>
239+
</Method>
87240
</Class>
88241
</Export>

0 commit comments

Comments
 (0)