1
|
1 |
"{ Package: 'stx:goodies/metacello' }"
|
|
2 |
|
|
3 |
Object subclass:#MetacelloPlatform
|
|
4 |
instanceVariableNames:'bypassProgressBars bypassGoferLoadUpdateCategories'
|
|
5 |
classVariableNames:'Current'
|
|
6 |
poolDictionaries:''
|
|
7 |
category:'Metacello-Core-Model'
|
|
8 |
!
|
|
9 |
|
|
10 |
|
|
11 |
!MetacelloPlatform class methodsFor:'accessing'!
|
|
12 |
|
|
13 |
current
|
|
14 |
Current
|
|
15 |
ifNil: [Current := MetacelloPlatform new].
|
|
16 |
^ Current
|
|
17 |
! !
|
|
18 |
|
|
19 |
!MetacelloPlatform class methodsFor:'initialize-release'!
|
|
20 |
|
|
21 |
initialize
|
|
22 |
"MetacelloPlatform initialize"
|
|
23 |
"MetacelloGemStonePlatform initialize"
|
|
24 |
"MetacelloPharoPlatform initialize"
|
|
25 |
"MetacelloSqueakPlatform initialize"
|
|
26 |
|
|
27 |
Current := self new
|
|
28 |
! !
|
|
29 |
|
|
30 |
!MetacelloPlatform methodsFor:'accessing'!
|
|
31 |
|
|
32 |
bypassGoferLoadUpdateCategories
|
|
33 |
|
|
34 |
bypassGoferLoadUpdateCategories == nil ifTrue: [ bypassGoferLoadUpdateCategories := false ].
|
|
35 |
^ bypassGoferLoadUpdateCategories
|
|
36 |
!
|
|
37 |
|
|
38 |
bypassGoferLoadUpdateCategories: anObject
|
|
39 |
bypassGoferLoadUpdateCategories := anObject
|
|
40 |
!
|
|
41 |
|
|
42 |
bypassProgressBars
|
|
43 |
|
|
44 |
bypassProgressBars == nil ifTrue: [ bypassProgressBars := false ].
|
|
45 |
^ bypassProgressBars
|
|
46 |
!
|
|
47 |
|
|
48 |
bypassProgressBars: anObject
|
|
49 |
bypassProgressBars := anObject
|
|
50 |
! !
|
|
51 |
|
|
52 |
!MetacelloPlatform methodsFor:'attributes'!
|
|
53 |
|
|
54 |
defaultPlatformAttributes
|
|
55 |
| versionString |
|
|
56 |
Smalltalk at: #SystemVersion ifPresent: [:cl |
|
|
57 |
versionString := cl current version.
|
|
58 |
(versionString beginsWith: 'Pharo')
|
|
59 |
ifTrue: [ ^ #(#squeakCommon #pharo ) ].
|
|
60 |
(versionString beginsWith: 'Squeak')
|
|
61 |
ifTrue: [^ #(#squeakCommon #squeak )].
|
|
62 |
"see http://code.google.com/p/metacello/issues/detail?id=146"
|
|
63 |
(versionString includesSubString: 'Pharo')
|
|
64 |
ifTrue: [ ^ #(#squeakCommon #pharo ) ].
|
|
65 |
(versionString includesSubString: 'Squeak')
|
|
66 |
ifTrue: [^ #(#squeakCommon #squeak )].
|
|
67 |
self error: 'Unrecognized version of Squeak/Pharo: ', versionString ].
|
|
68 |
^ #(#gemstone )
|
|
69 |
! !
|
|
70 |
|
|
71 |
!MetacelloPlatform methodsFor:'caching'!
|
|
72 |
|
|
73 |
clearCurrentVersionCache
|
|
74 |
MetacelloClearStackCacheNotification signal: #(#currentVersion #currentVersionAgainst: #currentVersionInfo)
|
|
75 |
!
|
|
76 |
|
|
77 |
primeStackCacheFor: cacheName doing: noArgBlock defaultDictionary: aDictionary
|
|
78 |
|
|
79 |
self deprecated: 'use #primeStackCacheWith:doing:'.
|
|
80 |
self
|
|
81 |
useStackCacheDuring: [:dict | | cache |
|
|
82 |
cache := dict at: cacheName ifAbsent: [].
|
|
83 |
cache == nil
|
|
84 |
ifTrue: [
|
|
85 |
cache := Dictionary new.
|
|
86 |
dict at: cacheName put: cache ].
|
|
87 |
^noArgBlock value ]
|
|
88 |
defaultDictionary: aDictionary
|
|
89 |
!
|
|
90 |
|
|
91 |
primeStackCacheWith: aDictionary doing: noArgBlock
|
|
92 |
|
|
93 |
self
|
|
94 |
useStackCacheDuring: [:dict | ^noArgBlock value ]
|
|
95 |
defaultDictionary: aDictionary
|
|
96 |
!
|
|
97 |
|
|
98 |
stackCacheFor: cacheName at: key doing: aBlock
|
|
99 |
|
|
100 |
^self stackCacheFor: cacheName cacheClass: Dictionary at: key doing: aBlock
|
|
101 |
!
|
|
102 |
|
|
103 |
stackCacheFor: cacheName cacheClass: cacheClass at: key doing: aBlock
|
|
104 |
|
|
105 |
self
|
|
106 |
useStackCacheDuring: [:dict | | cache |
|
|
107 |
cache := dict at: cacheName ifAbsent: [].
|
|
108 |
cache ~~ nil
|
|
109 |
ifTrue: [ | value hasEntry |
|
|
110 |
hasEntry := true.
|
|
111 |
value := cache at: key ifAbsent: [ hasEntry := false ].
|
|
112 |
hasEntry ifTrue: [ ^value ]]
|
|
113 |
ifFalse: [
|
|
114 |
cache := cacheClass new.
|
|
115 |
dict at: cacheName put: cache ].
|
|
116 |
^aBlock value: cache ]
|
|
117 |
defaultDictionary: nil
|
|
118 |
!
|
|
119 |
|
|
120 |
useStackCacheDuring: aBlock defaultDictionary: defaultDictionary
|
|
121 |
| dict |
|
|
122 |
dict := MetacelloStackCacheNotification signal.
|
|
123 |
dict == nil
|
|
124 |
ifTrue: [
|
|
125 |
dict := defaultDictionary == nil
|
|
126 |
ifTrue: [ Dictionary new ]
|
|
127 |
ifFalse: [ defaultDictionary ] ].
|
|
128 |
[ ^ aBlock value: dict ]
|
|
129 |
on: MetacelloStackCacheNotification , MetacelloClearStackCacheNotification
|
|
130 |
do: [ :ex |
|
|
131 |
(ex isKindOf: MetacelloStackCacheNotification)
|
|
132 |
ifTrue: [ ex resume: dict ].
|
|
133 |
(ex isKindOf: MetacelloClearStackCacheNotification)
|
|
134 |
ifTrue: [
|
|
135 |
| keys |
|
|
136 |
keys := ex cacheNames.
|
|
137 |
keys ifNil: [ keys := dict keys ].
|
|
138 |
keys
|
|
139 |
do: [ :k |
|
|
140 |
(dict includesKey: k)
|
|
141 |
ifTrue: [
|
|
142 |
| c |
|
|
143 |
c := dict at: k.
|
|
144 |
c keys do: [ :ck | c removeKey: ck ].
|
|
145 |
dict removeKey: k ] ].
|
|
146 |
ex resume ] ]
|
|
147 |
! !
|
|
148 |
|
|
149 |
!MetacelloPlatform methodsFor:'github support'!
|
|
150 |
|
|
151 |
downloadFile: url to: outputFileName
|
|
152 |
"download from <url> into <outputFileName>"
|
|
153 |
|
|
154 |
self subclassResponsibility
|
|
155 |
!
|
|
156 |
|
|
157 |
extractRepositoryFrom: zipFile to: directory
|
|
158 |
"unzip <zipFile> into <directory>"
|
|
159 |
|
|
160 |
self subclassResponsibility
|
|
161 |
!
|
|
162 |
|
|
163 |
fileDirectoryClass
|
|
164 |
|
|
165 |
^FileDirectory
|
|
166 |
! !
|
|
167 |
|
|
168 |
!MetacelloPlatform methodsFor:'notification'!
|
|
169 |
|
|
170 |
collection: aCollection do: aBlock displaying: aString
|
|
171 |
|
|
172 |
aCollection do: aBlock
|
|
173 |
!
|
|
174 |
|
|
175 |
do: aBlock displaying: aString
|
|
176 |
|
|
177 |
aBlock value
|
|
178 |
! !
|
|
179 |
|
|
180 |
!MetacelloPlatform methodsFor:'reflection'!
|
|
181 |
|
|
182 |
copyClass: oldClass as: newName inCategory: newCategoryName
|
|
183 |
|
|
184 |
self subclassResponsibility
|
|
185 |
!
|
|
186 |
|
|
187 |
globalNamed: globalName
|
|
188 |
|
|
189 |
^Smalltalk at: globalName
|
|
190 |
!
|
|
191 |
|
|
192 |
globalNamed: globalName ifAbsent: absentBlock
|
|
193 |
|
|
194 |
^Smalltalk at: globalName ifAbsent: absentBlock
|
|
195 |
! !
|
|
196 |
|
|
197 |
!MetacelloPlatform methodsFor:'repository creation'!
|
|
198 |
|
|
199 |
createRepository: aRepositorySpec
|
|
200 |
| type |
|
|
201 |
type := aRepositorySpec type.
|
|
202 |
type = 'http'
|
|
203 |
ifTrue: [
|
|
204 |
^ MCHttpRepository
|
|
205 |
location: aRepositorySpec description
|
|
206 |
user: aRepositorySpec username
|
|
207 |
password: aRepositorySpec password ].
|
|
208 |
type = 'directory'
|
|
209 |
ifTrue: [ ^ MCDirectoryRepository new directory: (FileDirectory on: aRepositorySpec description) ].
|
|
210 |
Smalltalk
|
|
211 |
at: #'MCFileTreeRepository'
|
|
212 |
ifPresent: [ :cl |
|
|
213 |
type = 'filetree'
|
|
214 |
ifTrue: [
|
|
215 |
| description headerSize |
|
|
216 |
description := aRepositorySpec description.
|
|
217 |
headerSize := 'filetree://' size.
|
|
218 |
^ cl new
|
|
219 |
directory:
|
|
220 |
(FileDirectory on: (aRepositorySpec description copyFrom: headerSize + 1 to: description size)) ] ].
|
|
221 |
Smalltalk
|
|
222 |
at: #'MCGitHubRepository'
|
|
223 |
ifPresent: [ :cl |
|
|
224 |
type = 'github'
|
|
225 |
ifTrue: [ ^ cl location: aRepositorySpec description ] ].
|
|
226 |
type = 'dictionary'
|
|
227 |
ifTrue: [
|
|
228 |
| description headerSize globalName |
|
|
229 |
description := aRepositorySpec description.
|
|
230 |
headerSize := 'dictionary://' size.
|
|
231 |
globalName := (description copyFrom: headerSize + 1 to: description size) asSymbol.
|
|
232 |
^ Smalltalk
|
|
233 |
at: globalName
|
|
234 |
ifAbsent: [
|
|
235 |
Smalltalk
|
|
236 |
at: globalName
|
|
237 |
put:
|
|
238 |
(MCDictionaryRepository new
|
|
239 |
description: description;
|
|
240 |
yourself) ] ].
|
|
241 |
^ nil
|
|
242 |
!
|
|
243 |
|
|
244 |
extractTypeFromDescription: description
|
|
245 |
description == nil
|
|
246 |
ifTrue: [ ^ nil ].
|
|
247 |
((description beginsWith: '/') or: [ description second = $: ])
|
|
248 |
ifTrue: [ ^ 'directory' ].
|
|
249 |
(description beginsWith: 'dictionary://')
|
|
250 |
ifTrue: [ ^ 'dictionary' ].
|
|
251 |
(description beginsWith: 'filetree://')
|
|
252 |
ifTrue: [ ^ 'filetree' ].
|
|
253 |
(description beginsWith: 'github://')
|
|
254 |
ifTrue: [ ^ 'github' ].
|
|
255 |
^ 'http'
|
|
256 |
! !
|
|
257 |
|
|
258 |
!MetacelloPlatform methodsFor:'scripting'!
|
|
259 |
|
|
260 |
defaultRepositoryDescription
|
|
261 |
^ 'http://www.squeaksource.com/MetacelloRepository'
|
|
262 |
! !
|
|
263 |
|
|
264 |
!MetacelloPlatform methodsFor:'tests'!
|
|
265 |
|
|
266 |
defaultTimeout
|
|
267 |
"squeak compatability"
|
|
268 |
^60
|
|
269 |
! !
|
|
270 |
|
|
271 |
!MetacelloPlatform methodsFor:'transactions'!
|
|
272 |
|
|
273 |
transact: aBlock
|
|
274 |
"On GemStone, we want to optionally abort before command execution and commit after
|
|
275 |
common execution. Other plaforms don't need to do anything special.
|
|
276 |
Returning out of block, skips commit."
|
|
277 |
|
|
278 |
aBlock value
|
|
279 |
! !
|
|
280 |
|
|
281 |
!MetacelloPlatform methodsFor:'user interaction'!
|
|
282 |
|
|
283 |
confirm: aString
|
|
284 |
|
|
285 |
^(Smalltalk hasClassNamed: #UIManager)
|
|
286 |
ifTrue: [ (Smalltalk classNamed: #UIManager) default perform: #confirm: with: aString ]
|
|
287 |
ifFalse: [
|
|
288 |
"throw warning and answer true, if no way to announce"
|
|
289 |
Warning signal: aString.
|
|
290 |
true ]
|
|
291 |
! !
|
|
292 |
|
|
293 |
!MetacelloPlatform methodsFor:'utilities'!
|
|
294 |
|
|
295 |
authorName
|
|
296 |
|
|
297 |
Smalltalk at: #Author ifPresent: [:cl | ^cl perform: #initials ].
|
|
298 |
^'no developer initials'
|
|
299 |
!
|
|
300 |
|
|
301 |
authorName: aString
|
|
302 |
"Primarily used for testing"
|
|
303 |
|
|
304 |
self subclassResponsibility
|
|
305 |
!
|
|
306 |
|
|
307 |
timestamp
|
|
308 |
|
|
309 |
^DateAndTime now printString
|
|
310 |
! !
|
|
311 |
|
|
312 |
!MetacelloPlatform class methodsFor:'documentation'!
|
|
313 |
|
|
314 |
version_SVN
|
|
315 |
^ '$Id:: $'
|
|
316 |
! !
|
|
317 |
|
|
318 |
MetacelloPlatform initialize!
|