1- script "com.livecode.library.extension-package "
1+ script "com.livecode.library.extension-utils "
22/*
3- This library provides handlers for managing livecode extension packages
3+ Title: Extension Package Handling Utilities
4+
5+ Summary: This library provides handlers for managing livecode extension packages
6+
7+ Version: 1.0.0
48*/
59
10+ on extensionInitialize
11+ if the target is not me then
12+ pass extensionInitialize
13+ end if
14+
15+ insert the script of me into back
16+
17+ if the environment contains "development" then
18+ set the _ideoverride of me to true
19+ end if
20+ end extensionInitialize
21+
22+ on extensionFinalize
23+ if the target is not me then
24+ pass extensionFinalize
25+ end if
26+
27+ remove the script of me from back
28+ end extensionFinalize
29+
630private command log pMsg
731 write pMsg & return to stdout
832end log
@@ -70,6 +94,115 @@ private command __EnsureExternal pExternal
7094 end if
7195end __EnsureExternal
7296
97+ private on __addToDependencies pDependee, pDependent, @xDependencies
98+ # AL-2015-04-13: [[ Bug 15216 ]] Use keys of array to remove duplicates
99+ put true into xDependencies[pDependee ][pDependent ]
100+ end __addToDependencies
101+
102+ private on __addToList pNode, @xList
103+ if xList is empty then
104+ put pNode into xList
105+ else
106+ put return & pNode after xList
107+ end if
108+ end __addToList
109+
110+ private on __removeFromList pNode, @xList
111+ get lineOffset (pNode , xList)
112+ if it is not 0 then
113+ delete line it of xList
114+ end if
115+ end __removeFromList
116+
117+ private on __visitNode pDependencies, pNode, @xUnmarked, @xMarked, @xTemporaryMarked, @xOrder
118+ if pNode is among the lines of xTemporaryMarked then
119+ return "Error"
120+ end if
121+ if pNode is among the lines of xMarked then
122+ # AL-2015-04-13: [[ Bug 15216 ]] Remove from unmarked if this was already marked
123+ __removeFromList pNode , xUnmarked
124+ return ""
125+ end if
126+ __addToList pNode , xTemporaryMarked
127+ repeat for each key tNode in pDependencies [pNode ]
128+ __visitNode pDependencies , tNode , xUnmarked, xMarked, xTemporaryMarked, xOrder
129+ if the result is not empty then
130+ return "Error"
131+ end if
132+ end repeat
133+ __addToList pNode , xMarked
134+ __removeFromList pNode , xUnmarked
135+ __removeFromList pNode , xTemporaryMarked
136+ __addToList pNode , xOrder
137+ end __visitNode
138+
139+ private function __dependencyOrder pDependencies, pList
140+ local tUnmarked , tTemporaryMarked , tMarked , tOrder , tToVisit
141+ put pList into tUnmarked
142+ repeat while tUnmarked is not empty
143+ put any line of tUnmarked into tToVisit
144+ __visitNode pDependencies , tToVisit , tUnmarked , tMarked , tTemporaryMarked , tOrder
145+ if the result is not empty then
146+ throw "Circularity in dependencies starting from" && tToVisit
147+ return empty
148+ end if
149+ end repeat
150+ return tOrder
151+ end __dependencyOrder
152+
153+ private function __extensionIsBuiltin pID
154+ switch pID
155+ case "com.livecode.widget"
156+ case "com.livecode.engine"
157+ case "com.livecode.canvas"
158+ case "com.livecode.foreign"
159+ case "com.livecode.arithmetic"
160+ case "com.livecode.array"
161+ case "com.livecode.binary"
162+ case "com.livecode.bitwise"
163+ case "com.livecode.byte"
164+ case "com.livecode.char"
165+ case "com.livecode.codeunit"
166+ case "com.livecode.date"
167+ case "com.livecode.file"
168+ case "com.livecode.list"
169+ case "com.livecode.logic"
170+ case "com.livecode.mathfoundation"
171+ case "com.livecode.math"
172+ case "com.livecode.sort"
173+ case "com.livecode.stream"
174+ case "com.livecode.string"
175+ case "com.livecode.system"
176+ case "com.livecode.type"
177+ case "com.livecode.typeconvert"
178+ case "com.livecode.extensions.libbrowser"
179+ case "com.livecode.java"
180+ case "com.livecode.objc"
181+ case "com.livecode.commercial.license"
182+ return true
183+ default
184+ return false
185+ end switch
186+ end __extensionIsBuiltin
187+
188+ function extensionsOrderByDependency pExtensions, pRequiresA, \
189+ pIncludeBuiltin
190+ # Accumulate an array of dependencies
191+ local tDependencies , tRequirements
192+ repeat for each line tExtension in pExtensions
193+ put pRequiresA [tExtension ] into tRequirements
194+ repeat for each element tDependent in tRequirements
195+ if not pIncludeBuiltin and __extensionIsBuiltin(tDependent ) then
196+ next repeat
197+ end if
198+ __addToDependencies tExtension , tDependent , tDependencies
199+ end repeat
200+ end repeat
201+
202+ # Order them
203+ return __dependencyOrder(tDependencies , pExtensions )
204+ end extensionsOrderByDependency
205+
73206private function __extensionResourcePath
74207 if the environment begins with "development" then
75208 if revEnvironmentIsInstalled() is false then
@@ -228,6 +361,8 @@ command buildPackageAndExtractExtension pProtectifyScript, \
228361 pSourceFolder , pSourceFileName , pTargetFolder , \
229362 pCommercialExtension , pLCCompile , pInterfaceFolder
230363
364+ log "HERE ALSO"
365+
231366 if pCommercialExtension is true and \
232367 not (pSourceFileName ends with ".lcb" ) then
233368 protectStack pProtectifyScript , pSourceFolder , \
@@ -252,11 +387,11 @@ command buildPackageAndExtractExtension pProtectifyScript, \
252387 extractExtension tPackage , pSourceFolder , pTargetFolder
253388 delete file tPackage
254389end buildPackageAndExtractExtension
255-
390+
256391private function q pParam
257392 return quote & pParam & quote
258393end q
259-
394+
260395command protectStack pProtectifyScript, pSourceFolder, pSourceFileName, pOutput, pGitHash
261396 if there is not a stack pProtectifyScript then
262397 throw "Error: could not load script protector:" && pProtectifyScript
@@ -324,7 +459,7 @@ command extractDocs pDocsParser, pOutputDir
324459 put tDocs into url ("binfile:" & pOutputDir & "/" & tName & ".lcdoc" )
325460 end repeat
326461end extractDocs
327-
462+
328463private command addFolderToArchive pBaseFolder, pArchive, pRemoveSource, pSourceFileName, pSupportFiles
329464 # First add the files, then recusively add any sub folders
330465 local tFiles
@@ -398,9 +533,9 @@ private command packageExtension pExtensionName, pSourceFolder, pSourceFileName,
398533 put pExtensionName into tTargetDir
399534 put pTargetFolder & slash & tTargetDir into tBuildTarget
400535 put pSourceFolder & slash & tTargetDir & ".lce" into tZip
401-
536+
402537 write "packaging extension" && pSourceFileName && \
403- "to" && tZip & return to stdout
538+ "to" && tZip & return to stdout
404539
405540 if there is a file tZip then
406541 delete file tZip
@@ -414,8 +549,8 @@ private command packageExtension pExtensionName, pSourceFolder, pSourceFileName,
414549
415550 if tError is empty then
416551 addFolderToArchive pSourceFolder , tZip , pRemoveSource , \
417- pSourceFileName , pSupportFiles
418-
552+ pSourceFileName , pSupportFiles
553+
419554 if the result begins with "ziperr" then
420555 put the result into tError
421556 end if
@@ -637,3 +772,111 @@ command extensionGenerateManifestForLCSExtension pDocsParser, pSourceFolder
637772 log "writing manifest to" && pSourceFolder & slash & "manifest.xml"
638773 put textEncode (tXML , "utf-8" ) into url("binfile:" & pSourceFolder & slash & "manifest.xml" )
639774end extensionGenerateManifestForLCSExtension
775+
776+
777+ private command __SetMetadata pKey, pValue, @xArray
778+ split pKey by "."
779+ put pValue into xArray[pKey ]
780+ end __SetMetadata
781+
782+ function extensionFetchMetadata pManifestPath
783+ local tDataA
784+
785+ local tManifestContents , tTreeID
786+ put url ("file:" & pManifestPath ) into tManifestContents
787+ put revXMLCreateTree(tManifestContents ,true ,true ,false ) into tTreeID
788+
789+ if tTreeID begins with "xmlerr" then
790+ return "Error: invalid xml in manifest" for error
791+ end if
792+
793+ local tTargetType
794+ put textDecode (revXMLNodeContents (tTreeID , "/package/type" ), "utf-8" ) into tTargetType
795+
796+ if tTargetType begins with "xmlerr" then
797+ return "Error: no type found in manifest" for error
798+ end if
799+ put tTargetType into tDataA ["type" ]
800+
801+ local tTargetName
802+ put textDecode (revXMLNodeContents (tTreeID , "/package/name" ), "utf-8" ) into tTargetName
803+ if tTargetName begins with "xmlerr" then
804+ return "Error: couldn't retrieve extension name from manifest" for error
805+ end if
806+ put tTargetName into tDataA ["name" ]
807+
808+ local tTargetTitle
809+ put textDecode (revXMLNodeContents (tTreeID , "/package/title" ), "utf-8" ) into tTargetTitle
810+
811+ if tTargetTitle is empty or tTargetTitle begins with "xmlerr" then
812+ put empty into tTargetTitle
813+ end if
814+ put tTargetTitle into tDataA ["title" ]
815+
816+ local tTargetVersion
817+ put textDecode (revXMLNodeContents (tTreeID , "/package/version" ), "utf-8" ) into tTargetVersion
818+
819+ if tTargetVersion is empty or tTargetVersion begins with "xmlerr" then
820+ put empty into tTargetVersion
821+ end if
822+ put tTargetVersion into tDataA ["version" ]
823+
824+ local tTargetAuthor
825+ put textDecode (revXMLNodeContents (tTreeID , "/package/author" ), "utf-8" ) into tTargetAuthor
826+ if tTargetAuthor is empty or tTargetAuthor begins with "xmlerr" then
827+ put empty into tTargetAuthor
828+ end if
829+ put tTargetAuthor into tDataA ["author" ]
830+
831+ # Fetch property metadata
832+ local tMetadataValue , tMetadataKey
833+ local tMetadataNodes , tMetadataA , tKeys , tValue
834+ put revXMLChildNames (tTreeID , "package" ,return,"metadata" ,true ) into tMetadataNodes
835+ repeat for each line tMetadata in tMetadataNodes
836+ put revXMLAttribute (tTreeID ,"package" & "/" & tMetadata ,"key" ) into tMetadataKey
837+ put revXMLNodeContents (tTreeID ,"package" & "/" & tMetadata ) into tMetadataValue
838+ if tMetadataValue is empty or tMetadataValue begins with "xmlerr" then
839+ put empty into tMetadataValue
840+ end if
841+ __SetMetadata tMetadataKey , tMetadataValue , tDataA
842+ end repeat
843+
844+ # Fetch extension dependencies
845+ local tRequires , tCount
846+ put 0 into tCount
847+ put revXMLChildNames (tTreeID ,"package" ,return,"requires" ,true ) into tRequires
848+ repeat for each line tDependency in tRequires
849+ add 1 to tCount
850+ local tName
851+ put revXMLAttribute (tTreeID ,"package" & "/" & tDependency ,"name" ) into tName
852+ put tName into tDataA ["requires" ][tCount ]
853+ end repeat
854+
855+ # Fetch library handlers
856+ if tTargetType is "library" then
857+ local tHandlerList , tHandlerNodes
858+ put revXMLChildNames (tTreeID , "package" ,return,"handler" ,true ) into tHandlerNodes
859+ repeat for each line tHandler in tHandlerNodes
860+ local tHandlerName
861+ put revXMLAttribute (tTreeID ,"package" & "/" & tHandler ,"name" ) into tHandlerName
862+
863+ if tHandlerName is empty or tHandlerName begins with "xmlerr" then
864+ next repeat
865+ end if
866+
867+ if tHandlerList is empty then
868+ put tHandlerName into tHandlerList
869+ else
870+ put return & tHandlerName after tHandlerList
871+ end if
872+ end repeat
873+ put tHandlerList into tDataA ["handlers" ]
874+ end if
875+
876+ # User visible should default to true
877+ if tDataA ["uservisible" ] is empty then
878+ put true into tDataA ["uservisible" ]
879+ end if
880+
881+ return tDataA for value
882+ end extensionFetchMetadata
0 commit comments