33<Class name =" MDX2JSON.Installer" >
44<TimeCreated >63481,77165.410085</TimeCreated >
55
6- <XData name =" Manifest " >
6+ <XData name =" Install " >
77<Description >
88See generated code in zsetup+1^MDX2JSON.Installer.1
99todo 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