[squeak-dev] The Inbox: Metacello-MC-ct.740.mcz
commits at source.squeak.org
commits at source.squeak.org
Thu Jul 14 14:14:30 UTC 2022
A new version of Metacello-MC was added to project The Inbox:
http://source.squeak.org/inbox/Metacello-MC-ct.740.mcz
==================== Summary ====================
Name: Metacello-MC-ct.740
Author: ct
Time: 7 November 2020, 3:04:55.670274 pm
UUID: 29d84de4-0aaf-304b-99e4-b08db78c9072
Ancestors: Metacello-MC-tobe.739
Complements Metacello-Core-ct.834. In particular, this patch introduces MetacelloRepositorySpec >> #updateRepository: to overcome invalidations when fetching an existing repository with different credentials again.
==================== Snapshot ====================
SystemOrganization addCategory: #'Metacello-MC'!
SystemOrganization addCategory: #'Metacello-MC-Directives'!
SystemOrganization addCategory: #'Metacello-MC-Gofer'!
SystemOrganization addCategory: #'Metacello-MC-Loaders'!
SystemOrganization addCategory: #'Metacello-MC-Model'!
SystemOrganization addCategory: #'Metacello-MC-Specs'!
SystemOrganization addCategory: #'Metacello-MC-Validation'!
MetacelloSpecLoader subclass: #MetacelloCommonMCSpecLoader
instanceVariableNames: 'operator loaderPolicy disablePackageCache'
classVariableNames: 'RetryPackageResolution'
poolDictionaries: ''
category: 'Metacello-MC-Loaders'!
----- Method: MetacelloCommonMCSpecLoader class>>nameComponentsFrom: (in category 'utilities') -----
nameComponentsFrom: aVersionName
| ar |
ar := (aVersionName last isDigit and: [ (aVersionName indexOf: $.) > 0 ])ifFalse: [Array with: aVersionName with: '' with: 0 with: aVersionName with: self]
ifTrue: [ | vrsn str |
str := ((aVersionName copyAfterLast: $-) copyAfterLast: $.).
vrsn := str isEmpty
ifTrue: [0]
ifFalse: [str asInteger].
Array
with: (aVersionName copyUpToLast: $-) "base pkg name"
with: ((aVersionName copyAfterLast: $-) copyUpTo: $.) "user"
with: vrsn "version"
with: aVersionName
with: self ].
^ar!
----- Method: MetacelloCommonMCSpecLoader class>>retryPackageResolution (in category 'accessing') -----
retryPackageResolution
"if true,
errors during #retryingResolvePackageSpecReferences:gofer: are caught and
the resolution is retried 3 times. After the thrid time, a MetacelloPackageSpecResolutionError
is thrown
if false,
an error during #retryingResolvePackageSpecReferences:gofer: will be passed,
likely resulting in a walkback ... useful for debugging."
RetryPackageResolution ifNil: [ RetryPackageResolution := true ].
^ RetryPackageResolution!
----- Method: MetacelloCommonMCSpecLoader class>>retryPackageResolution: (in category 'accessing') -----
retryPackageResolution: aBool
RetryPackageResolution := aBool!
----- Method: MetacelloCommonMCSpecLoader>>ancestorsFor: (in category 'versionInfo') -----
ancestorsFor: packageSpec
| cacheKey vi |
cacheKey := packageSpec file.
^MetacelloPlatform current
stackCacheFor: #ancestors
at: cacheKey
doing: [ :cache |
vi := packageSpec ancestors.
cache at: cacheKey put: vi ].!
----- Method: MetacelloCommonMCSpecLoader>>currentVersionInfoFor: (in category 'versionInfo') -----
currentVersionInfoFor: packageSpec
| cacheKey vi |
cacheKey := packageSpec file.
^MetacelloPlatform current
stackCacheFor: #currentVersionInfo
at: cacheKey
doing: [ :cache |
vi := packageSpec currentVersionInfo.
cache at: cacheKey put: vi ].!
----- Method: MetacelloCommonMCSpecLoader>>doLoad (in category 'actions') -----
doLoad
self subclassResponsibility!
----- Method: MetacelloCommonMCSpecLoader>>doingLoads: (in category 'actions') -----
doingLoads: aBlock
"escape mechanism for recording and null loaders to skip doing loaderlike things"
aBlock value!
----- Method: MetacelloCommonMCSpecLoader>>ensureForDevelopment (in category 'testing') -----
ensureForDevelopment
^ true!
----- Method: MetacelloCommonMCSpecLoader>>ensureSpecLoader (in category 'accessing') -----
ensureSpecLoader
^ self!
----- Method: MetacelloCommonMCSpecLoader>>fetchingSpecLoader (in category 'accessing') -----
fetchingSpecLoader
^self!
----- Method: MetacelloCommonMCSpecLoader>>hasRepositoryOverrides (in category 'testing') -----
hasRepositoryOverrides
^self loaderPolicy hasRepositoryOverrides!
----- Method: MetacelloCommonMCSpecLoader>>ignoreImage (in category 'accessing') -----
ignoreImage
^self loaderPolicy ignoreImage!
----- Method: MetacelloCommonMCSpecLoader>>initialize (in category 'initialize-release') -----
initialize
self loaderPolicy!
----- Method: MetacelloCommonMCSpecLoader>>linearLoadPackageSpec:gofer: (in category 'actions') -----
linearLoadPackageSpec: packageSpec gofer: gofer
self subclassResponsibility!
----- Method: MetacelloCommonMCSpecLoader>>linearLoadPackageSpecs:repositories: (in category 'private') -----
linearLoadPackageSpecs: packageSpecs repositories: repositories
| gofer |
gofer := MetacelloGofer new.
repositories do: [:repo | gofer repository: repo ].
packageSpecs do: [:pkg | pkg loadUsing: self gofer: gofer ].!
----- Method: MetacelloCommonMCSpecLoader>>load (in category 'actions') -----
load
| repos |
repos := self repositoriesFrom: self spec repositorySpecs.
^ self loadType == #atomic
ifTrue: [self atomicLoadPackageSpecs: self spec packageSpecsInLoadOrder repositories: repos]
ifFalse: ["assume #linear"
self linearLoadPackageSpecs: self spec packageSpecsInLoadOrder repositories: repos ]!
----- Method: MetacelloCommonMCSpecLoader>>loadPackageDirective:gofer: (in category 'actions') -----
loadPackageDirective: aPackageLoadDirective gofer: aGofer
| packageSpec |
packageSpec := aPackageLoadDirective spec.
MetacelloPlatform current
do: [
| loadBlock goferLoad answers resolvedReference |
aGofer disablePackageCache. "for good luck:)"
resolvedReference := self resolvePackageSpec: packageSpec gofer: aGofer.
resolvedReference isNil
ifTrue: [
"Package version already loaded into image"
^ self ].
loadBlock := [
"mcLoader preLoad: packageSpec."
goferLoad := MetacelloGoferLoad on: aGofer.
goferLoad addResolved: resolvedReference.
goferLoad execute.
MetacelloPlatform current clearCurrentVersionCache "mcLoader postLoad: packageSpec" ].
(answers := packageSpec answers) notEmpty
ifTrue: [ loadBlock valueSupplyingMetacelloAnswers: answers ]
ifFalse: [ loadBlock value ].
resolvedReference workingCopy repositoryGroup
addRepository: aPackageLoadDirective repository.
Transcript
cr;
show:
'Loaded -> ' , resolvedReference name , ' --- '
, aPackageLoadDirective repository repositoryDescription
, ' --- ' , resolvedReference repository description ]
displaying: 'Loading ' , packageSpec file!
----- Method: MetacelloCommonMCSpecLoader>>loadPackageDirectives:gofer: (in category 'actions') -----
loadPackageDirectives: pkgLoads gofer: aGofer
MetacelloPlatform current
do: [
| goferLoad loadBlock answers |
goferLoad := MetacelloGoferLoad on: aGofer.
answers := OrderedCollection new.
pkgLoads
do: [ :packageLoadDirective |
| resolvedReference |
aGofer disablePackageCache. "for good luck:)"
(resolvedReference := self
resolvePackageSpec: packageLoadDirective spec
gofer: aGofer) ~~ nil
ifTrue: [
goferLoad addResolved: resolvedReference.
answers addAll: packageLoadDirective spec answers.
packageLoadDirective resolvedReference: resolvedReference ] ].
Transcript
cr;
show: 'Starting atomic load'.
loadBlock := [
"pkgLoads do: [:packageLoadDirective | mcLoader preLoad: packageLoadDirective spec ]."
goferLoad execute.
pkgLoads
do: [ :packageLoadDirective |
packageLoadDirective resolvedReference == nil
ifTrue: [
Transcript
cr;
tab;
show: 'Already Loaded -> ' , packageLoadDirective file ]
ifFalse: [
Transcript
cr;
tab;
show:
'Loaded -> ' , packageLoadDirective file , ' --- '
, packageLoadDirective repository repositoryDescription
, ' --- '
,
packageLoadDirective resolvedReference repository description.
packageLoadDirective resolvedReference workingCopy repositoryGroup
addRepository: packageLoadDirective repository ] ].
MetacelloPlatform current clearCurrentVersionCache "pkgLoads do: [:packageLoadDirective |
packageLoadDirective resolvedReference ~~ nil
ifTrue: [mcLoader postLoad: packageLoadDirective spec ]]" ].
answers notEmpty
ifTrue: [ loadBlock valueSupplyingMetacelloAnswers: answers ]
ifFalse: [ loadBlock value ].
Transcript
cr;
show: 'Finished atomic load' ]
displaying: 'Atomic Load...'!
----- Method: MetacelloCommonMCSpecLoader>>loaderPolicy (in category 'accessing') -----
loaderPolicy
loaderPolicy == nil ifTrue: [ loaderPolicy := MetacelloLoaderPolicy new ].
^loaderPolicy!
----- Method: MetacelloCommonMCSpecLoader>>loaderPolicy: (in category 'accessing') -----
loaderPolicy: anObject
loaderPolicy := anObject!
----- Method: MetacelloCommonMCSpecLoader>>loadingSpecLoader (in category 'accessing') -----
loadingSpecLoader
^self!
----- Method: MetacelloCommonMCSpecLoader>>nameComponentsFrom: (in category 'packages') -----
nameComponentsFrom: aVersionName
^self class nameComponentsFrom: aVersionName!
----- Method: MetacelloCommonMCSpecLoader>>operator (in category 'accessing') -----
operator
operator == nil ifTrue: [ ^#= ].
^operator!
----- Method: MetacelloCommonMCSpecLoader>>operator: (in category 'accessing') -----
operator: aSymbol
operator := aSymbol!
----- Method: MetacelloCommonMCSpecLoader>>postLoad: (in category 'doits') -----
postLoad: packageOrVersionSpec
"subclassResponsibility, but it gets called during an upgrade, so leave it as NOOP"!
----- Method: MetacelloCommonMCSpecLoader>>preLoad: (in category 'doits') -----
preLoad: packageOrVersionSpec
self subclassResponsibility!
----- Method: MetacelloCommonMCSpecLoader>>recordingSpecLoader (in category 'accessing') -----
recordingSpecLoader
^(MetacelloNullRecordingMCSpecLoader on: self spec)
shouldDisablePackageCache: self shouldDisablePackageCache;
loaderPolicy: self loaderPolicy copy;
yourself!
----- Method: MetacelloCommonMCSpecLoader>>repositoriesFrom: (in category 'repositories') -----
repositoriesFrom: aMetacelloMVRepositorySpecs
^self repositoriesFrom: aMetacelloMVRepositorySpecs ignoreOverrides: false!
----- Method: MetacelloCommonMCSpecLoader>>repositoriesFrom:ignoreOverrides: (in category 'repositories') -----
repositoriesFrom: aMetacelloMVRepositorySpecs ignoreOverrides: ignoreOverrides
| repositories repos |
(ignoreOverrides not and: [self hasRepositoryOverrides]) ifTrue: [ ^self loaderPolicy overrideRepositories ].
repositories := MCRepositoryGroup default repositories.
repos := OrderedCollection new.
aMetacelloMVRepositorySpecs do: [:aSpec | | description repo |
description := aSpec description.
(repo := repositories
detect: [ :rep | rep description = description ]
ifNone: [ aSpec createRepository ]) ~~ nil
ifTrue: [ repos add: (aSpec updateRepository: repo) ]].
^repos!
----- Method: MetacelloCommonMCSpecLoader>>repositoryMap (in category 'accessing') -----
repositoryMap
^self loaderPolicy repositoryMap!
----- Method: MetacelloCommonMCSpecLoader>>resolvePackageSpec:gofer: (in category 'private') -----
resolvePackageSpec: packageSpec gofer: gofer
| references resolvedReference mcVersion loadedVersionInfos |
references := self
retryingResolvePackageSpecReferences: packageSpec
gofer: gofer.
resolvedReference := references last asMetacelloCachingResolvedReference.
mcVersion := resolvedReference version.
(loadedVersionInfos := self ancestorsFor: packageSpec) ~~ nil
ifTrue: [
loadedVersionInfos
do: [ :info |
info name = mcVersion info name
ifTrue: [
| spc |
"package already loaded, don't load again"
spc := packageSpec copy.
spc file: info name.
(MetacelloIgnorePackageLoaded signal: spc)
ifFalse: [ ^ nil ] ] ] ].
^ resolvedReference!
----- Method: MetacelloCommonMCSpecLoader>>resolvePackageSpecReferences:gofer: (in category 'private') -----
resolvePackageSpecReferences: packageSpec gofer: gofer
| versionReference references localGofer |
localGofer := gofer.
self hasRepositoryOverrides not
ifTrue: [
packageSpec repositorySpecs notEmpty
ifTrue: [
localGofer := MetacelloGofer new.
(self repositoriesFrom: packageSpec repositorySpecs) do: [:repo | localGofer repository: repo ]]].
(packageSpec getFile == nil or: [ self shouldDisablePackageCache ])
ifTrue: [
"don't use package-cache when trying to get latest version"
localGofer disablePackageCache ].
versionReference := packageSpec goferLoaderReference.
references := versionReference resolveAllWith: localGofer.
localGofer enablePackageCache.
^references!
----- Method: MetacelloCommonMCSpecLoader>>retryingResolvePackageSpecReferences:gofer: (in category 'private') -----
retryingResolvePackageSpecReferences: packageSpec gofer: gofer
| retryCount references repositoryError |
retryCount := 0.
references := #().
[ references isEmpty and: [ retryCount < 3 ] ]
whileTrue: [
retryCount > 0
ifTrue: [
Transcript
cr;
show: '...RETRY->' , packageSpec file ].
references := [ self resolvePackageSpecReferences: packageSpec gofer: gofer ]
on: Error , GoferRepositoryError
do: [ :ex |
self class retryPackageResolution
ifFalse: [ ex pass ].
retryCount >= 2
ifTrue: [
(ex isKindOf: GoferRepositoryError)
ifTrue: [
"ignore repository errors at this point, in case an alternate repository is in the list "
Transcript
cr;
show: 'gofer repository error: ' , ex description printString , '...ignoring'.
repositoryError := ex.
ex resume: #() ]
ifFalse: [ ex pass ] ].
ex return: #() ].
retryCount := retryCount + 1 ].
references isEmpty
ifTrue: [
Transcript
cr;
show: '...FAILED->' , packageSpec file.
(MetacelloPackageSpecResolutionError new
packageSpec: packageSpec;
repositories: gofer repositories;
repositoryError: repositoryError;
yourself) signal ].
^ references!
----- Method: MetacelloCommonMCSpecLoader>>shouldDisablePackageCache (in category 'accessing') -----
shouldDisablePackageCache
disablePackageCache == nil ifTrue: [ disablePackageCache := false ].
^ disablePackageCache!
----- Method: MetacelloCommonMCSpecLoader>>shouldDisablePackageCache: (in category 'accessing') -----
shouldDisablePackageCache: anObject
disablePackageCache := anObject!
MetacelloCommonMCSpecLoader subclass: #MetacelloFetchingMCSpecLoader
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Loaders'!
MetacelloFetchingMCSpecLoader subclass: #MetacelloEnsureFetchingMCSpecLoader
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Loaders'!
----- Method: MetacelloEnsureFetchingMCSpecLoader>>ensureSpecLoader (in category 'accessing') -----
ensureSpecLoader
^ self!
----- Method: MetacelloEnsureFetchingMCSpecLoader>>scheduleFetchFor:cachedReference: (in category 'private') -----
scheduleFetchFor: packageSpec cachedReference: reference
"reference already in the cache during fetch ...schedule a load directive for reference, so ensured load will come from cache"
^ self
scheduleFetchFor: packageSpec
reference: reference
message:
'Fetched -> (cached) ' , reference name , ' --- '
, reference repository repositoryDescription , ' --- '
, reference repository description!
----- Method: MetacelloEnsureFetchingMCSpecLoader>>scheduleFetchFor:nearestReference: (in category 'private') -----
scheduleFetchFor: packageSpec nearestReference: reference
"latest version in repository already matches the cached reference...schedule a load directive for reference, so ensured load will come from cache"
^ self
scheduleFetchFor: packageSpec
reference: reference
message:
'Fetched -> (nearest) ' , reference name , ' --- '
, reference repository repositoryDescription , ' --- '
, reference repository description!
----- Method: MetacelloFetchingMCSpecLoader>>actionLabel (in category 'accessing') -----
actionLabel
^'Fetching '!
----- Method: MetacelloFetchingMCSpecLoader>>ancestorsFor: (in category 'versionInfo') -----
ancestorsFor: packageSpec
^self loadData
ancestorsFor: packageSpec
ifAbsent: [ super ancestorsFor: packageSpec ]!
----- Method: MetacelloFetchingMCSpecLoader>>atomicLoadPackageSpecs:repositories: (in category 'private') -----
atomicLoadPackageSpecs: packageSpecs repositories: repositories
self loaderPolicy
pushAtomicLoadDirectivesDuring: [ super linearLoadPackageSpecs: packageSpecs repositories: repositories ]
for: self!
----- Method: MetacelloFetchingMCSpecLoader>>cacheRepository (in category 'accessing') -----
cacheRepository
^self loaderPolicy cacheRepository!
----- Method: MetacelloFetchingMCSpecLoader>>currentVersionInfoFor: (in category 'versionInfo') -----
currentVersionInfoFor: packageSpec
^self loadData
currentVersionInfoFor: packageSpec
ifAbsent: [ super currentVersionInfoFor: packageSpec ]!
----- Method: MetacelloFetchingMCSpecLoader>>doLoad (in category 'actions') -----
doLoad
self loaderPolicy copy load!
----- Method: MetacelloFetchingMCSpecLoader>>ensureSpecLoader (in category 'accessing') -----
ensureSpecLoader
^ (MetacelloEnsureFetchingMCSpecLoader on: self spec)
shouldDisablePackageCache: self shouldDisablePackageCache;
loaderPolicy: self loaderPolicy; "explicitly share the loaderPolicy"
yourself!
----- Method: MetacelloFetchingMCSpecLoader>>ensuredMap (in category 'accessing') -----
ensuredMap
^self loaderPolicy ensuredMap!
----- Method: MetacelloFetchingMCSpecLoader>>explicitLoadPackageSpecs:repositories: (in category 'private') -----
explicitLoadPackageSpecs: packageSpecs repositories: repositories
| directive |
directive := self loaderPolicy
pushExplicitLoadDirectivesDuring: [ super linearLoadPackageSpecs: packageSpecs repositories: repositories ]
for: self.
directive explicitLoadWithPolicy: self loaderPolicy.!
----- Method: MetacelloFetchingMCSpecLoader>>linearLoadPackageSpec:gofer: (in category 'actions') -----
linearLoadPackageSpec: packageSpec gofer: gofer
MetacelloPlatform current
do: [
| references nearestReference cachedReference externalReference mcVersion loadedVersionInfos |
cachedReference := nil.
packageSpec
searchCacheRepositoryForPackage: [
"check to see if mcz file is already in cacheRepository"
cachedReference := self
resolvePackageSpec: packageSpec
cachedGofer: self loaderPolicy cacheGofer.
(cachedReference ~~ nil and: [ packageSpec getFile ~~ nil ])
ifTrue: [
cachedReference name = packageSpec file
ifTrue: [
"exact match between packageSpec file and cache"
^ self
scheduleFetchFor: packageSpec
cachedReference: cachedReference ] ] ].
references := self
retryingResolvePackageSpecReferences: packageSpec
gofer: gofer. "look up mcz file"
nearestReference := references last asMetacelloCachingResolvedReference.
(cachedReference ~~ nil
and: [ cachedReference name = nearestReference name ])
ifTrue: [
"latest reference in repository matches cachedReference ... "
^ self
scheduleFetchFor: packageSpec
nearestReference: nearestReference ].
(self ignoreImage not
and: [ (loadedVersionInfos := self ancestorsFor: packageSpec) ~~ nil ])
ifTrue: [
"If the mcz is already loaded into the image, no need to copy"
loadedVersionInfos
do: [ :info |
info name = nearestReference name
ifTrue: [
| spc |
spc := packageSpec copy.
spc file: info name.
(MetacelloIgnorePackageLoaded signal: spc)
ifFalse: [ ^ self ] ] ] ].
externalReference := (references
select: [ :ref | ref name = nearestReference name ]) first
asMetacelloCachingResolvedReference.
self repositoryMap
at: externalReference name
put: externalReference repository.
(self
resolveDependencies: externalReference
nearest: nearestReference
into: (OrderedCollection with: nearestReference))
do: [ :reference |
| pSpec l |
mcVersion := reference version.
(l := (GoferVersionReference name: reference name)
resolveAllWith: self loaderPolicy cacheGofer) isEmpty
ifTrue: [
self cacheRepository storeVersion: mcVersion.
reference == nearestReference
ifTrue: [ pSpec := packageSpec ]
ifFalse: [
pSpec := packageSpec project packageSpec.
pSpec name: mcVersion package name ].
self loadData
addVersion: mcVersion
versionInfo: mcVersion info
resolvedReference: reference
packageSpec: pSpec ] ].
self scheduleFetchFor: packageSpec externalReference: externalReference ]
displaying: 'Fetching ' , packageSpec file!
----- Method: MetacelloFetchingMCSpecLoader>>linearLoadPackageSpecs:repositories: (in category 'private') -----
linearLoadPackageSpecs: packageSpecs repositories: repositories
self loaderPolicy
pushLinearLoadDirectivesDuring: [ super linearLoadPackageSpecs: packageSpecs repositories: repositories ]
for: self!
----- Method: MetacelloFetchingMCSpecLoader>>loadData (in category 'accessing') -----
loadData
^self loaderPolicy loadData!
----- Method: MetacelloFetchingMCSpecLoader>>loadDirective (in category 'accessing') -----
loadDirective
^self loaderPolicy loadDirective!
----- Method: MetacelloFetchingMCSpecLoader>>loadingSpecLoader (in category 'accessing') -----
loadingSpecLoader
^(MetacelloLoadingMCSpecLoader on: self spec)
shouldDisablePackageCache: self shouldDisablePackageCache;
loaderPolicy: self loaderPolicy copy;
yourself!
----- Method: MetacelloFetchingMCSpecLoader>>postLoad: (in category 'doits') -----
postLoad: packageOrVersionSpec
(MetacelloDirective postLoadSpec: packageOrVersionSpec loader: self) addTo: self loadDirective!
----- Method: MetacelloFetchingMCSpecLoader>>preLoad: (in category 'doits') -----
preLoad: packageOrVersionSpec
(MetacelloDirective preLoadSpec: packageOrVersionSpec loader: self) addTo: self loadDirective!
----- Method: MetacelloFetchingMCSpecLoader>>printOn: (in category 'printing') -----
printOn: aStream
super printOn: aStream.
aStream nextPut: $(.
self loadDirective printOn: aStream.
aStream nextPut: $)!
----- Method: MetacelloFetchingMCSpecLoader>>resolveDependencies:nearest:into: (in category 'private') -----
resolveDependencies: aResolvedReference nearest: nearestReference into: aCollection
| block retryCount coll notDone |
self flag: 'Not used, but retained to avoid upgrade issues'.
block := [ :dependency |
| reference |
reference := MetacelloCachingGoferResolvedReference
name: dependency versionInfo name
repository: aResolvedReference repository.
coll add: reference.
Transcript
cr;
show:
'Fetched dependency -> ' , reference name , ' --- '
, reference repository repositoryDescription.
self resolveDependencies: reference nearest: reference into: coll ].
retryCount := 0.
notDone := true.
coll := OrderedCollection new.
[ notDone and: [ retryCount < 3 ] ]
whileTrue: [
retryCount > 0
ifTrue: [
Transcript
cr;
show: '...RETRY' ].
[
"ensure that all resolved references have cached their version while wrapped by error handler"
aCollection do: [ :each | each version ].
nearestReference version dependencies do: block.
notDone := false ]
on: Error
do: [ :ex |
retryCount := retryCount + 1.
retryCount >= 3
ifTrue: [ ex pass ].
coll := OrderedCollection new ] ].
aCollection addAll: coll.
^ aCollection!
----- Method: MetacelloFetchingMCSpecLoader>>resolvePackageSpec:cachedGofer: (in category 'private') -----
resolvePackageSpec: packageSpec cachedGofer: gofer
| versionReference references |
versionReference := packageSpec goferLoaderReference.
(references := versionReference resolveAllWith: gofer) isEmpty
ifTrue: [ ^nil ].
^references last asMetacelloCachingResolvedReference.!
----- Method: MetacelloFetchingMCSpecLoader>>scheduleFetchFor:cachedReference: (in category 'private') -----
scheduleFetchFor: packageSpec cachedReference: reference
"reference already in the cache during fetch ...no need to schedule fetch"
^ self!
----- Method: MetacelloFetchingMCSpecLoader>>scheduleFetchFor:externalReference: (in category 'private') -----
scheduleFetchFor: packageSpec externalReference: reference
^ self
scheduleFetchFor: packageSpec
reference: reference
message:
'Fetched -> ' , reference name , ' --- '
, reference repository repositoryDescription , ' --- '
, reference repository description!
----- Method: MetacelloFetchingMCSpecLoader>>scheduleFetchFor:nearestReference: (in category 'private') -----
scheduleFetchFor: packageSpec nearestReference: reference
"latest version in repository already matches the cached reference...no need to schedule fetch"
^ self!
----- Method: MetacelloFetchingMCSpecLoader>>scheduleFetchFor:reference:message: (in category 'private') -----
scheduleFetchFor: packageSpec reference: reference message: message
self loaderPolicy resetCacheGofer.
self preLoad: packageSpec.
(MetacelloDirective loadPackage: packageSpec externalReference: reference loader: self) addTo: self loadDirective.
self postLoad: packageSpec.
Transcript
cr;
show: message!
MetacelloFetchingMCSpecLoader subclass: #MetacelloNullRecordingMCSpecLoader
instanceVariableNames: 'afterLoads beforeLoads evalDoits'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Loaders'!
----- Method: MetacelloNullRecordingMCSpecLoader>>actionLabel (in category 'accessing') -----
actionLabel
^'Recording '!
----- Method: MetacelloNullRecordingMCSpecLoader>>afterLoads (in category 'accessing') -----
afterLoads
afterLoads == nil ifTrue: [ afterLoads := OrderedCollection new ].
^afterLoads!
----- Method: MetacelloNullRecordingMCSpecLoader>>beforeLoads (in category 'accessing') -----
beforeLoads
beforeLoads == nil ifTrue: [ beforeLoads := OrderedCollection new ].
^beforeLoads!
----- Method: MetacelloNullRecordingMCSpecLoader>>currentVersionInfoFor: (in category 'versionInfo') -----
currentVersionInfoFor: packageSpec
^self loadData
currentVersionInfoFor: packageSpec
ifAbsent: [ nil ]!
----- Method: MetacelloNullRecordingMCSpecLoader>>doingLoads: (in category 'actions') -----
doingLoads: aBlock
"escape mechanism for recording and null loaders to skip doing loaderlike things"!
----- Method: MetacelloNullRecordingMCSpecLoader>>ensureForDevelopment (in category 'testing') -----
ensureForDevelopment
^false!
----- Method: MetacelloNullRecordingMCSpecLoader>>evalDoits (in category 'accessing') -----
evalDoits
evalDoits == nil ifTrue: [ evalDoits := false ].
^evalDoits!
----- Method: MetacelloNullRecordingMCSpecLoader>>evalDoits: (in category 'accessing') -----
evalDoits: aBool
evalDoits := aBool!
----- Method: MetacelloNullRecordingMCSpecLoader>>linearLoadPackageSpec:gofer: (in category 'actions') -----
linearLoadPackageSpec: packageSpec gofer: gofer
MetacelloPlatform current
do: [ | externalReference loadBlock answers fake |
externalReference := self resolveRecordingPackageSpecReference: packageSpec gofer: gofer.
loadBlock := [
self preLoad: packageSpec.
(MetacelloDirective
loadPackage: packageSpec
externalReference: externalReference
loader: self) addTo: self loadDirective.
self postLoad: packageSpec ].
(answers := packageSpec answers) notEmpty
ifTrue: [ loadBlock valueSupplyingMetacelloAnswers: answers ]
ifFalse: [ loadBlock value ].
fake := packageSpec copy.
fake name: fake file.
self loadData
addVersion: fake
versionInfo: fake
resolvedReference: externalReference
packageSpec: packageSpec ]
displaying: 'Recording ', packageSpec file!
----- Method: MetacelloNullRecordingMCSpecLoader>>loadPackageDirective:gofer: (in category 'actions') -----
loadPackageDirective: aPackageLoadDirective gofer: aGofer
"Noop"!
----- Method: MetacelloNullRecordingMCSpecLoader>>loadPackageDirectives:gofer: (in category 'actions') -----
loadPackageDirectives: pkgLoads gofer: aGofer
"Noop"!
----- Method: MetacelloNullRecordingMCSpecLoader>>loadedPackages (in category 'accessing') -----
loadedPackages
| packages |
packages := OrderedCollection new.
self loadDirective packageDirectivesDo: [:directive | packages add: directive file ].
^packages!
----- Method: MetacelloNullRecordingMCSpecLoader>>loadedRepositories (in category 'accessing') -----
loadedRepositories
| repos |
repos := OrderedCollection new.
self repositoryMap values collect: [:coll | repos addAll: coll ].
^repos!
----- Method: MetacelloNullRecordingMCSpecLoader>>loadingSpecLoader (in category 'accessing') -----
loadingSpecLoader
^self!
----- Method: MetacelloNullRecordingMCSpecLoader>>packages (in category 'accessing') -----
packages
| packages |
packages := OrderedCollection new.
self loadDirective packageDirectivesDo: [:directive | packages add: directive spec ].
^packages!
----- Method: MetacelloNullRecordingMCSpecLoader>>postLoad: (in category 'doits') -----
postLoad: packageOrVersionSpec
self evalDoits ifFalse: [ ^self ].
packageOrVersionSpec postLoadDoItBlock ~~ nil
ifTrue: [ self afterLoads add: packageOrVersionSpec printString, ' load' ].
super postLoad: packageOrVersionSpec!
----- Method: MetacelloNullRecordingMCSpecLoader>>preLoad: (in category 'doits') -----
preLoad: packageOrVersionSpec
self evalDoits ifFalse: [ ^self ].
packageOrVersionSpec preLoadDoItBlock ~~ nil
ifTrue: [ self beforeLoads add: packageOrVersionSpec printString, ' load' ].
super preLoad: packageOrVersionSpec!
----- Method: MetacelloNullRecordingMCSpecLoader>>recordingSpecLoader (in category 'accessing') -----
recordingSpecLoader
^self!
----- Method: MetacelloNullRecordingMCSpecLoader>>resolvePackageSpecReferences:gofer: (in category 'private') -----
resolvePackageSpecReferences: packageSpec gofer: gofer
| versionReference references localGofer |
localGofer := gofer.
self hasRepositoryOverrides not
ifTrue: [
packageSpec repositorySpecs notEmpty
ifTrue: [
localGofer := MetacelloGofer new.
(self repositoriesFrom: packageSpec repositorySpecs) do: [:repo | localGofer repository: repo ]]].
(packageSpec getFile == nil or: [ self shouldDisablePackageCache ])
ifTrue: [
"don't use package-cache when trying to get latest version"
localGofer disablePackageCache ].
versionReference := packageSpec goferLoaderReference.
references := versionReference resolveAllWith: localGofer.
localGofer enablePackageCache.
^references!
----- Method: MetacelloNullRecordingMCSpecLoader>>resolveRecordingPackageSpecReference:gofer: (in category 'private') -----
resolveRecordingPackageSpecReference: packageSpec gofer: gofer
| externalPackageReference |
externalPackageReference := packageSpec file == nil
ifTrue: [ GoferPackageReference name: packageSpec name ]
ifFalse: [ GoferResolvedReference name: packageSpec file repository: nil ].
packageSpec repositorySpecs isEmpty
ifTrue: [
self repositoryMap
at: externalPackageReference packageName
put:
(gofer repositories
reject: [ :repo | repo = MetacelloPlatform current defaultPackageCache ]) ]
ifFalse: [
self repositoryMap
at: externalPackageReference packageName
put:
(packageSpec repositorySpecs collect: [ :repoSpec | repoSpec createRepository ]) ].
^ externalPackageReference!
MetacelloCommonMCSpecLoader subclass: #MetacelloLoadingMCSpecLoader
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Loaders'!
----- Method: MetacelloLoadingMCSpecLoader>>actionLabel (in category 'accessing') -----
actionLabel
^'Loading '!
----- Method: MetacelloLoadingMCSpecLoader>>copySpec:from:to: (in category 'development support') -----
copySpec: pkgSpec from: repositorySpecs to: repository
| gofer |
gofer := MetacelloGofer new.
(self repositoriesFrom: repositorySpecs) do: [:repo | gofer repository: repo ].
^self copySpec: pkgSpec with: gofer to: repository!
----- Method: MetacelloLoadingMCSpecLoader>>copySpec:with:to: (in category 'development support') -----
copySpec: pkgSpec with: gofer to: aRepository
| repository resolvedReference |
[resolvedReference := pkgSpec goferLoaderReference resolveWith: gofer]
on: Error
do: [:ignored | ^nil ].
repository := MCRepositoryGroup default repositories
detect: [ :each | each = aRepository ]
ifNone: [ aRepository ].
repository storeVersion: resolvedReference version.
^resolvedReference repository!
----- Method: MetacelloLoadingMCSpecLoader>>doLoad (in category 'actions') -----
doLoad
"NOOP"!
----- Method: MetacelloLoadingMCSpecLoader>>fetchingSpecLoader (in category 'accessing') -----
fetchingSpecLoader
^(MetacelloFetchingMCSpecLoader on: self spec)
shouldDisablePackageCache: self shouldDisablePackageCache;
loaderPolicy: self loaderPolicy copy;
yourself!
----- Method: MetacelloLoadingMCSpecLoader>>goferCommitBranchPackage:using:commitMessage: (in category 'development support') -----
goferCommitBranchPackage: branchName using: repositorySpecs commitMessage: commitMessage
| gofer repoSpecs wc |
repoSpecs := self spec repositorySpecs notEmpty
ifTrue: [ self spec repositorySpecs ]
ifFalse: [ repositorySpecs ].
gofer := MetacelloGofer new.
gofer disablePackageCache.
wc := self spec workingCopy.
repositorySpecs
do: [ :repoSpec |
| repo |
repo := repoSpec createRepository.
(wc possiblyNewerVersionsIn: repo) notEmpty
ifTrue: [
self
notify:
'There are possibly newer versions of the package ' , self spec name printString , ' in the repository '
, repo description printString
, '. Cancel and manually merge if you want to pick up the changes from the later version.' ].
gofer repository: repo ].
gofer package: self spec name.
[ gofer interactiveCommit ]
on: MCVersionNameAndMessageRequest
do: [ :ex |
| ref |
ref := GoferVersionReference name: ex suggestedName.
ex
resume:
{(ref packageName , '.' , branchName , '-' , ref author , '.' , ref versionNumber printString).
commitMessage} ].
^ true!
----- Method: MetacelloLoadingMCSpecLoader>>goferCommitPackageUsing:commitMessage: (in category 'development support') -----
goferCommitPackageUsing: repositorySpecs commitMessage: commitMessage
| gofer repoSpecs wc |
repoSpecs := self spec repositorySpecs notEmpty
ifTrue: [ self spec repositorySpecs ]
ifFalse: [ repositorySpecs ].
gofer := MetacelloGofer new.
gofer disablePackageCache.
wc := self spec workingCopy.
repositorySpecs do: [:repoSpec | | repo |
repo := repoSpec createRepository.
(wc possiblyNewerVersionsIn: repo) notEmpty
ifTrue: [ self notify: 'There are possibly newer versions of the package ', self spec name printString, ' in the repository ', repo description printString, '. Cancel and manually merge if you want to pick up the changes from the later version.' ].
gofer repository: repo ].
gofer package: self spec name.
gofer commit: commitMessage.
^true!
----- Method: MetacelloLoadingMCSpecLoader>>latestPackage:fromRepository: (in category 'packages') -----
latestPackage: aString fromRepository: repositorySpecs
| gofer |
gofer := MetacelloGofer new.
gofer disablePackageCache.
(self repositoriesFrom: repositorySpecs) do: [:repo | gofer repository: repo ].
^([(GoferPackageReference name: aString) resolveWith: gofer]
on: Error
do: [:ignored | ^ nil ]) name!
----- Method: MetacelloLoadingMCSpecLoader>>linearLoadPackageSpec:gofer: (in category 'private') -----
linearLoadPackageSpec: packageSpec gofer: gofer
MetacelloPlatform current
do: [
| loadBlock goferLoad answers resolvedReference repo |
resolvedReference := self resolvePackageSpec: packageSpec gofer: gofer.
resolvedReference isNil
ifTrue: [
"Package version already loaded into image"
^ self ].
loadBlock := [
self preLoad: packageSpec.
goferLoad := MetacelloGoferLoad on: MetacelloGofer new.
goferLoad addResolved: resolvedReference.
goferLoad execute.
MetacelloPlatform current clearCurrentVersionCache.
self postLoad: packageSpec ].
(answers := packageSpec answers) notEmpty
ifTrue: [ loadBlock valueSupplyingMetacelloAnswers: answers ]
ifFalse: [ loadBlock value ].
repo := resolvedReference repository.
self hasRepositoryOverrides
ifTrue: [
repo := self loaderPolicy repositoryMap
at: resolvedReference name
ifAbsent: [ resolvedReference repository ].
resolvedReference workingCopy repositoryGroup addRepository: repo ]
ifFalse: [
resolvedReference workingCopy repositoryGroup
addRepository: resolvedReference repository ].
Transcript
cr;
show:
'Loaded -> ' , resolvedReference name , ' --- ' , repo repositoryDescription
, ' --- ' , resolvedReference repository description ]
displaying: 'Loading ' , packageSpec file!
----- Method: MetacelloLoadingMCSpecLoader>>packagesNeedSavingUsing:into: (in category 'development support') -----
packagesNeedSavingUsing: repositorySpecs into: aCollection
| wc repoSpecs repo |
(wc := self spec workingCopy) == nil ifTrue: [ ^self ].
(wc ancestry ancestors notEmpty and: [ wc modified not])
ifTrue: [ ^self ].
repoSpecs := self spec repositorySpecs notEmpty
ifTrue: [ self spec repositorySpecs ]
ifFalse: [ repositorySpecs ].
repo := (self spec getFile == nil or: [ wc ancestry ancestors isEmpty ])
ifTrue: [ (self repositoriesFrom: repoSpecs ignoreOverrides: true) first ]
ifFalse: [
([ self resolveSpec: self spec from: repoSpecs ]
on: Error
do: [:ignored | ^self ]) repository ].
aCollection add: self spec -> repo!
----- Method: MetacelloLoadingMCSpecLoader>>postLoad: (in category 'doits') -----
postLoad: packageOrVersionSpec
| block |
(block := packageOrVersionSpec postLoadDoItBlock) ~~ nil
ifTrue: [ block valueWithPossibleArgs: { self. packageOrVersionSpec. } ]!
----- Method: MetacelloLoadingMCSpecLoader>>preLoad: (in category 'doits') -----
preLoad: packageOrVersionSpec
| block |
(block := packageOrVersionSpec preLoadDoItBlock) ~~ nil
ifTrue: [ block valueWithPossibleArgs: { self. packageOrVersionSpec. } ]!
----- Method: MetacelloLoadingMCSpecLoader>>repositoryFor:from: (in category 'development support') -----
repositoryFor: pkgSpec from: repositorySpecs
^([self resolveSpec: pkgSpec from: repositorySpecs]
on: Error
do: [:ignored | ^nil ]) repository!
----- Method: MetacelloLoadingMCSpecLoader>>repositoryFor:with: (in category 'development support') -----
repositoryFor: pkgSpec with: gofer
^([self resolveSpec: pkgSpec with: gofer]
on: Error
do: [:ignored | ^nil ]) repository!
----- Method: MetacelloLoadingMCSpecLoader>>resolveSpec:from: (in category 'development support') -----
resolveSpec: pkgSpec from: repositorySpecs
| gofer |
gofer := MetacelloGofer new.
gofer disablePackageCache.
(self repositoriesFrom: repositorySpecs ignoreOverrides: true)
do: [:repo | gofer repository: repo ].
^self resolveSpec: pkgSpec with: gofer!
----- Method: MetacelloLoadingMCSpecLoader>>resolveSpec:with: (in category 'development support') -----
resolveSpec: pkgSpec with: gofer
^pkgSpec goferLoaderReference resolveWith: gofer!
----- Method: MetacelloLoadingMCSpecLoader>>savePackageUsing: (in category 'development support') -----
savePackageUsing: repositorySpecs
| wc repo repoSpecs newVersion |
(wc := self spec workingCopy) == nil ifTrue: [ ^false ].
(wc ancestry ancestors notEmpty and: [ wc modified not])
ifTrue: [ ^false ].
repoSpecs := self spec repositorySpecs notEmpty
ifTrue: [ self spec repositorySpecs ]
ifFalse: [ repositorySpecs ].
(self spec getFile == nil or: [ wc ancestry ancestors isEmpty ])
ifTrue: [ repo := (self repositoriesFrom: repoSpecs ignoreOverrides: true) first ]
ifFalse: [
[ | newer |
repo := (self resolveSpec: self spec from: repoSpecs) repository.
newer := wc possiblyNewerVersionsIn: repo.
newer isEmpty not
ifTrue: [
(MetacelloPlatform current confirm: 'CAUTION!! These versions in the repository may be newer:',
String cr, newer printString, String cr,
'Do you really want to save this version?') ifFalse: [ ^false ]] ]
on: Error
do: [:ignored | ^false ] ].
(newVersion := MetacelloPlatform current newVersionForWorkingCopy: wc) == nil ifTrue: [ ^false ].
repo storeVersion: newVersion.
^true!
----- Method: MetacelloBaselineConstructor>>projectClass (in category '*metacello-mc-accessing') -----
projectClass
^ MetacelloMCBaselineProject!
----- Method: MetacelloMemberSpec>>addToMetacelloPackages: (in category '*metacello-mc') -----
addToMetacelloPackages: aMetacelloPackagesSpec
aMetacelloPackagesSpec addMember: self!
----- Method: MetacelloMemberSpec>>addToMetacelloRepositories: (in category '*metacello-mc') -----
addToMetacelloRepositories: aMetacelloRepositoriesSpec
aMetacelloRepositoriesSpec addMember: self!
----- Method: MetacelloMemberSpec>>mergeIntoMetacelloPackages: (in category '*metacello-mc') -----
mergeIntoMetacelloPackages: aMetacelloPackagesSpec
aMetacelloPackagesSpec addMember: self!
----- Method: MetacelloMemberSpec>>mergeIntoMetacelloRepositories: (in category '*metacello-mc') -----
mergeIntoMetacelloRepositories: aMetacelloRepositoriesSpec
aMetacelloRepositoriesSpec addMember: self!
----- Method: MetacelloMemberSpec>>removeFromMetacelloPackages: (in category '*metacello-mc') -----
removeFromMetacelloPackages: aMetacelloPackagesSpec
aMetacelloPackagesSpec addMember: self!
----- Method: MetacelloMemberSpec>>removeFromMetacelloRepositories: (in category '*metacello-mc') -----
removeFromMetacelloRepositories: aMetacelloRepositoriesSpec
aMetacelloRepositoriesSpec addMember: self!
----- Method: MCDictionaryRepository>>asRepositorySpecFor: (in category '*metacello-mc') -----
asRepositorySpecFor: aMetacelloMCProject
| desc |
desc := self description.
desc ifNil: [ desc := 'dictionary://Metacello_Dictionary' ].
^(aMetacelloMCProject repositorySpec)
description: desc;
type: 'dictionary';
yourself!
----- Method: MCDictionaryRepository>>cacheReferences (in category '*metacello-mc') -----
cacheReferences
^ false!
----- Method: MCDictionaryRepository>>versionInfoFromVersionNamed: (in category '*metacello-mc') -----
versionInfoFromVersionNamed: aString
| versions |
versions := self dictionary values select: [:version | version info name beginsWith: aString ].
versions isEmpty ifTrue: [ ^ nil ].
versions := versions asSortedCollection: [ :a :b |
([ (a info name copyAfterLast: $.) asNumber ] on: Error do: [:ex | ex return: 0 ]) <=
([ (b info name copyAfterLast: $.) asNumber ] on: Error do: [:ex | ex return: 0 ]) ].
^ versions last info!
----- Method: String>>addToMetacelloRepositories: (in category '*metacello-mc') -----
addToMetacelloRepositories: aMetacelloRepositoriesSpec
| spec |
spec :=
(aMetacelloRepositoriesSpec project repositorySpec)
description: self;
yourself.
aMetacelloRepositoriesSpec addMember:
(aMetacelloRepositoriesSpec addMember
name: spec name;
spec: spec;
yourself)!
----- Method: String>>fetchRequiredForMetacelloMCVersion: (in category '*metacello-mc') -----
fetchRequiredForMetacelloMCVersion: aMetacelloMCVersion
^aMetacelloMCVersion doFetchRequiredFromArray: (Array with: self).!
----- Method: String>>loadRequiredForMetacelloMCVersion: (in category '*metacello-mc') -----
loadRequiredForMetacelloMCVersion: aMetacelloMCVersion
^aMetacelloMCVersion doLoadRequiredFromArray: (Array with: self).!
----- Method: String>>mergeIntoMetacelloRepositories: (in category '*metacello-mc') -----
mergeIntoMetacelloRepositories: aMetacelloRepositoriesSpec
| spec |
spec :=
(aMetacelloRepositoriesSpec project repositorySpec)
description: self;
yourself.
aMetacelloRepositoriesSpec addMember:
(aMetacelloRepositoriesSpec mergeMember
name: spec name;
spec: spec;
yourself)!
----- Method: String>>packageFileSpecFor: (in category '*metacello-mc') -----
packageFileSpecFor: aMetacelloPackagesSpec
^(aMetacelloPackagesSpec project packageSpec)
file: self;
yourself!
----- Method: String>>recordRequiredForMetacelloMCVersion: (in category '*metacello-mc') -----
recordRequiredForMetacelloMCVersion: aMetacelloMCVersion
^aMetacelloMCVersion doRecordRequiredFromArray: (Array with: self).!
----- Method: String>>removeFromMetacelloRepositories: (in category '*metacello-mc') -----
removeFromMetacelloRepositories: aMetacelloRepositoriesSpec
aMetacelloRepositoriesSpec addMember:
(aMetacelloRepositoriesSpec removeMember
name: self;
yourself)!
----- Method: String>>resolvePackageSpecsNamedForMetacelloMCVersion:visited:ifAbsent: (in category '*metacello-mc') -----
resolvePackageSpecsNamedForMetacelloMCVersion: aMetacelloMCVersion visited: visited ifAbsent: aBlock
^ aMetacelloMCVersion
allPackagesForSpecs: {(aMetacelloMCVersion packageNamed: self ifAbsent: aBlock)}
visited: visited!
----- Method: String>>setLoadsInMetacelloProject: (in category '*metacello-mc') -----
setLoadsInMetacelloProject: aMetacelloPackageSpec
aMetacelloPackageSpec setLoads: { self }.
!
----- Method: GoferPackageReference>>metacelloPackageNameWithBranch (in category '*metacello-mc') -----
metacelloPackageNameWithBranch
"answer array with package name and package name with branch name .. no branch name"
^ {(self packageName).
(self packageName)}!
GoferPackageReference subclass: #MetacelloGoferPackage
instanceVariableNames: 'packageFilename version workingCopy'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Gofer'!
----- Method: MetacelloGoferPackage class>>name:packageFilename: (in category 'instance creation') -----
name: aString packageFilename: packageFilename
^ self basicNew initializeName: aString packageFilename: packageFilename!
----- Method: MetacelloGoferPackage class>>packageFileName:matchesPackageName: (in category 'package name matching') -----
packageFileName: pkgFileName matchesPackageName: wcPkgName
^ (pkgFileName beginsWith: wcPkgName)
ifTrue: [
pkgFileName size = wcPkgName size
or: [
(pkgFileName at: wcPkgName size + 1) = $-
or: [
(pkgFileName at: wcPkgName size + 1) = $.
or: [ (pkgFileName at: wcPkgName size + 1) isDigit ] ] ] ]
ifFalse: [
pkgFileName size >= wcPkgName size
ifTrue: [ ^ false ].
(wcPkgName beginsWith: pkgFileName)
ifFalse: [ ^ false ].
^ (wcPkgName at: pkgFileName size + 1) = $. ]!
----- Method: MetacelloGoferPackage>>ancestors (in category 'querying') -----
ancestors
| wc |
(wc := self workingCopy) ~~ nil
ifTrue: [
wc ancestry ancestors isEmpty not
ifTrue: [ ^wc ancestry ancestors ]].
^nil!
----- Method: MetacelloGoferPackage>>currentVersionInfo (in category 'querying') -----
currentVersionInfo
| wc |
(wc := self workingCopy) ~~ nil
ifTrue: [
wc ancestry ancestors isEmpty not
ifTrue: [ ^wc ancestry ancestors first ]].
^nil!
----- Method: MetacelloGoferPackage>>findWorkingCopy (in category 'private') -----
findWorkingCopy
"Answer a working copy, or nil if the package is not loaded."
| wcs |
wcs := MCWorkingCopy allManagers select: [ :each | self matchesWorkingCopy: each ].
wcs isEmpty ifTrue: [ ^nil ].
^wcs detectMax: [:ea | ea package name size ]!
----- Method: MetacelloGoferPackage>>initializeName:packageFilename: (in category 'initialization') -----
initializeName: aString packageFilename: packagefilename
name := aString.
packageFilename := packagefilename!
----- Method: MetacelloGoferPackage>>matches: (in category 'private') -----
matches: aLoadableReference
| pFilename |
((pFilename := self packageFilename) == nil
or: [ self name = self packageFilename ])
ifTrue: [ ^ super matches: aLoadableReference ].
aLoadableReference name = pFilename
ifTrue: [ ^ true ].
(aLoadableReference name beginsWith: pFilename)
ifFalse: [ ^ false ].
^ aLoadableReference matchesMetacelloGoferPackage: self!
----- Method: MetacelloGoferPackage>>matchesMetacelloGoferPackage: (in category 'private') -----
matchesMetacelloGoferPackage: aMetacelloGoferPackage
self
error:
'Should not be matching a MetacelloGoferPackage with another MetacelloGoferPackage'!
----- Method: MetacelloGoferPackage>>matchesWorkingCopy: (in category 'private') -----
matchesWorkingCopy: aWorkingCopy
"check that the working copy package name matches the package file name and that the first ancestor's package file name
matches the packageName"
| pFilename |
(pFilename := self packageFilename) == nil ifTrue: [ ^self error: 'cannot match working copy' ].
(self class
packageFileName: pFilename
matchesPackageName: aWorkingCopy package name)
ifTrue: [
aWorkingCopy ancestry ancestors isEmpty ifTrue: [ ^true ].
^self class
packageFileName: aWorkingCopy ancestry ancestors first name
matchesPackageName: self packageName ].
^false!
----- Method: MetacelloGoferPackage>>packageFilename (in category 'accessing') -----
packageFilename
^packageFilename!
----- Method: MetacelloGoferPackage>>workingCopy (in category 'accessing') -----
workingCopy
workingCopy == nil ifTrue: [ workingCopy := self findWorkingCopy ].
^workingCopy!
----- Method: MCFtpRepository>>username: (in category '*metacello-mc') -----
username: aString
"For compatibility with MetacelloRepositorySpec"
^ self user: aString!
----- Method: MCDirectoryRepository>>asRepositorySpecFor: (in category '*metacello-mc') -----
asRepositorySpecFor: aMetacelloMCProject
""
^ directory asRepositorySpecFor: aMetacelloMCProject!
----- Method: MCDirectoryRepository>>cacheReferences (in category '*metacello-mc') -----
cacheReferences
^ false!
GoferCommit subclass: #MetacelloGoferCommit
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Gofer'!
----- Method: MetacelloGoferCommit>>execute: (in category 'running') -----
execute: aWorkingCopy
| version |
version := MetacelloPlatform current newVersionForWorkingCopy: aWorkingCopy.
self gofer repositories
do: [ :repository | repository storeVersion: version ]!
----- Method: MetacelloGroupSpec>>loadUsing:gofer: (in category '*metacello-mc') -----
loadUsing: aLoader gofer: gofer
"noop"!
----- Method: MetacelloGroupSpec>>resolveToLoadableSpec (in category '*metacello-mc') -----
resolveToLoadableSpec
^nil!
----- Method: MetacelloGroupSpec>>resolveToPackagesIn:andProjects:into:visited: (in category '*metacello-mc') -----
resolveToPackagesIn: aVersionSpec andProjects: andProjectsBool into: packages visited: visited
visited
visit: self
doing: [ :aSpec |
| map |
map := aVersionSpec packages map.
aSpec includes
do: [ :pkgName |
(aVersionSpec packageNamed: pkgName forMap: map ifAbsent: [ ])
projectDo: [ :prj |
andProjectsBool
ifTrue: [ packages at: prj name put: prj ] ]
packageDo: [ :pkg | packages at: pkg name put: pkg ]
groupDo: [ :grp |
grp
resolveToPackagesIn: aVersionSpec
andProjects: andProjectsBool
into: packages
visited: visited ] ] ]!
----- Method: MetacelloGroupSpec>>resolveToPackagesIn:andProjects:visited: (in category '*metacello-mc') -----
resolveToPackagesIn: aVersionSpec andProjects: andProjectsBool visited: visited
| packages |
packages := Dictionary new.
self
resolveToPackagesIn: aVersionSpec
andProjects: andProjectsBool
into: packages
visited: visited.
^ packages values asOrderedCollection!
----- Method: MetacelloGroupSpec>>resolveToPackagesIn:into:visited: (in category '*metacello-mc') -----
resolveToPackagesIn: aVersionSpec into: packages visited: visited
self
resolveToPackagesIn: aVersionSpec
andProjects: false
into: packages
visited: visited!
----- Method: MetacelloGroupSpec>>resolveToPackagesIn:visited: (in category '*metacello-mc') -----
resolveToPackagesIn: aVersionSpec visited: visited
| packages |
packages := Dictionary new.
self
resolveToPackagesIn: aVersionSpec
andProjects: false
into: packages
visited: visited.
^ packages values asOrderedCollection!
----- Method: MetacelloAbstractVersionConstructor>>projectClass (in category '*metacello-mc-accessing') -----
projectClass
^ MetacelloMCProject!
----- Method: MetacelloAbstractPackageSpec>>file (in category '*metacello-mc-querying') -----
file
"MetacelloPackageSpec compatibility"
^nil!
----- Method: MetacelloAbstractPackageSpec>>forceUpdatePackageSpec:using: (in category '*metacello-mc') -----
forceUpdatePackageSpec: updatedSpecs using: anMCLoader
^self updatePackageSpec: updatedSpecs using: anMCLoader!
----- Method: MetacelloAbstractPackageSpec>>getFile (in category '*metacello-mc-querying') -----
getFile
"MetacelloPackageSpec compatibility"
^ nil!
----- Method: MetacelloAbstractPackageSpec>>isPackageLoaded (in category '*metacello-mc-querying') -----
isPackageLoaded
^false!
----- Method: MetacelloAbstractPackageSpec>>loadUsing:gofer: (in category '*metacello-mc') -----
loadUsing: aLoader gofer: gofer
^self subclassResponsibility!
----- Method: MetacelloAbstractPackageSpec>>packagesNeedSavingVisited:using:into: (in category '*metacello-mc') -----
packagesNeedSavingVisited: visitedProjects using: repos into: aCollection
"noop by default"!
----- Method: MetacelloAbstractPackageSpec>>repository (in category '*metacello-mc-querying') -----
repository
self deprecated: 'Use repositories or repositorySpecs'.
^ nil!
----- Method: MetacelloAbstractPackageSpec>>repositorySpecs (in category '*metacello-mc') -----
repositorySpecs
^#()!
----- Method: MetacelloAbstractPackageSpec>>resolveToAllPackagesIn:into:visited: (in category '*metacello-mc') -----
resolveToAllPackagesIn: aVersionSpec into: packages visited: visited
visited
visit: self
doing: [:spec |
self visitingWithPackages: packages.
(spec includes, spec requires) do: [:pkgName |
(aVersionSpec packageNamed: pkgName)
projectDo: [:prj |
(prj resolveToAllPackagesIn: aVersionSpec visited: visited) do: [:pkg |
packages at: pkg name put: pkg ]]
packageDo: [:pkg |
packages at: pkg name put: pkg.
(pkg resolveToAllPackagesIn: aVersionSpec visited: visited) do: [:rpkg |
packages at: rpkg name put: rpkg ] ]
groupDo: [:grp | grp resolveToAllPackagesIn: aVersionSpec into: packages visited: visited ]]]!
----- Method: MetacelloAbstractPackageSpec>>resolveToAllPackagesIn:visited: (in category '*metacello-mc') -----
resolveToAllPackagesIn: aVersionSpec visited: visited
| packages |
packages := Dictionary new.
self resolveToAllPackagesIn: aVersionSpec into: packages visited: visited.
^packages values asOrderedCollection!
----- Method: MetacelloAbstractPackageSpec>>resolveToLoadableSpec (in category '*metacello-mc') -----
resolveToLoadableSpec
^self!
----- Method: MetacelloAbstractPackageSpec>>resolveToPackagesIn:andProjects:visited: (in category '*metacello-mc') -----
resolveToPackagesIn: aVersionSpec andProjects: andProjectsBool visited: visited
^ self resolveToPackagesIn: aVersionSpec visited: visited!
----- Method: MetacelloAbstractPackageSpec>>resolveToPackagesIn:visited: (in category '*metacello-mc') -----
resolveToPackagesIn: aVersionSpec visited: visited
^self subclassResponsibility!
----- Method: MetacelloAbstractPackageSpec>>updateForSpawnMethod: (in category '*metacello-mc') -----
updateForSpawnMethod: sourceSpec
"This means that this spec was used in a baseline and will be used in a version .... drop all information that isn't useful"
answers := name := requires := includes := nil!
----- Method: MetacelloAbstractPackageSpec>>updatePackageRepositoriesFor: (in category '*metacello-mc') -----
updatePackageRepositoriesFor: aVersionSpec
"noop by default"
^true!
----- Method: MetacelloAbstractPackageSpec>>updatePackageSpec:using: (in category '*metacello-mc') -----
updatePackageSpec: updatedSpecs using: anMCLoader
"Add pkg copy to updatedSpecs if the file in current image is different from the receiver's file"!
----- Method: MetacelloAbstractPackageSpec>>version (in category '*metacello-mc-querying') -----
version
"MetacelloPackageSpec compatibility"
^nil!
----- Method: MetacelloAbstractPackageSpec>>visitingWithPackages: (in category '*metacello-mc') -----
visitingWithPackages: packages
"noop"!
MetacelloAbstractPackageSpec subclass: #MetacelloPackageSpec
instanceVariableNames: 'file repositories goferPackage preLoadDoIt postLoadDoIt'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
----- Method: MetacelloPackageSpec>>ancestors (in category 'gofer') -----
ancestors
^self goferPackage ancestors!
----- Method: MetacelloPackageSpec>>compareCurrentVersion:targetVersionStatus:using: (in category 'testing') -----
compareCurrentVersion: anOperator targetVersionStatus: statusIgnored using: anMCLoader
self
currentPackageLoaded: [:bool | ^bool ]
comparing: anOperator
notLoaded: [:ignored | ^false ]
using: anMCLoader!
----- Method: MetacelloPackageSpec>>compareRelativeCurrentVersion:targetVersionStatus:using: (in category 'testing') -----
compareRelativeCurrentVersion: anOperator targetVersionStatus: statusIgnored using: anMCLoader
^self compareCurrentVersion: anOperator targetVersionStatus: statusIgnored using: anMCLoader!
----- Method: MetacelloPackageSpec>>compareWorkingCopyNamed:using: (in category 'testing') -----
compareWorkingCopyNamed: wcName using: comarisonOperator
| fileRef wcRef |
fileRef := GoferResolvedReference name: self file.
wcRef := GoferResolvedReference name: wcName.
^ wcRef compare: fileRef using: comarisonOperator!
----- Method: MetacelloPackageSpec>>configMethodBodyOn:hasName:indent: (in category 'printing') -----
configMethodBodyOn: aStream hasName: hasName indent: indent
| hasFile hasRepositories hasPreLoadDoIt hasPostLoadDoIt hasRequiresOrIncludesOrAnswers |
hasFile := file ~~ nil.
hasRepositories := self repositorySpecs size > 0.
hasPreLoadDoIt := self getPreLoadDoIt ~~ nil.
hasPostLoadDoIt := self getPostLoadDoIt ~~ nil.
hasRequiresOrIncludesOrAnswers := (self requires isEmpty and: [ self includes isEmpty and: [self answers isEmpty ]]) not.
hasRequiresOrIncludesOrAnswers
ifTrue: [
self
configMethodBodyOn: aStream
hasName: hasName
cascading: hasFile | hasRepositories | hasPreLoadDoIt | hasPostLoadDoIt
indent: indent ].
self
configMethodOn: aStream
for: file
selector: 'file: '
cascading: hasName | hasRepositories | hasPreLoadDoIt | hasPostLoadDoIt | hasRequiresOrIncludesOrAnswers
cascade: hasRepositories | hasPreLoadDoIt | hasPostLoadDoIt
indent: indent.
hasRepositories
ifTrue: [
(self repositorySpecs size > 1)
ifTrue: [
hasName | hasFile | hasPreLoadDoIt | hasPostLoadDoIt | hasRequiresOrIncludesOrAnswers
ifTrue: [
aStream cr;
tab: indent. ].
aStream
nextPutAll: 'repositories: [';
cr;
tab: indent + 1;
nextPutAll: 'spec';
cr.
self repositories configMethodCascadeOn: aStream indent: indent + 1.
aStream nextPutAll: ' ]' ]
ifFalse: [
hasName | hasFile | hasPreLoadDoIt | hasPostLoadDoIt | hasRequiresOrIncludesOrAnswers
ifTrue: [ aStream cr; tab: indent ].
self repositories configMethodCascadeOn: aStream indent: indent ].
hasPreLoadDoIt | hasPostLoadDoIt ifTrue: [ aStream nextPut: $; ] ].
self
configMethodOn: aStream
for: self getPreLoadDoIt
selector: 'preLoadDoIt: '
cascading: hasName | hasFile | hasRepositories | hasPostLoadDoIt | hasRequiresOrIncludesOrAnswers
cascade: hasPostLoadDoIt
indent: indent.
self
configMethodOn: aStream
for: self getPostLoadDoIt
selector: 'postLoadDoIt: '
cascading: hasName | hasFile | hasRepositories | hasPreLoadDoIt | hasRequiresOrIncludesOrAnswers
cascade: false
indent: indent.
aStream nextPut: $.!
----- Method: MetacelloPackageSpec>>configMethodCascadeOn:member:last:indent: (in category 'printing') -----
configMethodCascadeOn: aStream member: aMember last: lastCascade indent: indent
aMember methodUpdateSelector == #remove:
ifTrue: [ aStream nextPutAll: 'removePackage: ', self name printString ]
ifFalse: [ self configShortCutMethodBodyOn: aStream member: aMember indent: indent ].
lastCascade
ifTrue: [ aStream nextPut: $. ]
ifFalse: [ aStream nextPut: $;; cr ]!
----- Method: MetacelloPackageSpec>>configMethodOn:indent: (in category 'printing') -----
configMethodOn: aStream indent: indent
| hasRepositories hasPreLoadDoIt hasPostLoadDoIt hasRequiresOrIncludesOrAnswers hasFile |
hasFile := file ~~ nil.
hasRepositories := self repositorySpecs size > 0.
hasPreLoadDoIt := self getPreLoadDoIt ~~ nil.
hasPostLoadDoIt := self getPostLoadDoIt ~~ nil.
hasRequiresOrIncludesOrAnswers := (self requires isEmpty and: [ self includes isEmpty and: [self answers isEmpty ]]) not.
aStream tab: indent; nextPutAll: 'spec '.
hasFile | hasRepositories | hasPreLoadDoIt | hasPostLoadDoIt | hasRequiresOrIncludesOrAnswers
ifTrue: [
aStream cr; tab: indent + 1; nextPutAll: 'name: ', self name printString; nextPut: $;.
self configMethodBodyOn: aStream hasName: true indent: indent + 1 ]
ifFalse: [
aStream nextPutAll: 'name: ', self name printString ]!
----- Method: MetacelloPackageSpec>>configShortCutMethodBodyOn:member:indent: (in category 'printing') -----
configShortCutMethodBodyOn: aStream member: aMember indent: indent
| hasFile hasRepositories hasPreLoadDoIt hasPostLoadDoIt hasRequiresOrIncludesOrAnswers |
hasFile := file ~~ nil.
hasRepositories := self repositorySpecs size > 0.
hasPreLoadDoIt := self getPreLoadDoIt ~~ nil.
hasPostLoadDoIt := self getPostLoadDoIt ~~ nil.
hasRequiresOrIncludesOrAnswers := (self requires isEmpty and: [ self includes isEmpty and: [self answers isEmpty ]]) not.
hasRepositories | hasPreLoadDoIt | hasPostLoadDoIt | hasRequiresOrIncludesOrAnswers
ifTrue: [
aStream
nextPutAll: 'package: ', self name printString, ' ';
nextPutAll: aMember methodUpdateSelector asString, ' ['; cr.
aStream tab: indent + 1; nextPutAll: 'spec '.
self configMethodBodyOn: aStream hasName: false indent: indent + 2.
aStream nextPutAll: ' ]'.
^self ].
aStream nextPutAll: 'package: ', self name printString.
hasFile
ifTrue: [ aStream nextPutAll: ' with: ', file printString ]!
----- Method: MetacelloPackageSpec>>copySpecTo: (in category 'development support') -----
copySpecTo: aRepositorySpec
"Copy current mcz file to the repository named in aRepositorySpec"
self loader copySpec: self from: self repositorySpecs to: aRepositorySpec createRepository!
----- Method: MetacelloPackageSpec>>currentPackageLoaded:comparing:notLoaded:using: (in category 'testing') -----
currentPackageLoaded: loadedBlock comparing: comarisonOperator notLoaded: notLoadedBlock using: anMCLoader
"Use currentVersionInfoFor: because it involves the loader and returns versionInfo for a planned load
(atomic loaders) or currently loaded package"
| wcName vis |
vis := anMCLoader ancestorsFor: self.
vis notNil
ifTrue: [
| fileRef wcRef |
self getFile == nil
ifTrue: [ ^ loadedBlock value: false ].
vis
do: [ :vi |
wcName := vi name.
fileRef := GoferVersionReference name: self file.
fileRef versionNumber = 0
ifTrue: [
"a shame that GoferVersionReference doesn't have better method for recognizing a missing verion number"
"fix for: https://github.com/dalehenrich/metacello-work/issues/185"
^ loadedBlock value: false ].
wcRef := GoferVersionReference name: wcName.
(wcRef compare: fileRef using: comarisonOperator)
ifTrue: [ ^ loadedBlock value: true ] ].
^ loadedBlock value: false ].
^ notLoadedBlock value: true!
----- Method: MetacelloPackageSpec>>currentPackageLoaded:notLoaded:using: (in category 'testing') -----
currentPackageLoaded: loadedBlock notLoaded: notLoadedBlock using: anMCLoader
"Use currentVersionInfoFor: because it involves the loader and returns versionInfo for a planned load
(atomic loaders) or currently loaded package"
| vis |
vis := anMCLoader ancestorsFor: self.
vis notNil
ifTrue: [
self getFile == nil
ifTrue: [ ^ loadedBlock value: #() value: self file ].
^ loadedBlock value: vis value: self file ].
^ notLoadedBlock value
!
----- Method: MetacelloPackageSpec>>currentVersionInfo (in category 'gofer') -----
currentVersionInfo
^self goferPackage currentVersionInfo!
----- Method: MetacelloPackageSpec>>ensureLoadUsing: (in category 'loading') -----
ensureLoadUsing: mcLoader
self explicitLoadUsing: mcLoader ensureSpecLoader!
----- Method: MetacelloPackageSpec>>ensureLoadedForDevelopmentUsing: (in category 'loading') -----
ensureLoadedForDevelopmentUsing: mcLoader
"noop"
^true!
----- Method: MetacelloPackageSpec>>explicitLoadUsing: (in category 'loading') -----
explicitLoadUsing: mcLoader
| wc fetchingSpecLoader |
((wc := self workingCopy) ~~ nil and: [ wc needsSaving ])
ifTrue: [
(MetacelloSkipDirtyPackageLoad signal: self)
ifTrue: [
Transcript cr; show: 'Skipping load of modified package: ', self file.
^self]
ifFalse: [Transcript cr; show: 'Load over modified package: ', self file] ].
"fetch and explicitly load it"
fetchingSpecLoader := mcLoader fetchingSpecLoader.
fetchingSpecLoader
explicitLoadPackageSpecs: (Array with: self)
repositories: (fetchingSpecLoader repositoriesFrom: self repositorySpecs).!
----- Method: MetacelloPackageSpec>>extractNameFromFile (in category 'private') -----
extractNameFromFile
file == nil ifTrue: [ ^nil ].
^(self loader nameComponentsFrom: self file) first!
----- Method: MetacelloPackageSpec>>fetch (in category 'loading') -----
fetch
self fetchUsing: self loader!
----- Method: MetacelloPackageSpec>>fetchPackage: (in category 'loading') -----
fetchPackage: aLoaderPolicy
self fetchUsing:
(self loader
loaderPolicy: aLoaderPolicy;
yourself)!
----- Method: MetacelloPackageSpec>>fetchUsing: (in category 'loading') -----
fetchUsing: mcLoader
| fetchingSpecLoader |
fetchingSpecLoader := mcLoader fetchingSpecLoader.
fetchingSpecLoader
linearLoadPackageSpecs: (Array with: self)
repositories: (fetchingSpecLoader repositoriesFrom: self repositorySpecs).!
----- Method: MetacelloPackageSpec>>file (in category 'querying') -----
file
file == nil ifTrue: [ ^self name ].
^file!
----- Method: MetacelloPackageSpec>>file: (in category 'accessing') -----
file: aString
file := aString!
----- Method: MetacelloPackageSpec>>file:constructor: (in category 'construction') -----
file: aString constructor: aVersionConstructor
aVersionConstructor fileForPackage: aString!
----- Method: MetacelloPackageSpec>>forceUpdatePackageSpec:using: (in category 'development support') -----
forceUpdatePackageSpec: updatedSpecs using: anMCLoader
self updatePackageSpec: updatedSpecs force: true using: anMCLoader!
----- Method: MetacelloPackageSpec>>getFile (in category 'accessing') -----
getFile
"raw access to iv"
^file!
----- Method: MetacelloPackageSpec>>getName (in category 'accessing') -----
getName
"raw access to iv"
^ name!
----- Method: MetacelloPackageSpec>>getPostLoadDoIt (in category 'querying') -----
getPostLoadDoIt
^postLoadDoIt!
----- Method: MetacelloPackageSpec>>getPreLoadDoIt (in category 'querying') -----
getPreLoadDoIt
^preLoadDoIt!
----- Method: MetacelloPackageSpec>>getRepositories (in category 'accessing') -----
getRepositories
"raw access to iv"
^ repositories!
----- Method: MetacelloPackageSpec>>goferBranchPackage:message: (in category 'development support') -----
goferBranchPackage: branchName message: commitMessage
"uses gofer to do commit ... non-interactive"
| latestFile pkgSpec |
(file notNil and: [ (self name, '.', branchName) = self file ])
ifTrue: [
latestFile := self loader latestPackage: self file fromRepository: self repositorySpecs.
pkgSpec := self copy.
latestFile ~~ nil
ifTrue: [
pkgSpec file: latestFile.
pkgSpec goferCommitPackage: commitMessage.
^ self ] ].
self loader goferCommitBranchPackage: branchName using: self repositorySpecs commitMessage: commitMessage!
----- Method: MetacelloPackageSpec>>goferCommitPackage: (in category 'development support') -----
goferCommitPackage: commitMessage
"uses gofer to do commit ... non-interactive"
| latestFile pkgSpec |
^(file notNil and: [ self name = self file ])
ifTrue: [
latestFile := self loader latestPackage: self name fromRepository: self repositorySpecs.
pkgSpec := self copy.
pkgSpec file: latestFile.
pkgSpec goferCommitPackage: commitMessage ]
ifFalse: [ self loader goferCommitPackageUsing: self repositorySpecs commitMessage: commitMessage ]!
----- Method: MetacelloPackageSpec>>goferLoaderReference (in category 'accessing') -----
goferLoaderReference
^file == nil
ifTrue: [ GoferPackageReference name: self name ]
ifFalse: [
"does Monticello-style #versionInfoFromVersionNamed: matching"
MetacelloGoferPackage name: self name packageFilename: self file ]!
----- Method: MetacelloPackageSpec>>goferPackage (in category 'accessing') -----
goferPackage
goferPackage == nil
ifTrue: [ goferPackage := MetacelloGoferPackage name: self name packageFilename: self file ].
^goferPackage!
----- Method: MetacelloPackageSpec>>hasRepository (in category 'testing') -----
hasRepository
^ self repositorySpecs notEmpty!
----- Method: MetacelloPackageSpec>>includes:constructor: (in category 'construction') -----
includes: anObject constructor: aVersionConstructor
aVersionConstructor includesForPackage: anObject!
----- Method: MetacelloPackageSpec>>includesForPackageOrdering (in category 'private') -----
includesForPackageOrdering
^ self includes!
----- Method: MetacelloPackageSpec>>info (in category 'accessing') -----
info
"test compatibility method"
^self!
----- Method: MetacelloPackageSpec>>isPackageLoaded (in category 'querying') -----
isPackageLoaded
^self isPackageLoaded: self loader!
----- Method: MetacelloPackageSpec>>isPackageLoaded: (in category 'querying') -----
isPackageLoaded: aLoader
^(self workingCopyNameFor: aLoader) ~~ nil!
----- Method: MetacelloPackageSpec>>load (in category 'loading') -----
load
self explicitLoadUsing: self loader!
----- Method: MetacelloPackageSpec>>loadUsing: (in category 'loading') -----
loadUsing: mcLoader
self loader doingLoads: [ self explicitLoadUsing: mcLoader ]!
----- Method: MetacelloPackageSpec>>loadUsing:gofer: (in category 'loading') -----
loadUsing: aLoader gofer: gofer
^aLoader linearLoadPackageSpec: self gofer: gofer!
----- Method: MetacelloPackageSpec>>mergeMap (in category 'merging') -----
mergeMap
| map |
map := super mergeMap.
map at: #file put: file.
map at: #repositories put: self repositories.
map at: #preLoadDoIt put: preLoadDoIt.
map at: #postLoadDoIt put: postLoadDoIt.
^map!
----- Method: MetacelloPackageSpec>>mergeSpec: (in category 'merging') -----
mergeSpec: anotherSpec
| newSpec map anotherRepositories |
newSpec := super mergeSpec: anotherSpec.
map := anotherSpec mergeMap.
(anotherRepositories := map at: #repositories) notEmpty
ifTrue: [
newSpec
repositories: (self repositories isEmpty
ifTrue: [ anotherRepositories ]
ifFalse: [ self repositories mergeSpec: anotherRepositories ]) ].
^newSpec
!
----- Method: MetacelloPackageSpec>>name (in category 'querying') -----
name
name == nil ifTrue: [ name := self extractNameFromFile ].
^name!
----- Method: MetacelloPackageSpec>>nonOverridable (in category 'merging') -----
nonOverridable
^super nonOverridable, #( repositories)!
----- Method: MetacelloPackageSpec>>packageSpecsInLoadOrder (in category 'loading') -----
packageSpecsInLoadOrder
^{ self. }!
----- Method: MetacelloPackageSpec>>packagesNeedSavingVisited:using:into: (in category 'development support') -----
packagesNeedSavingVisited: visitedProjects using: repos into: aCollection
^self loader packagesNeedSavingUsing: repos into: aCollection!
----- Method: MetacelloPackageSpec>>postCopy (in category 'copying') -----
postCopy
super postCopy.
goferPackage := nil.
repositories := repositories copy.!
----- Method: MetacelloPackageSpec>>postLoadDoIt (in category 'querying') -----
postLoadDoIt
^postLoadDoIt!
----- Method: MetacelloPackageSpec>>postLoadDoIt: (in category 'loading') -----
postLoadDoIt: anObject
anObject setPostLoadDoItInMetacelloSpec: self!
----- Method: MetacelloPackageSpec>>postLoadDoIt:constructor: (in category 'construction') -----
postLoadDoIt: aSymbol constructor: aVersionConstructor
aVersionConstructor postLoadDoItForPackage: aSymbol!
----- Method: MetacelloPackageSpec>>preLoadDoIt (in category 'querying') -----
preLoadDoIt
^preLoadDoIt!
----- Method: MetacelloPackageSpec>>preLoadDoIt: (in category 'accessing') -----
preLoadDoIt: anObject
anObject setPreLoadDoItInMetacelloSpec: self!
----- Method: MetacelloPackageSpec>>preLoadDoIt:constructor: (in category 'construction') -----
preLoadDoIt: aSymbol constructor: aVersionConstructor
aVersionConstructor preLoadDoItForPackage: aSymbol!
----- Method: MetacelloPackageSpec>>projectDo:packageDo:groupDo: (in category 'visiting') -----
projectDo: projectBlock packageDo: packageBlock groupDo: groupBlock
packageBlock value: self!
----- Method: MetacelloPackageSpec>>repositories (in category 'querying') -----
repositories
repositories == nil ifTrue: [ repositories := self project repositoriesSpec ].
^ repositories!
----- Method: MetacelloPackageSpec>>repositories: (in category 'querying') -----
repositories: anObject
repositories := anObject!
----- Method: MetacelloPackageSpec>>repositories:constructor: (in category 'construction') -----
repositories: aBlock constructor: aVersionConstructor
aVersionConstructor repositoriesForPackage: aBlock!
----- Method: MetacelloPackageSpec>>repository (in category 'querying') -----
repository
self deprecated: 'Use repositories or repositorySpecs'.
self repositorySpecs isEmpty
ifTrue: [ ^ nil ].
^ self repositorySpecs first!
----- Method: MetacelloPackageSpec>>repository: (in category 'accessing') -----
repository: aStringOrMetacelloRepositorySpec
self repositories repository: aStringOrMetacelloRepositorySpec!
----- Method: MetacelloPackageSpec>>repository:constructor: (in category 'construction') -----
repository: anObject constructor: aVersionConstructor
aVersionConstructor repositoryForPackage: anObject!
----- Method: MetacelloPackageSpec>>repository:username:password: (in category 'accessing') -----
repository: aString username: username password: password
self repositories repository: aString username: username password: password!
----- Method: MetacelloPackageSpec>>repository:username:password:constructor: (in category 'construction') -----
repository: aString username: username password: password constructor: aVersionConstructor
aVersionConstructor repositoryForPackage: aString username: username password: password!
----- Method: MetacelloPackageSpec>>repositoryDescriptions (in category 'loading') -----
repositoryDescriptions
^ self repositorySpecs collect: [ :repoSpec | repoSpec description ]!
----- Method: MetacelloPackageSpec>>repositorySpecs (in category 'loading') -----
repositorySpecs
^self repositories map values!
----- Method: MetacelloPackageSpec>>requires:constructor: (in category 'construction') -----
requires: anObject constructor: aVersionConstructor
aVersionConstructor requiresForPackage: anObject!
----- Method: MetacelloPackageSpec>>resolveToPackagesIn:visited: (in category 'private') -----
resolveToPackagesIn: aVersionSpec visited: visited
^{ self }!
----- Method: MetacelloPackageSpec>>savePackage (in category 'development support') -----
savePackage
"Interactive save ... prompted for commit message and package name unless MCVersionNameAndMessageRequest handled"
| latestFile pkgSpec |
^(file notNil and: [ self name = self file ])
ifTrue: [
latestFile := self loader latestPackage: self name fromRepository: self repositorySpecs.
pkgSpec := self copy.
pkgSpec file: latestFile.
pkgSpec savePackage ]
ifFalse: [ self loader savePackageUsing: self repositorySpecs ]!
----- Method: MetacelloPackageSpec>>searchCacheRepositoryForPackage: (in category 'fetching') -----
searchCacheRepositoryForPackage: searchBlock
"evaluate the <searchBlock> if you want to search for the package in a local package cache"
"for standard mcz repositories the answer is YES!!"
searchBlock value!
----- Method: MetacelloPackageSpec>>setPostLoadDoIt: (in category 'accessing') -----
setPostLoadDoIt: aSymbol
postLoadDoIt := aSymbol!
----- Method: MetacelloPackageSpec>>setPreLoadDoIt: (in category 'accessing') -----
setPreLoadDoIt: aSymbol
preLoadDoIt := aSymbol!
----- Method: MetacelloPackageSpec>>supplyingAnswers:constructor: (in category 'construction') -----
supplyingAnswers: anObject constructor: aVersionConstructor
aVersionConstructor supplyingAnswersForPackage: anObject!
----- Method: MetacelloPackageSpec>>updateForSpawnMethod: (in category 'development support') -----
updateForSpawnMethod: sourceSpec
"This means that this spec was used in a baseline and will be used in a version .... drop all information that isn't useful"
| nm fl |
nm := name.
fl := file.
fl == nil
ifTrue: [
"if only name has been set, then force the file to be non-nil, if any attribute besides file is set, then leave file nil"
{answers.
requires.
includes.
repositories.
preLoadDoIt.
postLoadDoIt} detect: [ :each | each ~~ nil ] ifNone: [ fl := name ] ].
super updateForSpawnMethod: sourceSpec.
file := repositories := goferPackage := preLoadDoIt := postLoadDoIt := nil.
name := nm.
file := fl.
^ file == nil!
----- Method: MetacelloPackageSpec>>updatePackageRepositories: (in category 'development support') -----
updatePackageRepositories: repositorySpecs
| resolvedPackageRef |
Transcript cr; show: ' Looking up version -> ', self file.
resolvedPackageRef := self loader resolveSpec: self from: repositorySpecs.
Transcript cr; show: 'Update repositoryGroup -> ', resolvedPackageRef name, ' ' , resolvedPackageRef repository description.
resolvedPackageRef version workingCopy repositoryGroup addRepository: resolvedPackageRef repository!
----- Method: MetacelloPackageSpec>>updatePackageRepositoriesFor: (in category 'development support') -----
updatePackageRepositoriesFor: aVersionSpec
"Don't update the repository unless the package is loaded in the image"
self workingCopy == nil ifTrue: [ ^self ].
self updatePackageRepositories: self repositorySpecs, aVersionSpec repositorySpecs.!
----- Method: MetacelloPackageSpec>>updatePackageSpec:force:using: (in category 'development support') -----
updatePackageSpec: updatedSpecs force: force using: anMCLoader
"Add pkg copy to updatedSpecs if the file in current image is different from the receiver's file"
| viName |
(force not and: [ self getFile == nil ])
ifTrue: [ ^ self ]. "no file explicitly specified in this spec"
(viName := self workingCopyNameFor: anMCLoader) == nil
ifTrue: [ ^ self ]. "no working copy"
viName ~= self file
ifTrue: [
| spec |
spec := self copy.
spec file: viName.
updatedSpecs at: spec name put: spec ]
ifFalse: [ updatedSpecs at: self name put: #uptodate ]!
----- Method: MetacelloPackageSpec>>updatePackageSpec:using: (in category 'development support') -----
updatePackageSpec: updatedSpecs using: anMCLoader
"Add pkg copy to updatedSpecs if the file in current image is different from the receiver's file"
self updatePackageSpec: updatedSpecs force: false using: anMCLoader!
----- Method: MetacelloPackageSpec>>visitingWithPackages: (in category 'visiting') -----
visitingWithPackages: packages
packages at: self name put: self!
----- Method: MetacelloPackageSpec>>workingCopy (in category 'gofer') -----
workingCopy
^self goferPackage workingCopy!
----- Method: MetacelloPackageSpec>>workingCopyName (in category 'gofer') -----
workingCopyName
| wc |
(wc := self workingCopy) == nil ifTrue: [ ^nil ].
wc ancestry ancestors isEmpty not
ifTrue: [ ^wc ancestry ancestors first name ].
^nil!
----- Method: MetacelloPackageSpec>>workingCopyNameFor: (in category 'gofer') -----
workingCopyNameFor: anMCLoader
| vi |
(vi := anMCLoader currentVersionInfoFor: self) == nil ifTrue: [ ^nil ].
^vi name!
----- Method: GoferReference>>matchesMetacelloGoferPackage: (in category '*metacello-mc') -----
matchesMetacelloGoferPackage: aMetacelloGoferPackage
| pFilename refFilename char |
((pFilename := aMetacelloGoferPackage packageFilename) == nil
or: [ aMetacelloGoferPackage name = aMetacelloGoferPackage packageFilename ])
ifTrue: [ ^ super matches: self ].
self name = pFilename
ifTrue: [ ^ true ].
(self name beginsWith: pFilename)
ifFalse: [ ^ false ].
refFilename := self metacelloPackageNameWithBranch at: 2.
refFilename = pFilename
ifTrue: [ ^ true ].
pFilename size < refFilename size
ifTrue: [
(refFilename beginsWith: pFilename)
ifFalse: [ ^ false ].
(char := pFilename at: pFilename size) ~= $-
ifTrue: [ char := refFilename at: pFilename size + 1 ] ]
ifFalse: [
(pFilename beginsWith: refFilename)
ifFalse: [ ^ false ].
(char := refFilename at: refFilename size) ~= $-
ifTrue: [ char := pFilename at: refFilename size + 1 ] ].
^ char = $. or: [ char = $- ]!
GoferLoad subclass: #MetacelloGoferLoad
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Gofer'!
----- Method: MetacelloGoferLoad>>updateCategories (in category 'private') -----
updateCategories
MetacelloPlatform current bypassGoferLoadUpdateCategories
ifFalse: [ super updateCategories ]!
----- Method: MetacelloGoferLoad>>updateRepositories (in category 'private') -----
updateRepositories
"Noop for Metacello...done by loader itself"!
----- Method: BlockClosure>>valueSupplyingMetacelloAnswers: (in category '*metacello-mc') -----
valueSupplyingMetacelloAnswers: aListOfPairs
"evaluate the block using a list of questions / answers that might be called upon to
automatically respond to Object>>confirm: or FillInTheBlank requests"
^ [self value]
on: ProvideAnswerNotification
do:
[:notify | | answer caption |
caption := notify messageText withSeparatorsCompacted. "to remove new lines"
answer := aListOfPairs
detect:
[:each | caption = each first or:
[(caption includesSubstring: each first caseSensitive: false) or:
[(each first match: caption) or:
[(String includesSelector: #matchesRegex:) and:
[ [ caption matchesRegex: each first ] on: Error do: [:ignored | false ]]]]]]
ifNone: [nil].
answer
ifNotNil: [notify resume: answer second]
ifNil:
[ | outerAnswer |
outerAnswer := ProvideAnswerNotification signal: notify messageText.
outerAnswer
ifNil: [notify resume]
ifNotNil: [notify resume: outerAnswer]]]!
MetacelloSpec subclass: #MetacelloRepositorySpec
instanceVariableNames: 'description username password type'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
----- Method: MetacelloRepositorySpec>>addToMetacelloRepositories: (in category 'adding') -----
addToMetacelloRepositories: aMetacelloRepositoriesSpec
aMetacelloRepositoriesSpec addMember:
(aMetacelloRepositoriesSpec addMember
name: self name;
spec: self;
yourself)!
----- Method: MetacelloRepositorySpec>>canUpgradeTo: (in category 'mc support') -----
canUpgradeTo: aMetacelloRepositorySpec
self description = aMetacelloRepositorySpec description
ifTrue: [ ^ true ].
(#('github' 'gitorious' 'bitbucket') includes: self type)
ifTrue: [ ^ self createRepository canUpgradeTo: aMetacelloRepositorySpec createRepository ].
^ false!
----- Method: MetacelloRepositorySpec>>configMethodCascadeOn:lastCascade: (in category 'printing') -----
configMethodCascadeOn: aStream lastCascade: lastCascade
aStream nextPutAll: 'repository: ', self description printString.
(self username isEmpty not or: [ self password isEmpty not ])
ifTrue: [ aStream nextPutAll: ' username: ', self username printString, ' password: ', self password printString ].
lastCascade ifFalse: [ aStream nextPut: $;; cr ].!
----- Method: MetacelloRepositorySpec>>configMethodOn:indent: (in category 'printing') -----
configMethodOn: aStream indent: indent
aStream
tab: indent;
nextPutAll: 'spec '.
self configMethodCascadeOn: aStream lastCascade: true!
----- Method: MetacelloRepositorySpec>>createRepository (in category 'mc support') -----
createRepository
| repo |
repo := self project createRepository: self.
^ self updateRepository: (MCRepositoryGroup default repositories
detect: [ :each | each = repo ]
ifNone: [
MCRepositoryGroup default addRepository: repo.
repo ])!
----- Method: MetacelloRepositorySpec>>description (in category 'querying') -----
description
^description!
----- Method: MetacelloRepositorySpec>>description: (in category 'accessing') -----
description: aString
description := aString!
----- Method: MetacelloRepositorySpec>>extractTypeFromDescription (in category 'private') -----
extractTypeFromDescription
^MetacelloPlatform current extractTypeFromDescription: self description!
----- Method: MetacelloRepositorySpec>>hasNoLoadConflicts: (in category 'mc support') -----
hasNoLoadConflicts: aMetacelloRepositorySpec
self description = aMetacelloRepositorySpec description
ifTrue: [ ^ true ].
self type = aMetacelloRepositorySpec type
ifFalse: [
"if the types are different then we don't need to create the repoitory to
know that there will be conflicts"
^ false ].
(#('github' 'gitorious' 'bitbucket') includes: self type)
ifTrue: [
^ self createRepository
hasNoLoadConflicts: aMetacelloRepositorySpec createRepository ].
^ false!
----- Method: MetacelloRepositorySpec>>mergeIntoMetacelloRepositories: (in category 'private') -----
mergeIntoMetacelloRepositories: aMetacelloRepositoriesSpec
aMetacelloRepositoriesSpec addMember:
(aMetacelloRepositoriesSpec mergeMember
name: self name;
spec: self;
yourself)!
----- Method: MetacelloRepositorySpec>>mergeMap (in category 'merging') -----
mergeMap
| map |
map := super mergeMap.
map at: #'description' put: description.
map at: #'type' put: self type.
map at: #'username' put: username.
map at: #'password' put: password.
^ map!
----- Method: MetacelloRepositorySpec>>name (in category 'querying') -----
name
^self description!
----- Method: MetacelloRepositorySpec>>password (in category 'querying') -----
password
password == nil ifTrue: [ password := '' ].
^password!
----- Method: MetacelloRepositorySpec>>password: (in category 'accessing') -----
password: aString
password := aString!
----- Method: MetacelloRepositorySpec>>removeFromMetacelloRepositories: (in category 'private') -----
removeFromMetacelloRepositories: aMetacelloRepositoriesSpec
aMetacelloRepositoriesSpec addMember:
(aMetacelloRepositoriesSpec removeMember
name: self name;
spec: self;
yourself)!
----- Method: MetacelloRepositorySpec>>type (in category 'querying') -----
type
type == nil ifTrue: [ type := self extractTypeFromDescription ].
^type!
----- Method: MetacelloRepositorySpec>>type: (in category 'accessing') -----
type: aString
type := aString!
----- Method: MetacelloRepositorySpec>>updateRepository: (in category 'mc support') -----
updateRepository: aRepository
(self username notNil and: [self username notEmpty]) ifTrue: [
aRepository username: self username].
(self password notNil and: [self password notEmpty]) ifTrue: [
aRepository password: self password].
^ aRepository!
----- Method: MetacelloRepositorySpec>>username (in category 'querying') -----
username
username == nil ifTrue: [ username := '' ].
^username!
----- Method: MetacelloRepositorySpec>>username: (in category 'accessing') -----
username: aString
username := aString!
MetacelloVersion subclass: #MetacelloMCVersion
instanceVariableNames: 'loaderPolicy'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Model'!
----- Method: MetacelloMCVersion>>allPackagesForSpecNamed: (in category 'querying') -----
allPackagesForSpecNamed: aStringOrArray
"resolves list of packages associated with the named spec.
If the spec is a packages, answer a list including the package and the transitive closure on
its #requires: and #includes: fields.
If the spec is a project, answer a list of the packages associated with the project,
following the transitive closure on packages reachable starting with the #loads: field.
If the spec is a group, answers the list of packages in the #includes: field of the group.
Groups in the #includes: field are expanded following the transitive closure on groups"
"In essence, this query answers the list of all packages that would be loaded if the package
named <aString> were loaded."
"If there is no spec named <aString>, answers an empty list"
^self allPackagesForSpecNamed: aStringOrArray ifAbsent: [ ^#() ]!
----- Method: MetacelloMCVersion>>allPackagesForSpecNamed:ifAbsent: (in category 'querying') -----
allPackagesForSpecNamed: aStringOrArray ifAbsent: aBlock
"resolves list of packages associated with the named spec.
If the spec is a packages, answer a list including the package and the transitive closure on
its #requires: and #includes: fields.
If the spec is a project, answer a list of the packages associated with the project,
following the transitive closure on packages reachable starting with the #loads: field.
If the spec is a group, answers the list of packages in the #includes: field of the group.
Groups in the #includes: field are expanded following the transitive closure on groups"
"In essence, this query answers the list of all packages that would be loaded if the package
named <aString> were loaded."
"If there is no spec named <aString>, aBlock is evaluated"
^aStringOrArray
resolvePackageSpecsNamedForMetacelloMCVersion: self
visited: MetacelloVisitedPackages new
ifAbsent: aBlock!
----- Method: MetacelloMCVersion>>allPackagesForSpecs:visited: (in category 'private') -----
allPackagesForSpecs: pkgSpecs visited: visited
| coll |
coll := Dictionary new.
pkgSpecs
do: [:pkgSpec | (pkgSpec resolveToAllPackagesIn: self spec visited: visited)
do: [:pkg | coll at: pkg name put: pkg ]].
^ coll values asOrderedCollection!
----- Method: MetacelloMCVersion>>cacheRepository: (in category 'accessing') -----
cacheRepository: repository
"by default cacheRepository is an MCDictionaryRepository"
self loaderPolicy cacheRepository: repository!
----- Method: MetacelloMCVersion>>computeVersionStatus (in category 'private') -----
computeVersionStatus
"
#allLoadedToSpec - all projects and packages are loaded and match specification
#loadedToSpec - all loaded projects and packages match specifications (at least one package loaded)
#loadedMatchConstraints - all loaded projects and packages match constraints (at least one package loaded)
#somethingLoaded - at least one package loaded
"
self spec computeVersionStatus: [ :status | ^ status ].
^ #noStatus!
----- Method: MetacelloMCVersion>>currentlyLoadedClassesInVersion (in category 'querying') -----
currentlyLoadedClassesInVersion
^self spec currentlyLoadedClassesInVersion!
----- Method: MetacelloMCVersion>>currentlyLoadedExtensionClassesInVersion (in category 'querying') -----
currentlyLoadedExtensionClassesInVersion
^self spec currentlyLoadedExtensionClassesInVersion!
----- Method: MetacelloMCVersion>>defaultPackageNamesToLoad (in category 'querying') -----
defaultPackageNamesToLoad
"Answer the list of packages and projects to be loaded --> packages already loaded"
^ self defaultPackageNamesToLoad: self spec defaultPackageNames!
----- Method: MetacelloMCVersion>>defaultPackageNamesToLoad: (in category 'querying') -----
defaultPackageNamesToLoad: defaultList
"Answer the list of packages and projects to be loaded: packages already loaded plust defaultList"
^ self packageAndProjectNamesToLoad: defaultList loader: self loader!
----- Method: MetacelloMCVersion>>doFetchRequiredFromArray: (in category 'private') -----
doFetchRequiredFromArray: anArray
| oldPolicy oldBypassProgress displayString |
displayString := self versionNumber printString, ' of ', self spec projectLabel.
Transcript cr; show: 'Fetching ', displayString, '...'.
oldPolicy := loaderPolicy.
oldBypassProgress := MetacelloPlatform current bypassProgressBars.
self loaderPolicy silently ifTrue: [ MetacelloPlatform current bypassProgressBars: true ].
[ | ans |
ans := self fetchRequiredFromArray: anArray.
Transcript cr; show: '...finished ', self versionNumber printString.
^ans ]
ensure: [
MetacelloPlatform current bypassProgressBars: oldBypassProgress.
loaderPolicy := oldPolicy ]!
----- Method: MetacelloMCVersion>>doLoadRequiredFromArray: (in category 'private') -----
doLoadRequiredFromArray: anArray
| displayString oldPolicy oldBypassProgress |
displayString := self versionNumber printString, ' of ', self spec projectLabel.
Transcript cr; show: 'Loading ', displayString, '...'.
oldPolicy := loaderPolicy.
oldBypassProgress := MetacelloPlatform current bypassProgressBars.
self loaderPolicy silently ifTrue: [ MetacelloPlatform current bypassProgressBars: true ].
[ | fetchLoader |
fetchLoader := self fetchRequiredFromArray: (self defaultPackageNamesToLoad: anArray).
MetacelloPlatform current
do: [ fetchLoader doLoad ]
displaying: 'Loading ', displayString.
Transcript cr; show: '...finished ', self versionNumber printString.
^fetchLoader ]
ensure: [
MetacelloPlatform current bypassProgressBars: oldBypassProgress.
loaderPolicy := oldPolicy ]!
----- Method: MetacelloMCVersion>>doRecordRequiredFromArray: (in category 'private') -----
doRecordRequiredFromArray: anArray
| originalLoader oldPolicy displayString oldBypassProgress |
displayString := self versionNumber printString, ' of ', self spec projectLabel.
Transcript cr; show: 'Recording ', displayString, '...'.
originalLoader := self versionSpec loader.
oldPolicy := loaderPolicy.
oldBypassProgress := MetacelloPlatform current bypassProgressBars.
self loaderPolicy silently ifTrue: [ MetacelloPlatform current bypassProgressBars: true ].
[ MetacelloPlatform current
do: [ | ans |
self versionSpec loader: originalLoader recordingSpecLoader.
ans := (self executeLoadFromArray: anArray) copy.
Transcript cr; show: '...finished ', self versionNumber printString.
^ans ]
displaying: 'Recording ', displayString ]
ensure: [
MetacelloPlatform current bypassProgressBars: oldBypassProgress.
self versionSpec loader: originalLoader.
loaderPolicy := oldPolicy ]!
----- Method: MetacelloMCVersion>>executeLoadFromArray: (in category 'private') -----
executeLoadFromArray: anArray
| loader |
loader := MetacelloMCVersionSpecLoader on: self spec.
loader required: anArray.
loaderPolicy notNil ifTrue: [ loader loaderPolicy: loaderPolicy ].
^loader load
!
----- Method: MetacelloMCVersion>>fetch (in category 'actions') -----
fetch
^self doFetchRequiredFromArray: self spec defaultPackageNames!
----- Method: MetacelloMCVersion>>fetch: (in category 'actions') -----
fetch: required
^required fetchRequiredForMetacelloMCVersion: self!
----- Method: MetacelloMCVersion>>fetchRequiredFromArray: (in category 'private') -----
fetchRequiredFromArray: anArray
| originalLoader displayString newLoader |
originalLoader := self versionSpec loader.
newLoader := originalLoader fetchingSpecLoader.
displayString := newLoader actionLabel , self versionNumber printString , ' of ' , self spec projectLabel.
MetacelloPlatform current
do: [
[
self versionSpec loader: newLoader.
MetacelloPlatform current
useStackCacheDuring: [ :dict | ^ self executeLoadFromArray: anArray ]
defaultDictionary: Dictionary new ] ensure: [ self versionSpec loader: originalLoader ] ]
displaying: displayString!
----- Method: MetacelloMCVersion>>ignoreImage: (in category 'accessing') -----
ignoreImage: aBool
"by default ignoreImage is false"
self loaderPolicy ignoreImage: aBool!
----- Method: MetacelloMCVersion>>load (in category 'actions') -----
load
^self doLoadRequiredFromArray: self spec defaultPackageNames!
----- Method: MetacelloMCVersion>>load: (in category 'actions') -----
load: required
^required loadRequiredForMetacelloMCVersion: self!
----- Method: MetacelloMCVersion>>loadRequiredFromArray: (in category 'private') -----
loadRequiredFromArray: anArray
| displayString |
displayString := 'Loading ', self versionNumber printString, ' of ', self spec projectLabel.
MetacelloPlatform current
do: [ ^self executeLoadFromArray: anArray ]
displaying: displayString!
----- Method: MetacelloMCVersion>>loader: (in category 'private') -----
loader: aLoader
self versionSpec loader: aLoader!
----- Method: MetacelloMCVersion>>loaderPolicy (in category 'accessing') -----
loaderPolicy
loaderPolicy == nil ifTrue: [ loaderPolicy := MetacelloLoaderPolicy new ].
^ loaderPolicy!
----- Method: MetacelloMCVersion>>loaderPolicy: (in category 'accessing') -----
loaderPolicy: anObject
loaderPolicy := anObject!
----- Method: MetacelloMCVersion>>packageAndProjectNamesToLoad:loader: (in category 'querying') -----
packageAndProjectNamesToLoad: defaultList loader: aLoader
"Answer the list of packages and projects to be loaded: packages already loaded plust defaultList"
| loadedPackageNames projectMap loadedProjectNames list |
loadedPackageNames := ((self packages select: [:pkg | pkg isPackageLoaded: aLoader ])
collect: [:pkg | pkg name ]) asSet,
defaultList.
projectMap := Dictionary new.
self projects do: [:prj |
prj className ~~ nil
ifTrue: [ | coll loaded |
coll := projectMap at: prj className ifAbsent: [
coll := OrderedCollection new.
projectMap at: prj className put: coll.
coll].
(loaded := prj loadedPackageNames: aLoader) isEmpty
ifFalse: [ coll add: prj -> (loaded -> prj loadPackageList) ]]].
loadedProjectNames := Set new.
projectMap keysAndValuesDo: [:prjClass :coll |
coll size <= 1
ifTrue: [ coll do: [:assoc | loadedProjectNames add: assoc key name ]]
ifFalse: [
"multiple project references against the same configuration ... only count project as loaded
if there is an exact match for loaded projects...
See http://code.google.com/p/metacello/issues/detail?id=86"
coll do: [:assoc | | loaded packageList |
loaded := assoc value key. "loaded packages from project"
packageList := assoc value value. "loadlist for project"
(packageList difference: loaded) isEmpty
ifTrue: [ loadedProjectNames add: assoc key name ]]]].
list := loadedPackageNames, loadedProjectNames.
list isEmpty ifTrue: [ ^self spec defaultPackageNames].
^list!
----- Method: MetacelloMCVersion>>packages (in category 'querying') -----
packages
"Answers the list of packages associated with this version"
| packages |
packages := OrderedCollection new.
self spec projectDo: [:ignored | ] packageDo: [:pkg | packages add: pkg ] groupDo: [:ignored | ].
^packages!
----- Method: MetacelloMCVersion>>packagesForSpecNamed: (in category 'querying') -----
packagesForSpecNamed: aString
"resolves list of packages associated with the named spec.
If the spec is a packages, answer a list including only the package. #requires: and #includes:
fields in the package are ignored.
If the spec is a project, answers an empty list.
If the spec is a group, answers the list of packages in the #includes: field of the group.
Groups in the #includes: field are expanded following the transitive closure on groups"
"If there is no spec named <aString>, answers an empty list"
^self packagesForSpecNamed: aString ifAbsent: [ ^#() ]!
----- Method: MetacelloMCVersion>>packagesForSpecNamed:ifAbsent: (in category 'querying') -----
packagesForSpecNamed: aString ifAbsent: aBlock
"resolves list of packages associated with the named spec.
If the spec is a packages, answer a list including only the package. #requires: and #includes:
fields in the package are ignored.
If the spec is a project, answers an empty list.
If the spec is a group, answers the list of packages in the #includes: field of the group.
Groups in the #includes: field are expanded following the transitive closure on groups"
"If there is no spec named <aString>, aBlock is evaluated"
| pkgSpec |
pkgSpec := self spec packageNamed: aString ifAbsent: aBlock.
^pkgSpec resolveToPackagesIn: self spec visited: MetacelloVisitedPackages new!
----- Method: MetacelloMCVersion>>record (in category 'actions') -----
record
^self doRecordRequiredFromArray: self spec defaultPackageNames!
----- Method: MetacelloMCVersion>>record: (in category 'actions') -----
record: required
^required recordRequiredForMetacelloMCVersion: self!
----- Method: MetacelloMCVersion>>repositoryOverrides: (in category 'accessing') -----
repositoryOverrides: repositoriesCollection
self loaderPolicy overrideRepositories: repositoriesCollection!
----- Method: MetacelloMCVersion>>silently: (in category 'accessing') -----
silently: aBool
"by default silently is false"
self loaderPolicy silently: aBool!
MetacelloGenericProjectSpec subclass: #MetacelloMCProjectSpec
instanceVariableNames: 'file'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
MetacelloMCProjectSpec subclass: #MetacelloMCBaselineOfProjectSpec
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
----- Method: MetacelloMCBaselineOfProjectSpec>>asBaselineProjectSpec (in category 'scripting') -----
asBaselineProjectSpec
^ self!
----- Method: MetacelloMCBaselineOfProjectSpec>>asProjectRegistration (in category 'scripting') -----
asProjectRegistration
^ MetacelloProjectRegistration fromMCBaselineProjectSpec: self!
----- Method: MetacelloMCBaselineOfProjectSpec>>canDowngradeTo: (in category 'scripting') -----
canDowngradeTo: aProjectSpec
"cannot upgrade between baselines"
^ false!
----- Method: MetacelloMCBaselineOfProjectSpec>>canUpgradeTo: (in category 'scripting') -----
canUpgradeTo: aProjectSpec
"cannot upgrade between baselines unless repositories can be upgraded"
(self repositories canUpgradeTo: aProjectSpec repositories)
ifTrue: [ ^ true ].
^ false!
----- Method: MetacelloMCBaselineOfProjectSpec>>configHasVersionString (in category 'printing') -----
configHasVersionString
^ false!
----- Method: MetacelloMCBaselineOfProjectSpec>>constructClassName (in category 'private') -----
constructClassName
^ 'BaselineOf' , self name!
----- Method: MetacelloMCBaselineOfProjectSpec>>copyForRegistration:onWrite: (in category 'mutability') -----
copyForRegistration: aMetacelloProjectRegistration onWrite: aBlock
| copy |
aMetacelloProjectRegistration
baselineProjectSpecIfPresent: [ :spec |
copy := spec copy.
aBlock value: copy.
aMetacelloProjectRegistration baselineProjectSpec: copy ]
ifAbsent: [
aMetacelloProjectRegistration
configurationProjectSpecIfPresent: [ :spec |
copy := spec copy.
aBlock value: copy.
aMetacelloProjectRegistration configurationProjectSpec: copy ]
ifAbsent: [ aBlock value: nil ] ]!
----- Method: MetacelloMCBaselineOfProjectSpec>>determineCurrentVersionForLoad (in category 'loading') -----
determineCurrentVersionForLoad
^ self version!
----- Method: MetacelloMCBaselineOfProjectSpec>>ensureConfigurationLoaded:ensured: (in category 'loading') -----
ensureConfigurationLoaded: vrsn ensured: ensured
"answer true if the configuration should be reloaded"
"see Issue #181 for details ... basically we always want to consider loading the baseline from a project reference, especially if the two project specs are not the same..."
"https://github.com/dalehenrich/metacello-work/issues/181"
^ true!
----- Method: MetacelloMCBaselineOfProjectSpec>>ensureLoadUsing: (in category 'loading') -----
ensureLoadUsing: aLoader
"see https://github.com/dalehenrich/metacello-work/issues/244 ... uncoditionally load
baseline"
[ super ensureLoadUsing: aLoader ]
on: MetacelloIgnorePackageLoaded
do: [ :ex | ex resume: ex packageSpec name = self name ]!
----- Method: MetacelloMCBaselineOfProjectSpec>>hasClassName (in category 'printing') -----
hasClassName
^ className ~~ nil and: [ className ~= self constructClassName ]!
----- Method: MetacelloMCBaselineOfProjectSpec>>hasConflictWithConfigurationSpec: (in category 'testing') -----
hasConflictWithConfigurationSpec: projectSpec
"baseline can be loaded on top of a configuration without a conflict"
^ false!
----- Method: MetacelloMCBaselineOfProjectSpec>>hasConflictWithProjectSpec: (in category 'testing') -----
hasConflictWithProjectSpec: projectSpec
^ projectSpec hasConflictWithBaselineSpec: self!
----- Method: MetacelloMCBaselineOfProjectSpec>>isBaselineOfProjectSpec (in category 'testing') -----
isBaselineOfProjectSpec
^ true!
----- Method: MetacelloMCBaselineOfProjectSpec>>mergeImportLoads: (in category 'importing') -----
mergeImportLoads: aLoadList
aLoadList
ifNotNil: [ :otherLoads | self loads ifNil: [ loads := otherLoads ] ifNotNil: [ loads := loads , otherLoads ] ]!
----- Method: MetacelloMCBaselineOfProjectSpec>>mergeRepositoriesSpec: (in category 'merging') -----
mergeRepositoriesSpec: anotherRepositories
"anotherRepositories wins ... there can ever only be one repository for the
baseline to load from"
"https://github.com/dalehenrich/metacello-work/issues/251"
self repositories: anotherRepositories!
----- Method: MetacelloMCBaselineOfProjectSpec>>mergeSpec: (in category 'merging') -----
mergeSpec: anotherSpec
^ super mergeSpec: anotherSpec asBaselineProjectSpec!
----- Method: MetacelloMCBaselineOfProjectSpec>>projectLabel (in category 'printing') -----
projectLabel
^ 'baseline'!
----- Method: MetacelloMCBaselineOfProjectSpec>>repositoryBranchName (in category 'querying') -----
repositoryBranchName
"extract a branch name from the repository ... if possible"
"must parallel implementation of MetacelloMCBaselineProject>>setBaselineRepositoryDescription: we want the same repoSpec"
| spec repo |
self repositorySpecs do: [ :repoSpec | spec := repoSpec ].
repo := spec createRepository.
^ repo repositoryBranchName!
----- Method: MetacelloMCBaselineOfProjectSpec>>repositoryVersionString (in category 'querying') -----
repositoryVersionString
"extract a version string from the repository ... if possible"
"must parallel implementation of MetacelloMCBaselineProject>>setBaselineRepositoryDescription: we want the same repoSpec"
| spec repo |
self repositorySpecs do: [ :repoSpec | spec := repoSpec ].
[ repo := spec createRepository ]
on: Error
do: [ :ex | ^ '' ].
^ repo repositoryVersionString!
----- Method: MetacelloMCBaselineOfProjectSpec>>validateMergeForSpec: (in category 'merging') -----
validateMergeForSpec: aSpec
(aSpec validateMergeWithBaselineOfSpec: self)
ifFalse: [
self
error:
'The project spec ' , self name printString , ' in project '
, self project label , ' has incompatible specs. '
, aSpec class name asString , ' and ' , self class name asString
, ' are not compatible.' ]!
----- Method: MetacelloMCBaselineOfProjectSpec>>validateMergeWithBaselineOfSpec: (in category 'merging') -----
validateMergeWithBaselineOfSpec: aSpec
^ true!
----- Method: MetacelloMCBaselineOfProjectSpec>>validateVersionString:withDefaultVersionString: (in category 'scripting') -----
validateVersionString: issues withDefaultVersionString: ignored
self versionString
ifNotNil: [ :vs |
| prj |
prj := self project asBaselineProject.
vs ~= prj singletonVersionName
ifTrue: [
issues
add:
(MetacelloValidationError
configurationClass: self projectClass
reasonCode: #'invalidVersionString'
callSite:
#'validateForScriptLoad:withDefaultVersionString:withDefaultRepositoryDecription:'
explanation:
'version field is incorrect, should be: ' , prj singletonVersionName printString) ] ]!
----- Method: MetacelloMCBaselineOfProjectSpec>>version (in category 'querying') -----
version
self projectClass == nil
ifTrue: [ ^ nil ].
^ self projectClassProject version!
----- Method: MetacelloMCBaselineOfProjectSpec>>version:constructor: (in category 'construction') -----
version: anObject constructor: aVersionConstructor
self error: 'version: not allowed in a baseline project spec'!
----- Method: MetacelloMCBaselineOfProjectSpec>>versionString (in category 'querying') -----
versionString
^ versionString ifNil: [ self version ifNotNil: [:v | v versionString] ]!
----- Method: MetacelloMCBaselineOfProjectSpec>>versionString:constructor: (in category 'construction') -----
versionString: anObject constructor: aVersionConstructor
self error: 'versionString: not allowed in a baseline project spec'!
MetacelloMCProjectSpec subclass: #MetacelloMCConfigurationOfProjectSpec
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
----- Method: MetacelloMCConfigurationOfProjectSpec>>asConfigurationProjectSpec (in category 'scripting') -----
asConfigurationProjectSpec
^ self!
----- Method: MetacelloMCConfigurationOfProjectSpec>>asProjectRegistration (in category 'scripting') -----
asProjectRegistration
^ MetacelloProjectRegistration fromMCConfigurationProjectSpec: self!
----- Method: MetacelloMCConfigurationOfProjectSpec>>constructClassName (in category 'private') -----
constructClassName
^ 'ConfigurationOf' , self name!
----- Method: MetacelloMCConfigurationOfProjectSpec>>copyForRegistration:onWrite: (in category 'mutability') -----
copyForRegistration: aMetacelloProjectRegistration onWrite: aBlock
| copy |
aMetacelloProjectRegistration
configurationProjectSpecIfPresent: [ :spec |
copy := spec copy.
aBlock value: copy.
aMetacelloProjectRegistration configurationProjectSpec: copy ]
ifAbsent: [
aMetacelloProjectRegistration
baselineProjectSpecIfPresent: [ :spec |
copy := spec copy.
aBlock value: copy.
aMetacelloProjectRegistration baselineProjectSpec: copy ]
ifAbsent: [ aBlock value: nil ] ]!
----- Method: MetacelloMCConfigurationOfProjectSpec>>hasClassName (in category 'printing') -----
hasClassName
^ className ~~ nil and: [ className ~= self constructClassName ]!
----- Method: MetacelloMCConfigurationOfProjectSpec>>hasConflictWithBaselineSpec: (in category 'testing') -----
hasConflictWithBaselineSpec: projectSpec
projectSpec name = self name
ifFalse: [ ^ true ].
projectSpec project configuration className = self project configuration className
ifFalse: [ ^ true ].
^ ((projectSpec repositories isEmpty or: [ self repositories isEmpty ])
or: [ projectSpec repositories hasNoLoadConflicts: self repositories ]) not!
----- Method: MetacelloMCConfigurationOfProjectSpec>>hasConflictWithProjectSpec: (in category 'testing') -----
hasConflictWithProjectSpec: projectSpec
^ projectSpec hasConflictWithConfigurationSpec: self!
----- Method: MetacelloMCConfigurationOfProjectSpec>>isConfigurationOfProjectSpec (in category 'testing') -----
isConfigurationOfProjectSpec
^ true!
----- Method: MetacelloMCConfigurationOfProjectSpec>>mergeSpec: (in category 'merging') -----
mergeSpec: anotherSpec
^ super mergeSpec: anotherSpec asConfigurationProjectSpec!
----- Method: MetacelloMCConfigurationOfProjectSpec>>projectLabel (in category 'printing') -----
projectLabel
^ 'configuration'!
MetacelloMCProjectSpec subclass: #MetacelloMCNamelessProjectSpec
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
----- Method: MetacelloMCNamelessProjectSpec>>asProjectSpecForVersion: (in category 'scripting') -----
asProjectSpecForVersion: vrsn
"I'm a reference spec and my project comes from the project I'm loaded from, not the project I am loading"
"https://github.com/dalehenrich/metacello-work/issues/331"
| proj spec |
proj := vrsn ifNil: [ ^ self ] ifNotNil: [ vrsn versionSpec project ].
spec := proj configurationOfProjectSpecClass for: proj.
self copyForScriptingInto: spec.
spec loader: self loader.
self assert: (self className beginsWith: 'BaselineOf') not.
^ spec!
----- Method: MetacelloMCNamelessProjectSpec>>copyForRegistration:onWrite: (in category 'mutability') -----
copyForRegistration: aMetacelloProjectRegistration onWrite: aBlock
self error: 'Should be converting to configuration spec for the registration, so we should not get here'!
----- Method: MetacelloMCProjectSpec class>>new (in category 'instance creation') -----
new
self name == #MetacelloMCProjectSpec
ifTrue: [ self error: 'This class is abstract' ].
^ super new!
----- Method: MetacelloMCProjectSpec>>allPackagesLoaded: (in category 'testing') -----
allPackagesLoaded: aLoader
"answer true if all of the packages (excluding projects) are loaded"
| vrsn pkgs |
(vrsn := self versionOrNil) == nil
ifTrue: [ ^ false ].
pkgs := OrderedCollection new.
(self loadListForVersion: vrsn)
do: [ :nm |
vrsn packages
do: [ :pkg |
(pkg isPackageLoaded: aLoader)
ifFalse: [ ^ false ] ] ].
^ true!
----- Method: MetacelloMCProjectSpec>>asBaselineProjectSpec (in category 'scripting') -----
asBaselineProjectSpec
^ self copyForScriptingInto: (MetacelloMCBaselineOfProjectSpec for: self project asBaselineProject)!
----- Method: MetacelloMCProjectSpec>>asConfigurationProjectSpec (in category 'scripting') -----
asConfigurationProjectSpec
^ self copyForScriptingInto: (MetacelloMCConfigurationOfProjectSpec for: self project asConfigurationProject)!
----- Method: MetacelloMCProjectSpec>>asProjectRegistration (in category 'scripting') -----
asProjectRegistration
(self className beginsWith: 'BaselineOf')
ifTrue: [
^ MetacelloProjectRegistration
fromMCBaselineProjectSpec: self asBaselineProjectSpec ].
^ MetacelloProjectRegistration
fromMCConfigurationProjectSpec: self asConfigurationProjectSpec!
----- Method: MetacelloMCProjectSpec>>asProjectSpec (in category 'scripting') -----
asProjectSpec
^ self!
----- Method: MetacelloMCProjectSpec>>asProjectSpecForVersion: (in category 'scripting') -----
asProjectSpecForVersion: vrsn
^ self!
----- Method: MetacelloMCProjectSpec>>baseName (in category 'accessing') -----
baseName
^ MetacelloScriptEngine baseNameOf: self className!
----- Method: MetacelloMCProjectSpec>>canDowngradeTo: (in category 'scripting') -----
canDowngradeTo: aMetacelloProjectSpec
^ (super canDowngradeTo: aMetacelloProjectSpec) and: [ self file = aMetacelloProjectSpec file ]!
----- Method: MetacelloMCProjectSpec>>canUpgradeTo: (in category 'scripting') -----
canUpgradeTo: aMetacelloProjectSpec
^ (super canUpgradeTo: aMetacelloProjectSpec) and: [ self file = aMetacelloProjectSpec file ]!
----- Method: MetacelloMCProjectSpec>>className: (in category 'accessing') -----
className: aString
super className: aString.
self projectPackage: nil!
----- Method: MetacelloMCProjectSpec>>compareCurrentVersion:targetVersionStatus:using: (in category 'testing') -----
compareCurrentVersion: anOperator targetVersionStatus: targetVersionStatus using: anMCLoader
^ (MetacelloLookupProjectSpecForLoad new
projectSpec: self;
yourself) signal
performCurrentVersionTestAgainst: self versionOrNil
operator: anOperator
targetVersionStatus: targetVersionStatus
using: anMCLoader!
----- Method: MetacelloMCProjectSpec>>compareEqual: (in category 'scripting') -----
compareEqual: aMetacelloProjectSpec
"'projectPackage repositories'"
^ (super compareEqual: aMetacelloProjectSpec) and: [ self file = aMetacelloProjectSpec file ]!
----- Method: MetacelloMCProjectSpec>>compareRelativeCurrentVersion:targetVersionStatus:using: (in category 'testing') -----
compareRelativeCurrentVersion: anOperator targetVersionStatus: targetVersionStatus using: anMCLoader
| cv vrsn |
(vrsn := self versionOrNil) == nil ifTrue: [ ^false ].
(cv := self relativeCurrentVersion) == nil ifTrue: [ ^false ].
(targetVersionStatus includes: cv versionStatus)
ifTrue: [ ^cv perform: anOperator with: vrsn ].
^false!
----- Method: MetacelloMCProjectSpec>>copyForRegistration:onWrite: (in category 'mutability') -----
copyForRegistration: aMetacelloProjectRegistration onWrite: aBlock
self subclassResponsibility!
----- Method: MetacelloMCProjectSpec>>copyForScriptingInto: (in category 'scripting') -----
copyForScriptingInto: aProjectSpec
^aProjectSpec
setName: name;
className: className;
versionString: versionString;
operator: operator;
setLoads: loads;
preLoadDoIt: preLoadDoIt;
postLoadDoIt: postLoadDoIt;
repositories: repositories copy;
file: file!
----- Method: MetacelloMCProjectSpec>>determineCurrentVersionForLoad (in category 'loading') -----
determineCurrentVersionForLoad
"don't use self currentVersion, because we are interested in the currentVersion of the project as loaded in image, not the current version relative to our load list"
| prjct version currentVersion cvs |
self projectClass == nil
ifTrue: [ ^ nil ].
(version := self versionOrNil) == nil
ifTrue: [ ^ nil ].
version blessing == #'baseline'
ifTrue: [ ^ version ].
self loader ignoreImage
ifTrue: [ ^ version ].
prjct := self projectClass new project.
prjct loader: self loader.
(currentVersion := prjct currentVersion) == nil
ifTrue: [ ^ nil ].
(cvs := currentVersion versionStatus) == #'somethingLoaded'
ifTrue: [ ^ nil ].
(#(#'allLoadedToSpec' #'loadedToSpec' #'loadedMatchConstraints') includes: (cvs := currentVersion versionStatus))
ifTrue: [
(currentVersion perform: self operator with: version)
ifTrue: [
"load currentVersion"
^ currentVersion ]. "load version"
^ nil ].
version = currentVersion
ifTrue: [ ^ currentVersion ]. "I don't believe that it is possible to reach this point in the method, so I will be interested if I run across a case that produces this error"
(MetacelloProjectSpecLoadConflict projectSpec: self)
signal:
'Project load conflict for' , prjct label printString , ' between current version ' , currentVersion printString , '('
, cvs asString , ') and specified version ' , version printString
, '. Press resume to continue with load anyway'.
^ nil
!
----- Method: MetacelloMCProjectSpec>>ensureConfigurationLoaded:ensured: (in category 'loading') -----
ensureConfigurationLoaded: vrsn ensured: ensured
"answer true if the configuration should be reloaded:
blessing is #development
symbolic version (https://github.com/dalehenrich/metacello-work/issues/283)"
(vrsn blessing == #'development' or: [ self versionString isSymbol ])
ifTrue: [
ensured ~~ #'latest'
ifTrue: [ ^ MetacelloScriptEnsureProjectLoadedForDevelopment signal ] ].
^ false!
----- Method: MetacelloMCProjectSpec>>ensureLoadUsing: (in category 'loading') -----
ensureLoadUsing: aLoader
| pp |
pp := (MetacelloLookupProjectSpec new
projectSpec: self;
yourself) signal projectPackage.
pp
ifNil: [
self
error:
'Unable to resolve project package for ' , self name printString
,
'. It is likely that that the configuration referencing this project will not validate properly (see MetacelloToolBox class>>validateConfiguration:).' ].
pp ensureLoadUsing: aLoader!
----- Method: MetacelloMCProjectSpec>>ensureLoadedForDevelopmentUsing: (in category 'loading') -----
ensureLoadedForDevelopmentUsing: mcLoader
"for #development projects, always need latest version of package when contemplating a load"
| ensured |
ensured := mcLoader ensuredMap at: self name ifAbsent: [ nil ].
self projectClass ~~ nil
ifTrue: [
| vrsn |
vrsn := self versionOrNil.
vrsn ~~ nil
ifTrue: [
(self ensureConfigurationLoaded: vrsn ensured: ensured)
ifTrue: [
mcLoader ensureForDevelopment
ifTrue: [
| pc |
(pc := self projectClass) ~~ nil
ifTrue: [
MetacelloClearStackCacheNotification
signal:
#(#'currentVersion' #'currentVersionAgainst:' #'currentVersionInfo' #'versionConstructor' #'loadableSpecNames')
, {pc} ].
self ensureLoadUsing: mcLoader ]
ifFalse: [ self projectPackage fetchUsing: mcLoader ].
mcLoader ensuredMap at: self name put: #'latest' ].
^ self ] ].
ensured == nil
ifTrue: [
"projectClass == nil or version == nil"
mcLoader ensureForDevelopment
ifTrue: [
| pc |
(pc := self projectClass) ~~ nil
ifTrue: [
MetacelloClearStackCacheNotification
signal:
#(#'currentVersion' #'currentVersionAgainst:' #'currentVersionInfo' #'versionConstructor' #'loadableSpecNames')
, {pc} ].
self ensureLoadUsing: mcLoader ]
ifFalse: [ self fetchUsing: mcLoader ].
mcLoader ensuredMap at: self name put: #'present' ]!
----- Method: MetacelloMCProjectSpec>>ensureProjectLoaded (in category 'loading') -----
ensureProjectLoaded
"Ensure that the MetacelloProject is loaded in image.
projectClass == nil or requested version non-existent warrants a project package load."
"answer true if the projectClass exists"
(self projectClass == nil
or: [
self versionOrNil == nil
or: [ (loader notNil or: [ self isMutable ]) and: [ self loader ignoreImage ] ] ])
ifTrue: [
| pc |
(pc := self projectClass) ~~ nil
ifTrue: [
MetacelloClearStackCacheNotification
signal:
#(#'currentVersion' #'currentVersionAgainst:' #'currentVersionInfo' #'versionConstructor' #'loadableSpecNames')
, {pc} ].
self projectPackage ifNil: [ ^ true ].
self ensureLoadUsing: self loader ].
^ self projectClass ~~ nil!
----- Method: MetacelloMCProjectSpec>>fetchUsing: (in category 'loading') -----
fetchUsing: aLoader
(MetacelloLookupProjectSpec new
projectSpec: self;
yourself) signal projectPackage fetchUsing: aLoader!
----- Method: MetacelloMCProjectSpec>>file (in category 'querying') -----
file
file ifNil: [ ^ self className ].
^ file!
----- Method: MetacelloMCProjectSpec>>file: (in category 'accessing') -----
file: aString
self shouldBeMutable.
file := aString.
self projectPackage: nil!
----- Method: MetacelloMCProjectSpec>>file:constructor: (in category 'construction') -----
file: aString constructor: aVersionConstructor
aVersionConstructor fileForProject: aString!
----- Method: MetacelloMCProjectSpec>>getFile (in category 'accessing') -----
getFile
"raw access to iv"
^ file!
----- Method: MetacelloMCProjectSpec>>hasConflictWithBaselineSpec: (in category 'testing') -----
hasConflictWithBaselineSpec: projectSpec
^ self hasLoadConflicts: projectSpec!
----- Method: MetacelloMCProjectSpec>>hasConflictWithConfigurationSpec: (in category 'testing') -----
hasConflictWithConfigurationSpec: projectSpec
^ self hasLoadConflicts: projectSpec!
----- Method: MetacelloMCProjectSpec>>hasConflictWithProjectSpec: (in category 'testing') -----
hasConflictWithProjectSpec: projectSpec
(self className beginsWith: 'BaselineOf')
ifTrue: [ ^ projectSpec hasConflictWithBaselineSpec: self asBaselineProjectSpec ].
^ projectSpec
hasConflictWithConfigurationSpec: self asConfigurationProjectSpec!
----- Method: MetacelloMCProjectSpec>>hasNoLoadConflicts: (in category 'scripting') -----
hasNoLoadConflicts: aMetacelloProjectSpec
"'projectPackage repositories'"
^ (super hasNoLoadConflicts: aMetacelloProjectSpec)
and: [ self file = aMetacelloProjectSpec file ]!
----- Method: MetacelloMCProjectSpec>>isBaselineOfProjectSpec (in category 'testing') -----
isBaselineOfProjectSpec
^ false!
----- Method: MetacelloMCProjectSpec>>isConfigurationOfProjectSpec (in category 'testing') -----
isConfigurationOfProjectSpec
^ false!
----- Method: MetacelloMCProjectSpec>>isPartiallyLoaded: (in category 'testing') -----
isPartiallyLoaded: aLoader
| vrsn |
(vrsn := self versionOrNil) == nil ifTrue: [ ^false ].
(self loadListForVersion: vrsn) do: [:nm |
(vrsn packagesForSpecNamed: nm ) do: [:pkg |
(pkg isPackageLoaded: aLoader) ifTrue: [ ^true ]]].
^false!
----- Method: MetacelloMCProjectSpec>>isPossibleBaseline (in category 'testing') -----
isPossibleBaseline
| vrsn |
(vrsn := self versionOrNil) == nil ifTrue: [ ^false ].
(vrsn allPackagesForSpecNamed: (self loadListForVersion: vrsn)) do: [:pkg |
pkg workingCopy == nil ifTrue: [ ^false ]].
^true!
----- Method: MetacelloMCProjectSpec>>loadPackageList (in category 'accessing') -----
loadPackageList
| vrsn pkgs |
(vrsn := self versionOrNil) == nil ifTrue: [ ^#() ].
pkgs := OrderedCollection new.
(self loadListForVersion: vrsn) do: [:nm |
pkgs addAll: ((vrsn packagesForSpecNamed: nm ) collect: [:each | each name ])].
^pkgs!
----- Method: MetacelloMCProjectSpec>>loadVersion: (in category 'loading') -----
loadVersion: aVersionOrNil
"Load the correct version of the project"
| vrsn mcLoader list |
self ensureProjectLoaded.
vrsn := aVersionOrNil.
vrsn == nil
ifTrue: [ [ vrsn := self version ]
on: MetacelloVersionDoesNotExistError
do: [ :ex |
^ (MetacelloProjectSpecLoadError projectSpec: self)
versionDoesNotExistException: ex;
signal:
'No version found for ' , self versionString printString , ' of '
, self className asString , ' because: ' , ex description ] ].
mcLoader := self loader copy.
mcLoader operator: self operator.
vrsn loader: mcLoader.
list := (mcLoader ignoreImage
ifTrue: [ self loadListForVersion: vrsn ]
ifFalse: [ vrsn
packageAndProjectNamesToLoad: (self loadListForVersion: vrsn)
loader: mcLoader ]) asSet.
MetacelloPlatform current
useStackCacheDuring: [ :dict |
| projectCache cachedList |
projectCache := dict
at: self projectClass
ifAbsent: [ dict at: self projectClass put: Dictionary new ].
(cachedList := projectCache at: vrsn ifAbsent: [ ]) == nil
ifTrue: [ projectCache at: vrsn put: list ]
ifFalse: [
(cachedList size = list size
and: [ cachedList allSatisfy: [ :each | list includes: each ] ])
ifTrue:
[ "no need to refetch list ... recursion stoppper (Issue 95)" ^ self ]
ifFalse: [ projectCache at: vrsn put: list ] ].
vrsn versionString ~= self versionString
ifTrue: [ Transcript show: ' [' , vrsn versionString , ']' ].
mcLoader preLoad: self.
vrsn fetchRequiredFromArray: list. "do the load"
(MetacelloProjectSpecLoadedNotification new
projectSpec: (self copy versionString: vrsn versionString)) signal.
mcLoader postLoad: self ]
defaultDictionary: Dictionary new!
----- Method: MetacelloMCProjectSpec>>loadedPackageNames: (in category 'accessing') -----
loadedPackageNames: aLoader
| vrsn pkgs |
(vrsn := self versionOrNil) == nil ifTrue: [ ^#() ].
pkgs := OrderedCollection new.
(self loadListForVersion: vrsn) do: [:nm |
(vrsn packagesForSpecNamed: nm ) do: [:pkg |
(pkg isPackageLoaded: aLoader) ifTrue: [ pkgs add: pkg name ]]].
^pkgs!
----- Method: MetacelloMCProjectSpec>>metacelloRegistrationHash (in category 'scripting') -----
metacelloRegistrationHash
"file"
^ String stringHash: self file initialHash: super metacelloRegistrationHash!
----- Method: MetacelloMCProjectSpec>>packageFileSpecFor: (in category 'accessing') -----
packageFileSpecFor: aMetacelloPackagesSpec
^(aMetacelloPackagesSpec project projectReferenceSpec)
name: self name;
projectReference: self copy;
yourself.!
----- Method: MetacelloMCProjectSpec>>projectClass (in category 'querying') -----
projectClass
self className == nil
ifTrue: [ ^ nil ].
^ Smalltalk at: self className asSymbol ifAbsent: [ ]!
----- Method: MetacelloMCProjectSpec>>projectClassProject (in category 'querying') -----
projectClassProject
"indirection needed when projectClass is _not_ a subclass of MetacelloProject"
^ self projectClass new project
setBaselineRepositoryDescription: self repositoryDescriptions;
yourself!
----- Method: MetacelloMCProjectSpec>>projectPackage (in category 'accessing') -----
projectPackage
projectPackage
ifNil: [
self className ifNil: [ ^ nil ].
projectPackage := self project packageSpec.
projectPackage name: self className.
self getFile ifNotNil: [ projectPackage file: self file ].
projectPackage repositories: self getRepositories ].
^ projectPackage!
----- Method: MetacelloMCProjectSpec>>relativeCurrentVersion (in category 'querying') -----
relativeCurrentVersion
"currentVersion calculated relative to the loadList"
| vrsn expanded loadList |
(vrsn := self versionOrNil) == nil
ifTrue: [ ^ nil ].
expanded := [ vrsn expandToLoadableSpecNames: (loadList := self loadListForVersion: vrsn) ]
on: Error
do: [ :ex |
vrsn blessing == #'development'
ifTrue: [
self ensureLoadUsing: self loader.
vrsn := self versionOrNil.
ex return: (vrsn expandToLoadableSpecNames: loadList) ].
ex pass ].
^ self projectClassProject currentVersionAgainst: expanded!
----- Method: MetacelloMCProjectSpec>>resolveToAllPackagesIn:visited: (in category 'private') -----
resolveToAllPackagesIn: aVersionSpec visited: visited
| vrsn |
visited
pushProject: [
visited
visit: self
doing: [ :spec |
spec ensureProjectLoaded.
vrsn := spec version.
^ vrsn
allPackagesForSpecNamed: (self loadListForVersion: vrsn)
ifAbsent: [ self error: 'invalid loads: spec' ] ] ].
^ #()!
----- Method: MetacelloMCProjectSpec>>updateForSpawnMethod: (in category 'development support') -----
updateForSpawnMethod: sourceSpec
"This means that this spec was used in a baseline and will be used in a version .... drop all information that isn't useful"
repositories := className := operator := loads := projectPackage := nil.
sourceSpec ~~ nil ifTrue: [ versionString := sourceSpec versionString ].!
----- Method: MetacelloMCProjectSpec>>updatePackageSpec: (in category 'development support') -----
updatePackageSpec: updatedSpecs
"Add project copy to updatedSpecs if the current version of the project
is different from the receiver's version"
| prj currentVersion spec |
className == nil
ifTrue: [ ^ self ].
prj := self projectClassProject.
(currentVersion := prj currentVersion) = self versionOrNil
ifTrue: [ ^ self ].
currentVersion == nil
ifTrue: [ ^ self ].
spec := self copy.
spec versionString: currentVersion versionString.
updatedSpecs at: spec name put: spec!
----- Method: MetacelloMCProjectSpec>>validateForScriptLoad:withDefaultVersionString:withDefaultRepositoryDecription: (in category 'scripting') -----
validateForScriptLoad: aScriptEngine withDefaultVersionString: defaultVersionString withDefaultRepositoryDecription: defaultRepositoryDecription
| issues callSite |
issues := OrderedCollection new.
callSite := #'validateForScriptLoad:withDefaultVersionString:withDefaultRepositoryDecription:'.
self name
ifNil: [
issues
add:
(MetacelloValidationError
configurationClass: self projectClass
reasonCode: #'incompleteProjectSpec'
callSite: callSite
explanation: 'name field required') ].
self className
ifNil: [
issues
add:
(MetacelloValidationError
configurationClass: self projectClass
reasonCode: #'incompleteProjectSpec'
callSite: callSite
explanation: 'className field required') ].
self repositories isEmpty
ifTrue: [
defaultRepositoryDecription
ifNotNil: [ self repository: defaultRepositoryDecription ]
ifNil: [
issues
add:
(MetacelloValidationError
configurationClass: self projectClass
reasonCode: #'incompleteProjectSpec'
callSite: callSite
explanation: 'repository field required') ] ].
self validateVersionString: issues withDefaultVersionString: defaultVersionString.
^ issues!
----- Method: MetacelloMCProjectSpec>>validateVersionString:withDefaultVersionString: (in category 'scripting') -----
validateVersionString: issues withDefaultVersionString: defaultVersionString
self versionString
ifNil: [
defaultVersionString
ifNotNil: [ self versionString: defaultVersionString ]
ifNil: [
issues
add:
(MetacelloValidationError
configurationClass: self projectClass
reasonCode: #'incompleteProjectSpec'
callSite:
#'validateForScriptLoad:withDefaultVersionString:withDefaultRepositoryDecription:'
explanation: 'version field required') ] ]!
----- Method: MetacelloMCProjectSpec>>version (in category 'querying') -----
version
"Empty version string means use latestVersion or #bleedingEdge"
self projectClass == nil
ifTrue: [ ^ nil ].
^ self versionString == nil
ifTrue: [
| vrsn |
"Eventually it will become an error to not specify a project reference version as default: #stable is the preferred default"
"self deprecated: 'Must specify a project reference version.'."
self flag: 'deprecate after version 1.0'.
(vrsn := self projectClassProject latestVersion) == nil
ifTrue: [ self projectClassProject version: #bleedingEdge ]
ifFalse: [ vrsn ] ]
ifFalse: [ self projectClassProject version: self versionString ]!
----- Method: MetacelloMCProjectSpec>>versionForScriptEngine: (in category 'scripting') -----
versionForScriptEngine: aMetacelloScriptEngine
| prj |
prj := self projectClass ifNil: [ self project ] ifNotNil: [ self projectClassProject ].
^ ((prj projectForScriptEngine: aMetacelloScriptEngine) version: self versionString)
silently: aMetacelloScriptEngine silently;
ignoreImage: aMetacelloScriptEngine ignoreImage;
cacheRepository: aMetacelloScriptEngine cacheRepository;
repositoryOverrides: aMetacelloScriptEngine repositoryOverrides!
----- Method: MetacelloMCProjectSpec>>workingCopy (in category 'accessing') -----
workingCopy
^ self projectPackage workingCopy!
----- Method: Collection>>addToMetacelloRepositories: (in category '*metacello-mc') -----
addToMetacelloRepositories: aMetacelloRepositoriesSpec
self do: [:each | each addToMetacelloRepositories: aMetacelloRepositoriesSpec ]!
----- Method: Collection>>fetchRequiredForMetacelloMCVersion: (in category '*metacello-mc') -----
fetchRequiredForMetacelloMCVersion: aMetacelloMCVersion
^aMetacelloMCVersion doFetchRequiredFromArray: self.!
----- Method: Collection>>loadRequiredForMetacelloMCVersion: (in category '*metacello-mc') -----
loadRequiredForMetacelloMCVersion: aMetacelloMCVersion
^aMetacelloMCVersion doLoadRequiredFromArray: self.!
----- Method: Collection>>mergeIntoMetacelloRepositories: (in category '*metacello-mc') -----
mergeIntoMetacelloRepositories: aMetacelloRepositoriesSpec
self do: [:each | each mergeIntoMetacelloRepositories: aMetacelloRepositoriesSpec ]!
----- Method: Collection>>recordRequiredForMetacelloMCVersion: (in category '*metacello-mc') -----
recordRequiredForMetacelloMCVersion: aMetacelloMCVersion
^aMetacelloMCVersion doRecordRequiredFromArray: self.!
----- Method: Collection>>removeFromMetacelloRepositories: (in category '*metacello-mc') -----
removeFromMetacelloRepositories: aMetacelloRepositoriesSpec
self do: [:each | each removeFromMetacelloRepositories: aMetacelloRepositoriesSpec ]!
----- Method: Collection>>resolvePackageSpecsNamedForMetacelloMCVersion:visited:ifAbsent: (in category '*metacello-mc') -----
resolvePackageSpecsNamedForMetacelloMCVersion: aMetacelloMCVersion visited: visited ifAbsent: aBlock
^ aMetacelloMCVersion
allPackagesForSpecs: (self collect: [ :ea | aMetacelloMCVersion packageNamed: ea ifAbsent: aBlock ])
visited: visited!
----- Method: Collection>>setLoadsInMetacelloProject: (in category '*metacello-mc') -----
setLoadsInMetacelloProject: aMetacelloPackageSpec
aMetacelloPackageSpec setLoads: self asArray.
!
MetacelloVersionValidator subclass: #MetacelloMCVersionValidator
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Validation'!
!MetacelloMCVersionValidator commentStamp: 'dkh 1/26/2012 09:49' prior: 0!
Performs configuration validation.
For programmatically decoding reason codes use:
MetacellMCVersionValidator fullDescriptionForReasonCode: <reasonCode>
Warning reason codes:
#notDevelopmentVersion - the symbolic version #development refers to a non-development literal version.
#loadWarning - Warning signalled during load [load validation].
#onlyBaselineVersion - one or more baseline versions have been defined, but no non-baseline versions are defined.
#stableDevelopmentVersion - a version whose blessing is #development has been declared as a #stable version
Critical Warning reason codes:
#duplicateVersionDefinitions - there are multiple pragma methods specifying the same version
#loadDeprecation - deprecation warning signalled while loading configuration [load validation]
#missingRecommendedProjectSpecField - missing recommended fields in project reference (versionString). The versionString should be specified so that #bleedingEdge loads will be predictable and repeatable
#noLoadableVersions - no non #baseline versions defined in configuration
#noTests - no test cases defined in loaded configuration [load validation]
#noVersionSpecified - no version defined for the project reference or package. The version specified in the baseline or the latest version of the project or package in the repository will be used.
#packageNameMismatch - the name in the packageSpec does not match the name of the mcz file
#projectClassNameFileMismatch - the class name of the configuration does not match the mcz file containing the configuration
#testDeprecation - deprecation warning signalled while running configuration tests [load validation]
Error reason codes:
#cannotResolveVersion - the version (project reference or symbolic version) was not found in the specified configuration
#duplicateNames - multiple independent definitions for an entity with same name (project, package, or group)
#incompleteProjectSpec - missing required fields in project reference (className and/or repository)
#incorrectVersionString - the version declared in pragma doesn't match version in versionSpec
#invalidDoItSelector - doit select must be a Symbol
#invalidVersionString - versionString must be a String
#loadError - error occured while loading configuration [load validation]
#missingVersionImport - version specified in import pragma not defined in configuration
#noVersionsDefined - no usable baseline or version defined in configuration ... configuration cannot be loaded
#projectCreationError - error occured while resolving project reference
#shadowedNames - name duplication between packages and projects
#testFailures - test failures while running tests [load validation]
#versionCompositionError - error while creating versionSpec from pragmas
!
----- Method: MetacelloMCVersionValidator class>>populateReasonCodeDescriptions (in category 'private') -----
populateReasonCodeDescriptions
"update MetacelloMCVersionValidator class comment to include any changes to descriptions"
| dict |
dict := super populateReasonCodeDescriptions.
dict
at: #'notDevelopmentVersion'
put: 'the symbolic version #development refers to a non-development literal version.';
at: #'loadWarning' put: 'Warning signalled during load [load validation].';
at: #'stableDevelopmentVersion'
put: 'a version whose blessing is #development has been declared as a #stable version.'. "Warnings"
dict
at: #'loadDeprecation' put: 'deprecation warning signalled while loading configuration [load validation].';
at: #'missingRecommendedProjectSpecField'
put:
'missing recommended fields in project reference (versionString). The versionString should be specified so that #bleedingEdge loads will be predictable and repeatable.';
at: #'noLoadableVersions' put: 'no non #baseline versions defined in configuration.';
at: #'noTests' put: 'no test cases defined in loaded configuration [load validation].';
at: #'noVersionSpecified'
put:
'no version defined for the project reference or package. The version specified in the baseline or the latest version of the project or package in the repository will be used.';
at: #'testDeprecation'
put: 'deprecation warning signalled while running configuration tests [load validation].'. "Critical Warnings"
dict
at: #'loadError' put: 'error occured while loading configuration [load validation].';
at: #'testFailures' put: 'test failures while running tests [load validation].'. "Errors"
^ dict!
----- Method: MetacelloMCVersionValidator class>>validateConfigurationLoad: (in category 'instance creation') -----
validateConfigurationLoad: configurationClass
^ ((self new)
configurationClass: configurationClass;
yourself) validateProjectLoad!
----- Method: MetacelloMCVersionValidator class>>validateConfigurationLoad:version: (in category 'instance creation') -----
validateConfigurationLoad: configurationClass version: versionString
^self validateConfigurationLoad: configurationClass version: versionString loads: #()!
----- Method: MetacelloMCVersionValidator class>>validateConfigurationLoad:version:loads: (in category 'instance creation') -----
validateConfigurationLoad: configurationClass version: versionString loads: loadList
^ ((self new)
configurationClass: configurationClass;
yourself) validateProjectVersionLoad: versionString loads: loadList!
----- Method: MetacelloMCVersionValidator>>criticalWarningReasonCodes (in category 'private') -----
criticalWarningReasonCodes
^ super criticalWarningReasonCodes
, #(#noLoadableVersions #noTests #testDeprecation #loadDeprecation #noVersionSpecified #'missingRecommendedProjectSpecField' )!
----- Method: MetacelloMCVersionValidator>>errorReasonCodes (in category 'private') -----
errorReasonCodes
^ super errorReasonCodes, #(#loadError #testFailures )!
----- Method: MetacelloMCVersionValidator>>validateBaselineVersionSpec: (in category 'validation') -----
validateBaselineVersionSpec: versionSpec
| projectNames packageNames groupNames versionMessage |
self
validateDoIts: versionSpec
versionString: versionSpec versionString
errorMessage: ' version ' , versionSpec versionString printString.
projectNames := Set new.
packageNames := Set new.
groupNames := Set new.
versionMessage := ' in version ' , versionSpec versionString printString.
versionSpec
projectDo: [ :projectSpec |
projectSpec resolveProjectSpec className == nil
ifTrue: [
self
recordValidationError:
'Missing required field (className:) for project reference ' , projectSpec name printString , ' in version '
, versionSpec versionString printString
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'incompleteProjectSpec' ].
projectSpec resolveProjectSpec versionString == nil
ifTrue: [
self
recordValidationCriticalWarning:
'Missing recommended field (versionString:) for project reference ' , projectSpec name printString , ' in version '
, versionSpec versionString printString
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'missingRecommendedProjectSpecField' ].
projectSpec hasRepository
ifTrue: [
(self recurse and: [ projectSpec versionString ~~ nil ])
ifTrue: [
| project |
projectSpec resolveProjectSpec ensureProjectLoaded.
project := self
validateProjectCreationFrom: projectSpec resolveProjectSpec projectClass
onError: [ :ex |
self
recordValidationError: 'Error creating project reference: ' , ex description
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'projectCreationError'.
nil ].
project ~~ nil
ifTrue: [
self validationReport
addAll:
(self class
validateProject: project
version: projectSpec versionString
debug: self debug
recurse: self recurse
visited: self visited) ] ] ]
ifFalse: [
self
recordValidationError:
'Missing required field (repository:) for project reference ' , projectSpec name printString , ' in version '
, versionSpec versionString printString
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'incompleteProjectSpec' ].
self
validateDoIts: projectSpec
versionString: versionSpec versionString
errorMessage: projectSpec name printString , versionMessage.
(projectNames includes: projectSpec name)
ifTrue: [
self
recordValidationError:
'Duplicate projects named' , projectSpec name printString , versionMessage
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'duplicateNames' ]
ifFalse: [ projectNames add: projectSpec name ] ]
packageDo: [ :packageSpec |
self
validateDoIts: packageSpec
versionString: versionSpec versionString
errorMessage: packageSpec name printString , versionMessage.
(packageNames includes: packageSpec name)
ifTrue: [
self
recordValidationError:
'Duplicate packages named' , packageSpec name printString , versionMessage
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'duplicateNames' ]
ifFalse: [ projectNames add: packageSpec name ] ]
groupDo: [ :groupSpec |
(groupNames includes: groupSpec name)
ifTrue: [
self
recordValidationError: 'Duplicate groups named' , groupSpec name printString , versionMessage
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'duplicateNames' ]
ifFalse: [ projectNames add: groupSpec name ] ].
(packageNames intersection: projectNames) notEmpty
ifTrue: [
self
recordValidationError: 'Names duplicated between packages and projects' , versionMessage
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'shadowedNames' ].
(groupNames intersection: projectNames) notEmpty
ifTrue: [
self
recordValidationError: 'Names duplicated between groups and projects' , versionMessage
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'shadowedNames' ].
(projectNames intersection: packageNames) notEmpty
ifTrue: [
self
recordValidationError: 'Names duplicated between projects and packages' , versionMessage
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'shadowedNames' ].
(groupNames intersection: packageNames) notEmpty
ifTrue: [
self
recordValidationError: 'Names duplicated between groups and packages' , versionMessage
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'shadowedNames' ].
(projectNames intersection: groupNames) notEmpty
ifTrue: [
self
recordValidationError: 'Names duplicated between projects and groups' , versionMessage
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'shadowedNames' ].
(packageNames intersection: groupNames) notEmpty
ifTrue: [
self
recordValidationError: 'Names duplicated between packages and groups' , versionMessage
versionString: versionSpec versionString
callSite: #'validateBaselineVersionSpec:'
reasonCode: #'shadowedNames' ]!
----- Method: MetacelloMCVersionValidator>>validateCleanLoadAndTestsForVersion:loads: (in category 'loading') -----
validateCleanLoadAndTestsForVersion: version loads: loadList
| cleanLoad cleanTests |
cleanTests := cleanLoad := false.
[
self validateVersionLoad: version loads: loadList.
cleanLoad := true ]
on: Error , Warning
do: [ :ex |
(ex isKindOf: Error)
ifTrue: [
self
recordValidationError:
'Error while loading version ' , version versionString printString , ' in ' , self configurationClass name asString
, ' ' , ex description
versionString: version versionString
callSite: #validateCleanLoadAndTestsForVersion:loads:
reasonCode: #loadError ].
(ex isKindOf: Warning)
ifTrue: [
(ex isKindOf: Deprecation)
ifTrue: [
self
recordValidationCriticalWarning:
'Deprecation while loading version ' , version versionString printString , ' in '
, self configurationClass name asString , ' ' , ex description
versionString: version versionString
callSite: #validateCleanLoadAndTestsForVersion:loads:
reasonCode: #loadDeprecation ]
ifFalse: [
self
recordValidationWarning:
'Warning while loading version ' , version versionString printString , ' in ' , self configurationClass name asString
, ' ' , ex description
versionString: version versionString
callSite: #validateCleanLoadAndTestsForVersion:loads:
reasonCode: #loadWarning.
Smalltalk
at: #UndeclaredVariableWarning
ifPresent: [ :undeclaredWrning |
(ex isKindOf: undeclaredWrning)
ifTrue: [ ex resume: true ] ].
ex resume ] ] ].
cleanLoad
ifTrue: [
cleanTests := [ self validateVersionTests: version ]
on: Deprecation
do: [ :ex |
| message |
message := 'Deprecation warning while running tests for version ' , version versionString printString , ' in '
, self configurationClass name asString , ' ' , ex description. "Deprecation warning for release tests is the same as a test failure"
self
recordValidationCriticalWarning: message
versionString: version versionString
callSite: #validateCleanLoadAndTestsForVersion:loads:
reasonCode: #testDeprecation.
ex return: false ].
cleanTests
ifTrue: [ MetacelloCleanLoadAndTestsNotification signal: version ]
ifFalse: [ MetacelloCleanLoadNotification signal: version ] ]!
----- Method: MetacelloMCVersionValidator>>validateProjectLoad (in category 'loading') -----
validateProjectLoad
| issues project versions currentVersion collectedIssues |
(issues := self validateProject select: [ :issue | issue isError ]) notEmpty
ifTrue: [ ^ issues ].
project := self configurationClass project.
collectedIssues := issues.
versions := project versions
select: [ :version |
validationReport := nil.
version blessing ~~ #broken
and: [
version blessing ~~ #baseline
and: [ (issues := (self validateProject: project version: version versionString) select: [ :issue | issue isCritical ]) isEmpty ] ] ].
validationReport := collectedIssues.
versions isEmpty
ifTrue: [
self
recordValidationCriticalWarning: 'No non #baseline versions available in ' , self configurationClass name asString
callSite: #validateProjectLoad
reasonCode: #noLoadableVersions.
^ self validationReport ].
(currentVersion := project currentVersion) ~~ nil
ifTrue: [
| index |
index := versions indexOf: currentVersion.
versions := versions copyFrom: index to: versions size ].
versions do: [ :version | self validateCleanLoadAndTestsForVersion: version loads: #('ALL') ].
^ self validationReport!
----- Method: MetacelloMCVersionValidator>>validateProjectVersionLoad:loads: (in category 'loading') -----
validateProjectVersionLoad: versionString loads: loadList
| issues project version |
(issues := (self validateProjectVersion: versionString) select: [ :issue | issue isError ]) notEmpty
ifTrue: [ ^ issues ].
project := self configurationClass project.
version := project
version: versionString
ifAbsent: [
self
recordValidationError: 'Version ' , versionString printString , ' does not exist.'
callSite: #validateProjectVersionLoad:loads:
reasonCode: #cannotResolveVersion.
^ self validationReport ].
version blessing = #broken
ifTrue: [ self error: 'The specified version is #broken' ].
self validateCleanLoadAndTestsForVersion: version loads: loadList.
^ self validationReport
!
----- Method: MetacelloMCVersionValidator>>validateVersionLoad:loads: (in category 'loading') -----
validateVersionLoad: version loads: loadList
| list |
list := loadList asOrderedCollection.
list isEmpty
ifTrue: [ list add: 'default' ].
(version groups includes: 'Tests')
ifTrue: [ list add: 'Tests' ].
version load: list!
----- Method: MetacelloMCVersionValidator>>validateVersionSpec: (in category 'private') -----
validateVersionSpec: versionSpec
versionSpec blessing value == #'broken'
ifTrue: [ ^ self ].
versionSpec
projectDo: [ :projectSpec |
| referencedProjectSpec |
projectSpec versionString == nil
ifTrue: [
self
recordValidationCriticalWarning:
'No version specified for the project reference ' , projectSpec name printString
, ' in version ' , versionSpec versionString printString
versionString: versionSpec versionString
callSite: #'validateVersionSpec:'
reasonCode: #'noVersionSpecified' ].
referencedProjectSpec := projectSpec referencedSpec.
versionSpec blessing value == #'baseline'
ifTrue: [
referencedProjectSpec hasRepository
ifTrue: [
(referencedProjectSpec file beginsWith: referencedProjectSpec className)
ifFalse: [
self
recordValidationCriticalWarning:
'The class name of project ' , referencedProjectSpec className printString
, ' does not match the file name '
, referencedProjectSpec file printString
, ' in version ' , versionSpec versionString printString
versionString: versionSpec versionString
callSite: #'validateVersionSpec:'
reasonCode: #'projectClassNameFileMismatch' ] ]
ifFalse: [
self
recordValidationError:
'The specification for the project reference ' , projectSpec name printString
, ' in version ' , versionSpec versionString printString
, ' is missing the required repository field'
versionString: versionSpec versionString
callSite: #'validateVersionSpec:'
reasonCode: #'incompleteProjectSpec' ] ].
referencedProjectSpec ensureProjectLoaded
ifTrue: [
[ projectSpec version ]
on: MetacelloVersionDoesNotExistError
do: [ :ex |
| explanation |
explanation := projectSpec versionString == nil
ifTrue: [ 'the default version' ]
ifFalse: [ 'version ' , projectSpec versionString printString ].
self
recordValidationError:
'Cannot resolve ' , explanation , ' for the project reference '
, projectSpec name printString , ' in version '
, versionSpec versionString printString
versionString: versionSpec versionString
callSite: #'validateVersionSpec:'
reasonCode: #'cannotResolveVersion' ] ] ]
packageDo: [ :packageSpec |
(packageSpec file beginsWith: packageSpec name)
ifFalse: [
self
recordValidationCriticalWarning:
'The name of package ' , packageSpec name printString
, ' does not match the file name '
, packageSpec file printString , ' in version '
, versionSpec versionString printString
versionString: versionSpec versionString
callSite: #'validateVersionSpec:'
reasonCode: #'packageNameMismatch' ].
packageSpec file = packageSpec name
ifTrue: [
self
recordValidationCriticalWarning:
'No version specified for the package ' , packageSpec name printString
, ' in version ' , versionSpec versionString printString
versionString: versionSpec versionString
callSite: #'validateVersionSpec:'
reasonCode: #'noVersionSpecified' ] ]
groupDo: [ :ignored | ].
self validateBaselineVersionSpec: versionSpec!
----- Method: MetacelloMCVersionValidator>>validateVersionSpecForSymbolicVersion:symbolicVersion: (in category 'private') -----
validateVersionSpecForSymbolicVersion: versionSpec symbolicVersion: symbolicVersionString
| blessing |
versionSpec blessing value == #broken
ifTrue: [ ^ self ].
blessing := versionSpec blessing value.
(symbolicVersionString == #development and: [ blessing ~~ #development ])
ifTrue: [
self
recordValidationWarning:
'Symbolic version ' , symbolicVersionString printString , ' refers to a version' , versionSpec versionString printString
, ' whose blessing ' , blessing printString , ' is not #development'
versionString: versionSpec versionString
callSite: #validateVersionSpecForSymbolicVersion:symbolicVersion:
reasonCode: #notDevelopmentVersion ]!
----- Method: MetacelloMCVersionValidator>>validateVersionTests: (in category 'loading') -----
validateVersionTests: version
| testCases cleanTests |
testCases := IdentitySet new.
cleanTests := true.
version currentlyLoadedClassesInVersion
do: [ :class |
((class inheritsFrom: TestCase) and: [ class isAbstract not ])
ifTrue: [ testCases add: class ] ].
testCases
do: [ :testCase |
| testResults |
testResults := testCase suite run.
testResults defects notEmpty
ifTrue: [
self
recordValidationError:
'Test failures in tests ' , testCase name asString , ' for ' , version versionString printString , ' in '
, self configurationClass name asString , ' ' , testResults printString
versionString: version versionString
callSite: #validateVersionTests:
reasonCode: #testFailures.
cleanTests := false ] ].
testCases isEmpty
ifTrue: [
self
recordValidationCriticalWarning:
'No test cases for ' , version versionString printString , ' in ' , self configurationClass name asString
versionString: version versionString
callSite: #validateVersionTests:
reasonCode: #noTests.
cleanTests := false ].
^ cleanTests!
----- Method: MetacelloMCVersionValidator>>warningReasonCodes (in category 'private') -----
warningReasonCodes
^ super warningReasonCodes, #(#loadWarning #notDevelopmentVersion #stableDevelopmentVersion)!
Object subclass: #MetacelloConfigTemplate
instanceVariableNames: 'project'
classVariableNames: 'LastVersionLoad'
poolDictionaries: ''
category: 'Metacello-MC-Model'!
!MetacelloConfigTemplate commentStamp: '<historical>' prior: 0!
Copy me to create a new configuration or edit and evaluate the following doits.
"Create configuration class and initial baseline method"
MetacelloToolBox
createBaseline: '1.0-baseline'
for: 'MyProject'
repository: 'http://www.example.com/MyProjectRepository'
requiredProjects: #('Gofer')
packages: #('MyProject-Core' 'MyProject-Tests')
dependencies:
{('MyProject-Core' -> #('Gofer')).
('MyProject-Tests' -> #('MyProject-Core'))}
groups:
{('default' -> #('Core')).
('Core' -> #('MyProject-Core')).
('Tests' -> #('MyProject-Tests'))}.
"create initial development method from the baseline"
MetacelloToolBox
createDevelopment: '1.0'
for: 'MyProject'
importFromBaseline: '1.0-baseline'
description: 'initial version'.
!
----- Method: MetacelloConfigTemplate class>>DevelopmentSupport (in category 'development support') -----
DevelopmentSupport
"See the methods in the 'development support' category on the class-side of MetacelloBaseConfiguration. Decide what development support methods you would like to use and copy them the the class-side of your configuration."
<apiDocumentation>!
----- Method: MetacelloConfigTemplate class>>baseConfigurationClassIfAbsent: (in category 'private') -----
baseConfigurationClassIfAbsent: aBlock
^Smalltalk
at: #'ConfigurationOf'
ifAbsent: [
self ensureMetacelloBaseConfiguration.
Smalltalk at: #'ConfigurationOf' ifAbsent: aBlock ].!
----- Method: MetacelloConfigTemplate class>>ensureMetacello (in category 'private') -----
ensureMetacello
(self baseConfigurationClassIfAbsent: []) ensureMetacello!
----- Method: MetacelloConfigTemplate class>>ensureMetacelloBaseConfiguration (in category 'private') -----
ensureMetacelloBaseConfiguration
Smalltalk
at: #'ConfigurationOf'
ifAbsent: [
| repository version |
repository := MCHttpRepository
location: 'http://smalltalkhub.com/mc/dkh/metacello/main'
user: ''
password: ''.
repository
versionReaderForFileNamed: 'Metacello-Base-dkh.107'
do: [ :reader |
version := reader version.
version load.
version workingCopy repositoryGroup addRepository: repository ] ]!
----- Method: MetacelloConfigTemplate class>>isMetacelloConfig (in category 'metacello tool support') -----
isMetacelloConfig
"Answer true and the Metacello tools will operate on you"
^true!
----- Method: MetacelloConfigTemplate class>>load (in category 'loading') -----
load
"Load the #stable version defined for this platform. The #stable version is the version that is recommended to be used on this platform."
"self load"
<apiDocumentation>
^(self project version: #stable) load!
----- Method: MetacelloConfigTemplate class>>loadBleedingEdge (in category 'loading') -----
loadBleedingEdge
"Load the latest versions of the mcz files defined for this project. It is not likely that the #bleedingEdge has been tested."
"self loadBleedingEdge"
<apiDocumentation>
^(self project version: #bleedingEdge) load!
----- Method: MetacelloConfigTemplate class>>loadDevelopment (in category 'loading') -----
loadDevelopment
"Load the #development version defined for this platform. The #development version will change over time and is not expected to be stable."
"self loadDevelopment"
<apiDocumentation>
^(self project version: #development) load!
----- Method: MetacelloConfigTemplate class>>project (in category 'accessing') -----
project
^self new project!
----- Method: MetacelloConfigTemplate class>>validate (in category 'development support') -----
validate
"Check the configuration for Errors, Critical Warnings, and Warnings (see class comment for MetacelloMCVersionValidator for more information).
Errors identify specification issues that will result in unexpected behaviour when you load the configuration.
Critical Warnings identify specification issues that may result in unexpected behavior when you load the configuration.
Warnings identify specification issues that are technically correct, but are worth take a look at."
"self validate"
<apiDocumentation>
self ensureMetacello.
^ ((Smalltalk at: #MetacelloToolBox) validateConfiguration: self debug: #() recurse: false) explore!
----- Method: MetacelloConfigTemplate>>customProjectAttributes (in category 'accessing') -----
customProjectAttributes
"Edit to return a collection of any custom attributes e.g. for conditional loading: Array with: #'Condition1' with: #'Condition2.
For more information see: http://code.google.com/p/metacello/wiki/CustomProjectAttrributes "
^ #()!
----- Method: MetacelloConfigTemplate>>project (in category 'accessing') -----
project
^ project
ifNil: [
"Bootstrap Metacello if it is not already loaded"
self class ensureMetacello.
project := MetacelloMCProject new projectAttributes: self customProjectAttributes. "Create the Metacello project"
(Smalltalk at: #'MetacelloVersionConstructor') on: self project: project. "Construct the project"
project loadType: #'linear'. "change to #atomic if desired"
project ]!
Object subclass: #MetacelloConfigTemplateExample
instanceVariableNames: 'project'
classVariableNames: 'LastVersionLoad'
poolDictionaries: ''
category: 'Metacello-MC-Model'!
!MetacelloConfigTemplateExample commentStamp: '<historical>' prior: 0!
Copy me to create a new configuration or edit and evaluate the following doits.
"Create configuration class and initial baseline method"
MetacelloToolBox
createBaseline: '1.0-baseline'
for: 'MyProject'
repository: 'http://www.example.com/MyProjectRepository'
requiredProjects: #('Gofer')
packages: #('MyProject-Core' 'MyProject-Tests')
dependencies:
{('MyProject-Core' -> #('Gofer')).
('MyProject-Tests' -> #('MyProject-Core'))}
groups:
{('default' -> #('Core')).
('Core' -> #('MyProject-Core')).
('Tests' -> #('MyProject-Tests'))}.
"create initial development method from the baseline"
MetacelloToolBox
createDevelopment: '1.0'
for: 'MyProject'
importFromBaseline: '1.0-baseline'
description: 'initial version'.
!
----- Method: MetacelloConfigTemplateExample class>>DevelopmentSupport (in category 'development support') -----
DevelopmentSupport
"See the methods in the 'development support' category on the class-side of MetacelloBaseConfiguration. Decide what development support methods you would like to use and copy them the the class-side of your configuration."
<apiDocumentation>!
----- Method: MetacelloConfigTemplateExample class>>baseConfigurationClassIfAbsent: (in category 'private') -----
baseConfigurationClassIfAbsent: aBlock
^Smalltalk
at: #MetacelloBaseConfiguration
ifAbsent: [
self ensureMetacelloBaseConfiguration.
Smalltalk at: #MetacelloBaseConfiguration ifAbsent: aBlock ].!
----- Method: MetacelloConfigTemplateExample class>>ensureMetacello (in category 'private') -----
ensureMetacello
(self baseConfigurationClassIfAbsent: []) ensureMetacello!
----- Method: MetacelloConfigTemplateExample class>>ensureMetacelloBaseConfiguration (in category 'private') -----
ensureMetacelloBaseConfiguration
Smalltalk
at: #MetacelloBaseConfiguration
ifAbsent: [
| repository version |
repository := MCHttpRepository location: 'http://seaside.gemstone.com/ss/metacello' user: '' password: ''.
repository
versionReaderForFileNamed: 'Metacello-Base-DaleHenrichs.2.mcz'
do: [ :reader |
version := reader version.
version load.
version workingCopy repositoryGroup addRepository: repository ] ]!
----- Method: MetacelloConfigTemplateExample class>>isMetacelloConfig (in category 'metacello tool support') -----
isMetacelloConfig
"Answer true and the Metacello tools will operate on you"
^true!
----- Method: MetacelloConfigTemplateExample class>>load (in category 'loading') -----
load
"Load the #stable version defined for this platform. The #stable version is the version that is recommended to be used on this platform."
"self load"
<apiDocumentation>
^(self project version: #stable) load!
----- Method: MetacelloConfigTemplateExample class>>loadBleedingEdge (in category 'loading') -----
loadBleedingEdge
"Load the latest versions of the mcz files defined for this project. It is not likely that the #bleedingEdge has been tested."
"self loadBleedingEdge"
<apiDocumentation>
^(self project version: #bleedingEdge) load!
----- Method: MetacelloConfigTemplateExample class>>loadDevelopment (in category 'loading') -----
loadDevelopment
"Load the #development version defined for this platform. The #development version will change over time and is not expected to be stable."
"self loadDevelopment"
<apiDocumentation>
^(self project version: #development) load!
----- Method: MetacelloConfigTemplateExample class>>project (in category 'accessing') -----
project
^self new project!
----- Method: MetacelloConfigTemplateExample class>>validate (in category 'development support') -----
validate
"Check the configuration for Errors, Critical Warnings, and Warnings (see class comment for MetacelloMCVersionValidator for more information).
Errors identify specification issues that will result in unexpected behaviour when you load the configuration.
Critical Warnings identify specification issues that may result in unexpected behavior when you load the configuration.
Warnings identify specification issues that are technically correct, but are worth take a look at."
"self validate"
<apiDocumentation>
self ensureMetacello.
^ ((Smalltalk at: #MetacelloToolBox) validateConfiguration: self debug: #() recurse: false) explore!
----- Method: MetacelloConfigTemplateExample>>baseline10: (in category 'baselines') -----
baseline10: spec
"Baselines are used by convention in Metacello and essentially are nothing else than normal versions.
Name the baseline after the first version it was introduced.
In this case 1.0-baseline was introduced the first time with the 1.0 version defined in the #version10 method.
Metacello only uses the following tag to figure out the name of this baseline:"
<version: '1.0-baseline'>
"Using #common makes this dependency declaration available for all Smalltalks.
If you need more fine-grained control you can add several #for:do: sections for other releases."
spec for: #common do: [
spec blessing: #baseline.
"specify the default repository for your project's packages"
spec repository: 'http://smalltalkhub.com/mc/JohnDoe/MyProject/main'.
"use separate methods for external projects"
self
fuelMetalevel: spec;
fileSystemLegacy: spec.
"specify the dependencies between packages and projects"
spec
"a package without dependencies:"
package: 'MyProject-Core';
package: 'MyProject-Tests' with: [
"Specfiy dependencies using the #requires: directive, you can refer to any name here, in this case to an external project"
spec requires: #('MyProject-Core' 'FuelMetalevel' 'FileSystemLegacy')].
"using groups certain packages and projects can be loaded conditionally"
spec
"load the tests by default"
group: 'default' with: #('core' 'test');
group: 'test' with: #('MyProject-Tests');
group: 'core' with: #('MyProject-Core')]!
----- Method: MetacelloConfigTemplateExample>>customProjectAttributes (in category 'accessing') -----
customProjectAttributes
"Edit to return a collection of any custom attributes e.g. for conditional loading: Array with: #'Condition1' with: #'Condition2.
For more information see: http://code.google.com/p/metacello/wiki/CustomProjectAttrributes"
^ #().!
----- Method: MetacelloConfigTemplateExample>>development: (in category 'tags') -----
development: spec
"By convention the development branch should point to a fixed version that is regularly updated and might contain unstable code.
The name used by Metacello is only defined by the following pragma:"
<symbolicVersion: #development >
"For the development tag refer to a fixed version which you update if you commit new code.
Note that you can refer here to any other version name from this configuration"
spec for: #'common' version: 'dev'.!
----- Method: MetacelloConfigTemplateExample>>fileSystemLegacy: (in category 'external projects') -----
fileSystemLegacy: spec
"This is an example of an external project which does not have a configuration yet.
Note that the package name is only used in the Metacello configuration and does not have be exactly the same as the Monticello project/version name."
spec package: 'FileSystemLegacy' with: [
spec
repository: 'http://smalltalkhub.com/mc/PharoExtras/FileSystemLegacy/main';
"if you do not specify a version, automatically the newest version is chose."
file: 'FileSystem-Legacy-JohanBrichau.2' ]!
----- Method: MetacelloConfigTemplateExample>>fuelMetalevel: (in category 'external projects') -----
fuelMetalevel: spec
"Specify a dependency on an external project which has it's own configuration.
The given project name can be chosen freely, for simplicity use the same name as the configuration or the conditional group you load."
spec project: 'FuelMetalevel' with: [
spec
repository: 'http://ss3.gemstone.com/ss/Fuel';
className: 'ConfigurationOfFuel';
"if you want to load by default a special group usse the #loads: message plus a group name of the external configuration"
loads: #FuelMetalevel ].!
----- Method: MetacelloConfigTemplateExample>>project (in category 'accessing') -----
project
^ project ifNil: [
"Bootstrap Metacello if it is not already loaded"
(self class baseConfigurationClassIfAbsent: []) ensureMetacello.
"Construct Metacello project"
project := MetacelloMCProject new projectAttributes: self customProjectAttributes.
(Smalltalk at: #MetacelloVersionConstructor) on: self project: project.
project loadType: #linear. "change to #atomic if desired"
project ]!
----- Method: MetacelloConfigTemplateExample>>stable: (in category 'tags') -----
stable: spec
"Symbolic versions can be used to introduce an indirection to a version number.
The real name used by Metacello is only defined by the following pragma:"
<symbolicVersion: #stable >
"If another version is stable for a differen Smalltalk use a specific name"
"spec for: #'pharo1.4.x' version: '0.9'"
"Specfiy which exact version you want to load"
spec for: #'common' version: '1.0'.!
----- Method: MetacelloConfigTemplateExample>>version10: (in category 'versions') -----
version10: spec
"The name for this version is solely defined by the following pragma:"
<version: '1.0' imports: #('1.0-baseline') >
"Baselines are used to define more complex setups for your project.
If you want to use external projects and have fine-graind control of the dependencies between packages use the #imports: part.
See the #baseline10: for more details."
"Using #for:do: with the #common release specifier the following version declaration is valid for all platforms."
spec for: #common do: [
spec
description: 'Version 1.0 the current stable release';
blessing: #release;
author: 'John Doe';
timestamp: '2013-05-01'.
"Specify the versions for each package and external project defined in the baseline, here the 1.0-baseline defined in the baseline10 method."
spec
"For standard Monticello packages simply refere to the full version name without the extension:"
package: 'MyProject-Core' with: 'MyProject-Core-JohnDoe.52';
package: 'MyProject-Tests' with: 'MyProject-Tests-JohnDoe.73';
"External projects versions are specified using #project:with:.
Note the project name referes to the name used in the Metacello declaration.
FuelMetalevel is defined in the #fuelMetalevel: method."
project: 'FuelMetalevel' with: #stable ].
"If you want to specify different version on other platforms add another #for:do: block with a different version identifier."!
----- Method: MetacelloConfigTemplateExample>>versionDevelopment: (in category 'versions') -----
versionDevelopment: spec
"version specification for the current development branch, see #version10 for a complete explanation of a version declaration.
In this case the 'dev' version uses the same baselin as version '1.0':"
<version: 'dev' imports: #('1.0-baseline') >
"Update this configuration regulrarly with intermediate releases.
If a version is more stable or should stay accessible copy this 'dev' definition and give it a proper version name on its own.
For example, in this case you might want to split a new version '1.1' by copying over this definition."
spec for: #common do: [
spec
description: 'Development Version';
blessing: #development;
author: 'John Doe';
timestamp: '2013-05-09'.
spec
package: 'MyProject-Core' with: 'MyProject-Core-JohnDoe.152';
package: 'MyProject-Tests' with: 'MyProject-Tests-JohnDoe.173';
"note that for the 'dev' version we rely on the #development version of the external FuleMetalevel project"
project: 'FuelMetalevel' with: #development ].!
Object subclass: #MetacelloDirective
instanceVariableNames: 'spec loader'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Directives'!
----- Method: MetacelloDirective class>>loadPackage:externalReference:loader: (in category 'instance creation') -----
loadPackage: aPackageSpec externalReference: externalReference loader: aLoader
^MetacelloPackageLoadDirective new
spec: aPackageSpec externalReference: externalReference loader: aLoader!
----- Method: MetacelloDirective class>>loader: (in category 'instance creation') -----
loader: aLoader
^self new
loader: aLoader!
----- Method: MetacelloDirective class>>postLoadSpec:loader: (in category 'instance creation') -----
postLoadSpec: packageOrVersionSpec loader: aLoader
^MetacelloPostLoadDirective new
spec: packageOrVersionSpec loader: aLoader!
----- Method: MetacelloDirective class>>preLoadSpec:loader: (in category 'instance creation') -----
preLoadSpec: packageOrVersionSpec loader: aLoader
^MetacelloPreLoadDirective new
spec: packageOrVersionSpec loader: aLoader!
----- Method: MetacelloDirective>>addTo: (in category 'actions') -----
addTo: aLoaderDirective
aLoaderDirective add: self!
----- Method: MetacelloDirective>>directivesDo: (in category 'enumerating') -----
directivesDo: aBlock
aBlock value: self!
----- Method: MetacelloDirective>>label (in category 'printing') -----
label
^self spec label!
----- Method: MetacelloDirective>>loadUsing:gofer: (in category 'actions') -----
loadUsing: aLoaderDirective gofer: aGofer
self subclassResponsibility!
----- Method: MetacelloDirective>>loader (in category 'accessing') -----
loader
^loader!
----- Method: MetacelloDirective>>loader: (in category 'accessing') -----
loader: aLoader
loader := aLoader!
----- Method: MetacelloDirective>>packageDirectivesDo: (in category 'enumerating') -----
packageDirectivesDo: aBlock!
----- Method: MetacelloDirective>>packageDo: (in category 'actions') -----
packageDo: aBlock!
----- Method: MetacelloDirective>>postLoadDo: (in category 'actions') -----
postLoadDo: aBlock!
----- Method: MetacelloDirective>>preLoadDo: (in category 'actions') -----
preLoadDo: aBlock!
----- Method: MetacelloDirective>>prepostLoadDirectivesDo: (in category 'enumerating') -----
prepostLoadDirectivesDo: aBlock!
----- Method: MetacelloDirective>>prepostLoadDo: (in category 'enumerating') -----
prepostLoadDo: aBlock!
----- Method: MetacelloDirective>>printOn: (in category 'printing') -----
printOn: aStream
self printOn: aStream indent: 0!
----- Method: MetacelloDirective>>printOn:indent: (in category 'printing') -----
printOn: aStream indent: indent
indent timesRepeat: [ aStream tab ].
aStream
nextPutAll: self title;
nextPutAll: ' : ';
nextPutAll: self label.!
----- Method: MetacelloDirective>>printString (in category 'printing') -----
printString
"Explicit override of superclass implementation. When you are printing a loadDirective it is annoying to have it truncated."
^String streamContents: [:s | self printOn: s]!
----- Method: MetacelloDirective>>spec (in category 'accessing') -----
spec
^spec!
----- Method: MetacelloDirective>>spec:loader: (in category 'initialize-release') -----
spec: packageOrVersionSpec loader: aLoader
spec := packageOrVersionSpec.
loader := aLoader!
----- Method: MetacelloDirective>>title (in category 'accessing') -----
title
self subclassResponsibility!
----- Method: MetacelloDirective>>versionDirectivesDepthFirstDo: (in category 'enumerating') -----
versionDirectivesDepthFirstDo: aBlock!
----- Method: MetacelloDirective>>versionDirectivesDo: (in category 'enumerating') -----
versionDirectivesDo: aBlock!
----- Method: MetacelloDirective>>versionDo: (in category 'actions') -----
versionDo: aBlock!
MetacelloDirective subclass: #MetacelloPackageLoadDirective
instanceVariableNames: 'resolvedReference externalReference'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Directives'!
----- Method: MetacelloPackageLoadDirective>>externalReference (in category 'accessing') -----
externalReference
^ externalReference!
----- Method: MetacelloPackageLoadDirective>>file (in category 'accessing') -----
file
^self externalReference name!
----- Method: MetacelloPackageLoadDirective>>label (in category 'printing') -----
label
^self file!
----- Method: MetacelloPackageLoadDirective>>loadUsing:gofer: (in category 'actions') -----
loadUsing: aLoaderDirective gofer: aGofer
aLoaderDirective loadPackageDirective: self gofer: aGofer!
----- Method: MetacelloPackageLoadDirective>>packageDirectivesDo: (in category 'enumerating') -----
packageDirectivesDo: aBlock
aBlock value: self!
----- Method: MetacelloPackageLoadDirective>>packageDo: (in category 'enumerating') -----
packageDo: aBlock
aBlock value: self!
----- Method: MetacelloPackageLoadDirective>>packageName (in category 'accessing') -----
packageName
^self externalReference packageName!
----- Method: MetacelloPackageLoadDirective>>repository (in category 'accessing') -----
repository
^self externalReference repository!
----- Method: MetacelloPackageLoadDirective>>resolvedReference (in category 'accessing') -----
resolvedReference
^ resolvedReference!
----- Method: MetacelloPackageLoadDirective>>resolvedReference: (in category 'accessing') -----
resolvedReference: anObject
resolvedReference := anObject!
----- Method: MetacelloPackageLoadDirective>>spec:externalReference:loader: (in category 'initialize-release') -----
spec: aPackageSpec externalReference: anExternalReference loader: aLoader
super spec: aPackageSpec loader: aLoader.
externalReference := anExternalReference!
----- Method: MetacelloPackageLoadDirective>>title (in category 'accessing') -----
title
^'load'!
MetacelloDirective subclass: #MetacelloPrePostLoadDirective
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Directives'!
MetacelloPrePostLoadDirective subclass: #MetacelloPostLoadDirective
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Directives'!
----- Method: MetacelloPostLoadDirective>>addTo: (in category 'actions') -----
addTo: aLoaderDirective
spec postLoadDoIt value ~~ nil ifTrue: [ aLoaderDirective add: self ]!
----- Method: MetacelloPostLoadDirective>>label (in category 'printing') -----
label
^super label, ' >> ', self spec postLoadDoIt value asString!
----- Method: MetacelloPostLoadDirective>>loadUsing:gofer: (in category 'actions') -----
loadUsing: aLoaderDirective gofer: aGofer
aLoaderDirective loadPostloadDirective: self.!
----- Method: MetacelloPostLoadDirective>>postLoadDo: (in category 'actions') -----
postLoadDo: aBlock
aBlock value: self!
----- Method: MetacelloPostLoadDirective>>title (in category 'accessing') -----
title
^'postload'!
MetacelloPrePostLoadDirective subclass: #MetacelloPreLoadDirective
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Directives'!
----- Method: MetacelloPreLoadDirective>>addTo: (in category 'actions') -----
addTo: aLoaderDirective
spec preLoadDoIt value ~~ nil ifTrue: [ aLoaderDirective add: self ]!
----- Method: MetacelloPreLoadDirective>>label (in category 'printing') -----
label
^super label, ' >> ', self spec preLoadDoIt value asString!
----- Method: MetacelloPreLoadDirective>>loadUsing:gofer: (in category 'actions') -----
loadUsing: aLoaderDirective gofer: aGofer
aLoaderDirective loadPreloadDirective: self.!
----- Method: MetacelloPreLoadDirective>>preLoadDo: (in category 'actions') -----
preLoadDo: aBlock
aBlock value: self!
----- Method: MetacelloPreLoadDirective>>title (in category 'accessing') -----
title
^'preload'!
----- Method: MetacelloPrePostLoadDirective>>evaluateSupplyingAnswers: (in category 'actions') -----
evaluateSupplyingAnswers: loadBlock
| answers |
(answers := self spec answers) notEmpty
ifTrue: [ loadBlock valueSupplyingMetacelloAnswers: answers ]
ifFalse: [ loadBlock value]!
----- Method: MetacelloPrePostLoadDirective>>prepostLoadDirectivesDo: (in category 'enumerating') -----
prepostLoadDirectivesDo: aBlock
aBlock value: self!
----- Method: MetacelloPrePostLoadDirective>>prepostLoadDo: (in category 'enumerating') -----
prepostLoadDo: aBlock
aBlock value: self!
MetacelloDirective subclass: #MetacelloVersionLoadDirective
instanceVariableNames: 'loadDirectives'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Directives'!
MetacelloVersionLoadDirective subclass: #MetacelloAtomicLoadDirective
instanceVariableNames: 'packageloads preloads postloads'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Directives'!
----- Method: MetacelloAtomicLoadDirective>>directivesDo: (in category 'enumerating') -----
directivesDo: aBlock
aBlock value: self.
self preloads do: [:directive | directive directivesDo: aBlock ].
self loadDirectives do: [:directive | directive directivesDo: aBlock ].
self postloads do: [:directive | directive directivesDo: aBlock ].!
----- Method: MetacelloAtomicLoadDirective>>finalizeLoad: (in category 'actions') -----
finalizeLoad: aGofer
"load the accumulated packages (if any), reset the package list"
| pkgLoads |
self preloads do: [:directive | super loadPreloadDirective: directive ].
preloads := nil.
(pkgLoads := self packageloads) notEmpty
ifTrue: [
self loader loadingSpecLoader
loadPackageDirectives: pkgLoads
gofer: aGofer.
self packageloads: nil ].
self postloads do: [:directive | super loadPostloadDirective: directive ].
postloads := nil!
----- Method: MetacelloAtomicLoadDirective>>loadAtomicLoadDirective:gofer: (in category 'actions') -----
loadAtomicLoadDirective: aLoaderDirective gofer: aGofer
aLoaderDirective loadDirectives do: [:directive | directive loadUsing: self gofer: aGofer ].!
----- Method: MetacelloAtomicLoadDirective>>loadLinearLoadDirective:gofer: (in category 'actions') -----
loadLinearLoadDirective: aLoaderDirective gofer: aGofer
self finalizeLoad: aGofer.
super loadLinearLoadDirective: aLoaderDirective gofer: aGofer!
----- Method: MetacelloAtomicLoadDirective>>loadPackageDirective:gofer: (in category 'loading') -----
loadPackageDirective: aPackageLoadDirective gofer: aGofer
"accumulate packages"
self packageloads add: aPackageLoadDirective!
----- Method: MetacelloAtomicLoadDirective>>loadPostloadDirective: (in category 'loading') -----
loadPostloadDirective: aPostloadDirective
"accumulate postloads"
self postloads add: aPostloadDirective!
----- Method: MetacelloAtomicLoadDirective>>loadPreloadDirective: (in category 'loading') -----
loadPreloadDirective: aPreloadDirective
"accumulate preloads"
self preloads add: aPreloadDirective!
----- Method: MetacelloAtomicLoadDirective>>loadUsing:gofer: (in category 'actions') -----
loadUsing: aLoaderDirective gofer: aGofer
self loadDirectives isEmpty ifTrue: [ ^self ].
aLoaderDirective loadAtomicLoadDirective: self gofer: aGofer.!
----- Method: MetacelloAtomicLoadDirective>>packageloads (in category 'accessing') -----
packageloads
packageloads == nil ifTrue: [ packageloads := OrderedCollection new ].
^ packageloads!
----- Method: MetacelloAtomicLoadDirective>>packageloads: (in category 'accessing') -----
packageloads: anObject
packageloads := anObject!
----- Method: MetacelloAtomicLoadDirective>>postloads (in category 'accessing') -----
postloads
postloads == nil ifTrue: [ postloads := OrderedCollection new ].
^ postloads!
----- Method: MetacelloAtomicLoadDirective>>preloads (in category 'accessing') -----
preloads
preloads == nil ifTrue: [ preloads := OrderedCollection new ].
^ preloads!
----- Method: MetacelloAtomicLoadDirective>>prepostLoadDirectivesDo: (in category 'enumerating') -----
prepostLoadDirectivesDo: aBlock
self preloads do: [:directive | directive prepostLoadDirectivesDo: aBlock ].
self loadDirectives do: [:directive | directive prepostLoadDirectivesDo: aBlock ].
self postloads do: [:directive | directive prepostLoadDirectivesDo: aBlock ].!
----- Method: MetacelloAtomicLoadDirective>>prepostLoadsDo: (in category 'enumerating') -----
prepostLoadsDo: aBlock
self preloads do: [:directive | directive prepostLoadDo: aBlock ].
self loadDirectives do: [:directive | directive prepostLoadDo: aBlock ].
self postloads do: [:directive | directive prepostLoadDo: aBlock ].!
----- Method: MetacelloAtomicLoadDirective>>title (in category 'accessing') -----
title
^'atomic load'!
MetacelloVersionLoadDirective subclass: #MetacelloExplicitLoadDirective
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Directives'!
----- Method: MetacelloExplicitLoadDirective>>explicitLoadUsing:gofer: (in category 'actions') -----
explicitLoadUsing: aLoaderDirective gofer: aGofer
aLoaderDirective loadLinearLoadDirective: self gofer: aGofer.!
----- Method: MetacelloExplicitLoadDirective>>explicitLoadWithPolicy: (in category 'actions') -----
explicitLoadWithPolicy: aLoadPolicy
| gofer |
gofer := MetacelloGofer new.
gofer disablePackageCache.
gofer repository: aLoadPolicy cacheRepository.
self explicitLoadUsing: self gofer: gofer!
----- Method: MetacelloExplicitLoadDirective>>isExplicit (in category 'testing') -----
isExplicit
^true!
----- Method: MetacelloExplicitLoadDirective>>loadUsing:gofer: (in category 'actions') -----
loadUsing: aLoaderDirective gofer: aGofer
aLoaderDirective loadExplicitLoadDirective: self gofer: aGofer.!
----- Method: MetacelloExplicitLoadDirective>>title (in category 'accessing') -----
title
^'explicit load'!
MetacelloVersionLoadDirective subclass: #MetacelloLinearLoadDirective
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Directives'!
----- Method: MetacelloLinearLoadDirective>>loadUsing:gofer: (in category 'actions') -----
loadUsing: aLoaderDirective gofer: aGofer
self loadDirectives isEmpty ifTrue: [ ^self ].
aLoaderDirective loadLinearLoadDirective: self gofer: aGofer.!
----- Method: MetacelloLinearLoadDirective>>title (in category 'accessing') -----
title
^'linear load'!
----- Method: MetacelloVersionLoadDirective>>add: (in category 'actions') -----
add: aDirective
self loadDirectives add: aDirective!
----- Method: MetacelloVersionLoadDirective>>directivesDo: (in category 'enumerating') -----
directivesDo: aBlock
aBlock value: self.
self loadDirectives do: [:directive | directive directivesDo: aBlock ].!
----- Method: MetacelloVersionLoadDirective>>finalizeLoad: (in category 'actions') -----
finalizeLoad: aGofer
"nothing special for linear loads"!
----- Method: MetacelloVersionLoadDirective>>isExplicit (in category 'testing') -----
isExplicit
^false!
----- Method: MetacelloVersionLoadDirective>>label (in category 'printing') -----
label
self spec == nil ifTrue: [ ^'' ].
^self spec label!
----- Method: MetacelloVersionLoadDirective>>loadAtomicLoadDirective:gofer: (in category 'actions') -----
loadAtomicLoadDirective: aLoaderDirective gofer: aGofer
aLoaderDirective loadDirectives do: [:directive | directive loadUsing: aLoaderDirective gofer: aGofer ].
aLoaderDirective finalizeLoad: aGofer.!
----- Method: MetacelloVersionLoadDirective>>loadDirectives (in category 'accessing') -----
loadDirectives
loadDirectives == nil ifTrue: [ loadDirectives := OrderedCollection new ].
^ loadDirectives!
----- Method: MetacelloVersionLoadDirective>>loadDirectives: (in category 'accessing') -----
loadDirectives: anObject
loadDirectives := anObject!
----- Method: MetacelloVersionLoadDirective>>loadExplicitLoadDirective:gofer: (in category 'actions') -----
loadExplicitLoadDirective: aLoaderDirective gofer: aGofer
"load has already been performed, no need to load again"!
----- Method: MetacelloVersionLoadDirective>>loadLinearLoadDirective:gofer: (in category 'actions') -----
loadLinearLoadDirective: aLoaderDirective gofer: aGofer
aLoaderDirective loadDirectives do: [:directive | directive loadUsing: aLoaderDirective gofer: aGofer ].
aLoaderDirective finalizeLoad: aGofer.!
----- Method: MetacelloVersionLoadDirective>>loadPackageDirective:gofer: (in category 'loading') -----
loadPackageDirective: aPackageLoadDirective gofer: aGofer
aPackageLoadDirective loader loadingSpecLoader
loadPackageDirective: aPackageLoadDirective
gofer: aGofer!
----- Method: MetacelloVersionLoadDirective>>loadPostloadDirective: (in category 'loading') -----
loadPostloadDirective: aPostloadDirective
| block |
(block := aPostloadDirective spec postLoadDoItBlock) ~~ nil
ifTrue: [
aPostloadDirective evaluateSupplyingAnswers: [ block valueWithPossibleArgs:
(Array
with: aPostloadDirective loader
with: aPostloadDirective spec) ].
Transcript cr; show: 'Evaluated -> ', aPostloadDirective spec label, ' >> ', aPostloadDirective spec postLoadDoIt value asString]!
----- Method: MetacelloVersionLoadDirective>>loadPreloadDirective: (in category 'loading') -----
loadPreloadDirective: aPreloadDirective
| block |
(block := aPreloadDirective spec preLoadDoItBlock) ~~ nil
ifTrue: [
aPreloadDirective evaluateSupplyingAnswers: [ block valueWithPossibleArgs:
(Array
with: aPreloadDirective loader
with: aPreloadDirective spec) ].
Transcript cr; show: 'Evaluated -> ', aPreloadDirective spec label, ' >> ', aPreloadDirective spec preLoadDoIt value asString]!
----- Method: MetacelloVersionLoadDirective>>loadWithPolicy: (in category 'actions') -----
loadWithPolicy: aLoadPolicy
| gofer |
gofer := MetacelloGofer new.
gofer disablePackageCache.
gofer repository: aLoadPolicy cacheRepository.
self loadUsing: self gofer: gofer!
----- Method: MetacelloVersionLoadDirective>>packageDirectivesDo: (in category 'enumerating') -----
packageDirectivesDo: aBlock
self loadDirectives do: [:directive | directive packageDirectivesDo: aBlock ].!
----- Method: MetacelloVersionLoadDirective>>packagesDo: (in category 'enumerating') -----
packagesDo: aBlock
self loadDirectives do: [:directive | directive packageDo: aBlock ].!
----- Method: MetacelloVersionLoadDirective>>prepostLoadDirectivesDo: (in category 'enumerating') -----
prepostLoadDirectivesDo: aBlock
self loadDirectives do: [:directive | directive prepostLoadDirectivesDo: aBlock ].!
----- Method: MetacelloVersionLoadDirective>>prepostLoadsDo: (in category 'enumerating') -----
prepostLoadsDo: aBlock
self loadDirectives do: [:directive | directive prepostLoadDo: aBlock ].!
----- Method: MetacelloVersionLoadDirective>>printLoadDirectivesOn:indent: (in category 'printing') -----
printLoadDirectivesOn: aStream indent: indent
self loadDirectives do: [:each |
aStream cr.
each printOn: aStream indent: indent + 1 ].!
----- Method: MetacelloVersionLoadDirective>>printOn:indent: (in category 'printing') -----
printOn: aStream indent: indent
super printOn: aStream indent: indent.
self printLoadDirectivesOn: aStream indent: indent!
----- Method: MetacelloVersionLoadDirective>>spec (in category 'accessing') -----
spec
"Expected to be a MetacelloVersionSpec"
(spec == nil and: [ self loader ~~ nil ])
ifTrue: [
^[ self loader spec versionSpec ]
on: MessageNotUnderstood
do: [:ex | ex return: self loader spec ]].
^spec!
----- Method: MetacelloVersionLoadDirective>>versionDirectivesDepthFirstDo: (in category 'enumerating') -----
versionDirectivesDepthFirstDo: aBlock
self loadDirectives do: [:directive | directive versionDirectivesDepthFirstDo: aBlock ].
aBlock value: self.!
----- Method: MetacelloVersionLoadDirective>>versionDirectivesDo: (in category 'enumerating') -----
versionDirectivesDo: aBlock
aBlock value: self.
self loadDirectives do: [:directive | directive versionDirectivesDo: aBlock ].!
----- Method: MetacelloVersionLoadDirective>>versionDo: (in category 'enumerating') -----
versionDo: aBlock
aBlock value: self.!
----- Method: MetacelloVersionLoadDirective>>versionsDo: (in category 'enumerating') -----
versionsDo: aBlock
self loadDirectives do: [:directive | directive versionDo: aBlock ].!
Object subclass: #MetacelloLoadData
instanceVariableNames: 'dataMap versionInfoMap packageNameMap'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Loaders'!
----- Method: MetacelloLoadData>>addVersion:versionInfo:resolvedReference:packageSpec: (in category 'accessing') -----
addVersion: version versionInfo: versionInfo resolvedReference: resolvedReference packageSpec: packageSpec
| vis |
"check for duplicates and use the one that is being added"
(vis := self packageNameMap at: packageSpec name ifAbsent: [ ]) ~~ nil
ifTrue: [
"remove old references"
vis
do: [ :vi |
self dataMap removeKey: vi name.
self versionInfoMap removeKey: vi name ] ].
self dataMap
at: version info name
put:
{version.
resolvedReference.
packageSpec}.
self versionInfoMap at: versionInfo name put: {versionInfo}.
self packageNameMap at: packageSpec name put: {versionInfo}!
----- Method: MetacelloLoadData>>ancestorsFor:ifAbsent: (in category 'versionInfo') -----
ancestorsFor: packageSpec ifAbsent: aBlock
^self versionInfoMap
at: packageSpec file
ifAbsent: [
self packageNameMap
at: packageSpec name
ifAbsent: aBlock ]!
----- Method: MetacelloLoadData>>currentVersionInfoFor:ifAbsent: (in category 'versionInfo') -----
currentVersionInfoFor: packageSpec ifAbsent: aBlock
^self versionInfoMap
at: packageSpec file
ifPresent: [ :v | v first ]
ifAbsent: [
self packageNameMap
at: packageSpec name
ifPresent: [ :v | v first ]
ifAbsent: aBlock ]!
----- Method: MetacelloLoadData>>dataMap (in category 'accessing') -----
dataMap
dataMap == nil ifTrue: [ dataMap := Dictionary new ].
^dataMap!
----- Method: MetacelloLoadData>>do: (in category 'enumerating') -----
do: aBlock
self dataMap valuesDo: [:ar |
aBlock value: (ar at: 1) value: (ar at: 2) value: (ar at: 3) ]!
----- Method: MetacelloLoadData>>isEmpty (in category 'testing') -----
isEmpty
^self dataMap isEmpty!
----- Method: MetacelloLoadData>>packageNameMap (in category 'accessing') -----
packageNameMap
packageNameMap == nil ifTrue: [ packageNameMap := Dictionary new ].
^packageNameMap!
----- Method: MetacelloLoadData>>versionInfoMap (in category 'accessing') -----
versionInfoMap
versionInfoMap == nil ifTrue: [ versionInfoMap := Dictionary new ].
^versionInfoMap!
Object subclass: #MetacelloLoaderPolicy
instanceVariableNames: 'overrideRepositories repositoryMap ensuredMap cacheRepository cacheGofer ignoreImage loadData loadDirective silently'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Loaders'!
----- Method: MetacelloLoaderPolicy class>>overrideRepositories: (in category 'instance creation') -----
overrideRepositories: aCollection
^self new overrideRepositories: aCollection!
----- Method: MetacelloLoaderPolicy>>cacheGofer (in category 'accessing') -----
cacheGofer
cacheGofer == nil
ifTrue: [
"don't use a caching Gofer here, since we expect the contents to change during a fetch operation"
cacheGofer := Gofer new.
cacheGofer disablePackageCache.
cacheGofer repository: self cacheRepository. ].
^ cacheGofer!
----- Method: MetacelloLoaderPolicy>>cacheRepository (in category 'accessing') -----
cacheRepository
cacheRepository == nil ifTrue: [ cacheRepository := MCDictionaryRepository new ].
^ cacheRepository!
----- Method: MetacelloLoaderPolicy>>cacheRepository: (in category 'accessing') -----
cacheRepository: anMCRepository
cacheRepository := anMCRepository.
"getting a new repository, so wipe out the cacheGofer and ensureMap"
ensuredMap := cacheGofer := nil!
----- Method: MetacelloLoaderPolicy>>ensuredMap (in category 'accessing') -----
ensuredMap
ensuredMap == nil ifTrue: [ ensuredMap := Dictionary new ].
^ensuredMap!
----- Method: MetacelloLoaderPolicy>>ensuredMap: (in category 'accessing') -----
ensuredMap: anObject
ensuredMap := anObject!
----- Method: MetacelloLoaderPolicy>>hasRepositoryOverrides (in category 'testing') -----
hasRepositoryOverrides
^self overrideRepositories ~~ nil!
----- Method: MetacelloLoaderPolicy>>ignoreImage (in category 'accessing') -----
ignoreImage
^ ignoreImage!
----- Method: MetacelloLoaderPolicy>>ignoreImage: (in category 'accessing') -----
ignoreImage: anObject
ignoreImage := anObject!
----- Method: MetacelloLoaderPolicy>>initialize (in category 'initialize-release') -----
initialize
self
repositoryMap;
cacheRepository;
ensuredMap.
ignoreImage := false!
----- Method: MetacelloLoaderPolicy>>load (in category 'actions') -----
load
overrideRepositories := Array with: self cacheRepository. "ensure that hasRepositoryOverrides is true"
self loadDirective loadWithPolicy: self!
----- Method: MetacelloLoaderPolicy>>loadData (in category 'accessing') -----
loadData
loadData == nil ifTrue: [ loadData := MetacelloLoadData new ].
^loadData!
----- Method: MetacelloLoaderPolicy>>loadDirective (in category 'accessing') -----
loadDirective
loadDirective == nil ifTrue: [ loadDirective := MetacelloLinearLoadDirective new ].
^ loadDirective!
----- Method: MetacelloLoaderPolicy>>overrideRepositories (in category 'accessing') -----
overrideRepositories
^ overrideRepositories!
----- Method: MetacelloLoaderPolicy>>overrideRepositories: (in category 'accessing') -----
overrideRepositories: anObject
overrideRepositories := anObject!
----- Method: MetacelloLoaderPolicy>>pushAtomicLoadDirectivesDuring:for: (in category 'actions') -----
pushAtomicLoadDirectivesDuring: aBlock for: aLoader
self pushLoadDirective: (MetacelloAtomicLoadDirective loader: aLoader) during: aBlock.!
----- Method: MetacelloLoaderPolicy>>pushExplicitLoadDirectivesDuring:for: (in category 'actions') -----
pushExplicitLoadDirectivesDuring: aBlock for: aLoader
| directive |
directive := MetacelloExplicitLoadDirective loader: aLoader.
self pushLoadDirective: directive during: aBlock.
^directive!
----- Method: MetacelloLoaderPolicy>>pushLinearLoadDirectivesDuring:for: (in category 'actions') -----
pushLinearLoadDirectivesDuring: aBlock for: aLoader
self pushLoadDirective: (MetacelloLinearLoadDirective loader: aLoader) during: aBlock.!
----- Method: MetacelloLoaderPolicy>>pushLoadDirective:during: (in category 'private') -----
pushLoadDirective: aLoaderDirective during: aBlock
| oldRoot |
self loadDirective add: aLoaderDirective.
oldRoot := loadDirective.
loadDirective := aLoaderDirective.
aBlock ensure: [ loadDirective := oldRoot ].!
----- Method: MetacelloLoaderPolicy>>repositoryMap (in category 'accessing') -----
repositoryMap
repositoryMap == nil ifTrue: [ repositoryMap := Dictionary new ].
^repositoryMap!
----- Method: MetacelloLoaderPolicy>>repositoryMap: (in category 'accessing') -----
repositoryMap: anObject
repositoryMap := anObject!
----- Method: MetacelloLoaderPolicy>>resetCacheGofer (in category 'accessing') -----
resetCacheGofer
cacheGofer := nil!
----- Method: MetacelloLoaderPolicy>>silently (in category 'accessing') -----
silently
silently == nil ifTrue: [ silently := false ].
^ silently!
----- Method: MetacelloLoaderPolicy>>silently: (in category 'accessing') -----
silently: anObject
silently := anObject!
Object subclass: #MetacelloMCPartiallyLoadedStatus
instanceVariableNames: 'hasNoPackage hasNoProject aProjectIsLoaded aPackageIsLoaded aLoadedProjectIsExact aLoadedPackageIsExact aLoadedProjectIsCurrent aLoadedPackageIsCurrent aLoadedProjectIsNotCurrent aLoadedPackageIsNotCurrent aProjectNotLoaded aPackageNotLoaded vrsnStatus abort'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
----- Method: MetacelloMCPartiallyLoadedStatus class>>new (in category 'instance creation') -----
new
^ self basicNew initialize!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedPackageIsCurrent (in category 'accessing') -----
aLoadedPackageIsCurrent
^ aLoadedPackageIsCurrent!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedPackageIsCurrent: (in category 'accessing') -----
aLoadedPackageIsCurrent: aBoolean
aLoadedPackageIsCurrent := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedPackageIsExact (in category 'accessing') -----
aLoadedPackageIsExact
^ aLoadedPackageIsExact!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedPackageIsExact: (in category 'accessing') -----
aLoadedPackageIsExact: aBoolean
aLoadedPackageIsExact := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedPackageIsNotCurrent (in category 'accessing') -----
aLoadedPackageIsNotCurrent
^ aLoadedPackageIsNotCurrent!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedPackageIsNotCurrent: (in category 'accessing') -----
aLoadedPackageIsNotCurrent: aBoolean
aLoadedPackageIsNotCurrent := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedProjectIsCurrent: (in category 'accessing') -----
aLoadedProjectIsCurrent: aBoolean
aLoadedProjectIsCurrent := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedProjectIsExact (in category 'accessing') -----
aLoadedProjectIsExact
^ aLoadedProjectIsExact!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedProjectIsExact: (in category 'accessing') -----
aLoadedProjectIsExact: aBoolean
aLoadedProjectIsExact := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedProjectIsNotCurrent (in category 'accessing') -----
aLoadedProjectIsNotCurrent
^ aLoadedProjectIsNotCurrent!
----- Method: MetacelloMCPartiallyLoadedStatus>>aLoadedProjectIsNotCurrent: (in category 'accessing') -----
aLoadedProjectIsNotCurrent: aBoolean
aLoadedProjectIsNotCurrent := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>aPackageIsLoaded (in category 'accessing') -----
aPackageIsLoaded
^aPackageIsLoaded!
----- Method: MetacelloMCPartiallyLoadedStatus>>aPackageIsLoaded: (in category 'accessing') -----
aPackageIsLoaded: aBoolean
aPackageIsLoaded := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>aPackageNotLoaded (in category 'accessing') -----
aPackageNotLoaded
^aPackageNotLoaded!
----- Method: MetacelloMCPartiallyLoadedStatus>>aPackageNotLoaded: (in category 'accessing') -----
aPackageNotLoaded: aBoolean
aPackageNotLoaded := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>aProjectIsLoaded (in category 'accessing') -----
aProjectIsLoaded
^aProjectIsLoaded!
----- Method: MetacelloMCPartiallyLoadedStatus>>aProjectIsLoaded: (in category 'accessing') -----
aProjectIsLoaded: aBoolean
aProjectIsLoaded := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>aProjectNotLoaded (in category 'accessing') -----
aProjectNotLoaded
^aProjectNotLoaded!
----- Method: MetacelloMCPartiallyLoadedStatus>>aProjectNotLoaded: (in category 'accessing') -----
aProjectNotLoaded: aBoolean
aProjectNotLoaded := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>abort (in category 'accessing') -----
abort
^ abort!
----- Method: MetacelloMCPartiallyLoadedStatus>>abort: (in category 'accessing') -----
abort: aBoolean
abort := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>evaluateStatus: (in category 'evaulation') -----
evaluateStatus: validStatusList
^self abort
ifTrue: [ false ]
ifFalse: [
(self hasNoProject or: [ self vrsnStatus isEmpty ])
ifTrue: [ true ]
ifFalse: [
| valid |
valid := true.
vrsnStatus
do: [ :status |
(validStatusList includes: status)
ifFalse: [ valid := false ] ].
valid ] ]!
----- Method: MetacelloMCPartiallyLoadedStatus>>hasNoPackage (in category 'accessing') -----
hasNoPackage
^ hasNoPackage!
----- Method: MetacelloMCPartiallyLoadedStatus>>hasNoPackage: (in category 'accessing') -----
hasNoPackage: aBoolean
hasNoPackage := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>hasNoProject (in category 'accessing') -----
hasNoProject
^ hasNoProject!
----- Method: MetacelloMCPartiallyLoadedStatus>>hasNoProject: (in category 'accessing') -----
hasNoProject: aBoolean
hasNoProject := aBoolean!
----- Method: MetacelloMCPartiallyLoadedStatus>>initialize (in category 'initialization') -----
initialize
super initialize.
hasNoPackage := hasNoProject := true.
aProjectIsLoaded := aPackageIsLoaded := false.
aLoadedProjectIsExact := aLoadedPackageIsExact := false.
aLoadedProjectIsCurrent := aLoadedPackageIsCurrent := false.
aLoadedProjectIsNotCurrent := aLoadedPackageIsNotCurrent := false.
aProjectNotLoaded := aPackageNotLoaded := false.
vrsnStatus := Set new.
abort := false!
----- Method: MetacelloMCPartiallyLoadedStatus>>isAllLoadedToSpec: (in category 'testing') -----
isAllLoadedToSpec: matchBlock
"all projects and packages are loaded and match specification"
(self evaluateStatus: #(#allLoadedToSpec))
ifTrue: [
((hasNoPackage
or: [
aPackageIsLoaded & aPackageNotLoaded not & aLoadedPackageIsExact & aLoadedPackageIsNotCurrent not
& aLoadedPackageIsCurrent not ])
and: [
hasNoProject
or: [
aProjectIsLoaded & aProjectNotLoaded not & aLoadedProjectIsExact & aLoadedProjectIsNotCurrent not
& aLoadedProjectIsCurrent not ] ])
ifTrue: [ matchBlock value: #allLoadedToSpec ] ]!
----- Method: MetacelloMCPartiallyLoadedStatus>>isLoadedMatchConstraints: (in category 'testing') -----
isLoadedMatchConstraints: matchBlock
"all loaded projects and packages match constraints (at least one package loaded)"
| matchStatus |
matchStatus := #loadedMatchConstraints.
(self evaluateStatus: #(#allLoadedToSpec #loadedToSpec #loadedMatchConstraints))
ifTrue: [
aPackageIsLoaded & aProjectIsLoaded
ifTrue: [
(aLoadedPackageIsExact | aLoadedPackageIsCurrent & aLoadedPackageIsNotCurrent not
and: [ aLoadedProjectIsExact | aLoadedProjectIsCurrent & aLoadedProjectIsNotCurrent not ])
ifTrue: [ matchBlock value: matchStatus ] ]
ifFalse: [
aPackageIsLoaded
ifTrue: [
aLoadedPackageIsExact | aLoadedPackageIsCurrent & aLoadedPackageIsNotCurrent not
ifTrue: [ matchBlock value: matchStatus ] ]
ifFalse: [
hasNoPackage & (aLoadedProjectIsExact | aLoadedProjectIsCurrent) & aLoadedProjectIsNotCurrent not
ifTrue: [ matchBlock value: matchStatus ] ] ] ]!
----- Method: MetacelloMCPartiallyLoadedStatus>>isLoadedToSpec: (in category 'testing') -----
isLoadedToSpec: matchBlock
"all loaded projects and packages match specifications (at least one package loaded)"
| matchStatus |
matchStatus := #loadedToSpec.
(self evaluateStatus: #(#allLoadedToSpec #loadedToSpec))
ifTrue: [
aPackageIsLoaded & aProjectIsLoaded
ifTrue: [
(aLoadedPackageIsExact & aLoadedPackageIsCurrent not & aLoadedPackageIsNotCurrent not
and: [ aLoadedProjectIsExact & aLoadedProjectIsCurrent not & aLoadedProjectIsNotCurrent not ])
ifTrue: [ matchBlock value: matchStatus ] ]
ifFalse: [
aPackageIsLoaded
ifTrue: [
aLoadedPackageIsExact & aLoadedPackageIsCurrent not & aLoadedPackageIsNotCurrent not
ifTrue: [ matchBlock value: matchStatus ] ]
ifFalse: [
hasNoPackage & aLoadedProjectIsExact & aLoadedProjectIsCurrent not & aLoadedProjectIsNotCurrent not
ifTrue: [ matchBlock value: matchStatus ] ] ] ]!
----- Method: MetacelloMCPartiallyLoadedStatus>>isSomethingLoaded: (in category 'testing') -----
isSomethingLoaded: somethingLoadedBlock
"at least one package loaded"
(self evaluateStatus: #(#allLoadedToSpec #loadedToSpec #loadedMatchConstraints #somethingLoaded))
ifTrue: [
aPackageIsLoaded
ifTrue: [ somethingLoadedBlock value: #somethingLoaded ] ]!
----- Method: MetacelloMCPartiallyLoadedStatus>>vrsnStatus (in category 'accessing') -----
vrsnStatus
^vrsnStatus!
Object subclass: #MetacelloMCVersionSpecLoader
instanceVariableNames: 'versionSpec required packages loader loaderPolicy'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Loaders'!
----- Method: MetacelloMCVersionSpecLoader class>>on: (in category 'instance creation') -----
on: aVersionSpec
^(self new)
versionSpec: aVersionSpec;
yourself!
----- Method: MetacelloMCVersionSpecLoader>>label (in category 'accessing') -----
label
^self versionSpec label!
----- Method: MetacelloMCVersionSpecLoader>>load (in category 'loading') -----
load
| mcLoader |
packages := Dictionary new.
self resolveToLoadableSpecs.
mcLoader := self loader.
packages values
do: [ :pkg |
pkg ensureLoadedForDevelopmentUsing: mcLoader.
(MetacelloIgnorePackageLoaded signal: pkg)
ifFalse: [
mcLoader ignoreImage
ifFalse: [
(pkg
compareCurrentVersion: self operator
targetVersionStatus: #(#'allLoadedToSpec')
using: mcLoader)
ifTrue: [ packages removeKey: pkg name ] ] ] ].
packages notEmpty
ifTrue: [
mcLoader preLoad: self versionSpec.
mcLoader load.
mcLoader postLoad: self versionSpec ].
^ mcLoader!
----- Method: MetacelloMCVersionSpecLoader>>loader (in category 'accessing') -----
loader
loader == nil
ifTrue: [
loader := self versionSpec loader copy.
loader spec: self.
loaderPolicy notNil ifTrue: [ loader loaderPolicy: loaderPolicy] ].
^loader!
----- Method: MetacelloMCVersionSpecLoader>>loaderPolicy (in category 'accessing') -----
loaderPolicy
^ loaderPolicy!
----- Method: MetacelloMCVersionSpecLoader>>loaderPolicy: (in category 'accessing') -----
loaderPolicy: anObject
loaderPolicy := anObject!
----- Method: MetacelloMCVersionSpecLoader>>name (in category 'accessing') -----
name
^self versionSpec name!
----- Method: MetacelloMCVersionSpecLoader>>operator (in category 'accessing') -----
operator
^self loader operator!
----- Method: MetacelloMCVersionSpecLoader>>packageSpecsInLoadOrder (in category 'spec compatibility') -----
packageSpecsInLoadOrder
^ self versionSpec packageSpecsInLoadOrderForMap: packages!
----- Method: MetacelloMCVersionSpecLoader>>packages (in category 'accessing') -----
packages
^packages!
----- Method: MetacelloMCVersionSpecLoader>>project (in category 'accessing') -----
project
^self versionSpec project!
----- Method: MetacelloMCVersionSpecLoader>>repositories (in category 'loading') -----
repositories
^self repositorySpecs!
----- Method: MetacelloMCVersionSpecLoader>>repositorySpecs (in category 'spec compatibility') -----
repositorySpecs
| repositoryMap |
repositoryMap := self versionSpec repositories ~~ nil
ifTrue: [ self versionSpec repositories map ]
ifFalse: [ Dictionary new ].
^repositoryMap values.!
----- Method: MetacelloMCVersionSpecLoader>>required (in category 'accessing') -----
required
required == nil ifTrue: [ ^#() ].
^ required!
----- Method: MetacelloMCVersionSpecLoader>>required: (in category 'accessing') -----
required: anObject
required := anObject!
----- Method: MetacelloMCVersionSpecLoader>>resolvePackageNames (in category 'loading') -----
resolvePackageNames
packages := Dictionary new.
self resolveToLoadableSpecs.
^packages values collect: [:pkg | pkg name ]!
----- Method: MetacelloMCVersionSpecLoader>>resolveToLoadableSpecs (in category 'private') -----
resolveToLoadableSpecs
self versionSpec resolveToLoadableSpecs: required forLoad: true map: packages!
----- Method: MetacelloMCVersionSpecLoader>>versionSpec (in category 'accessing') -----
versionSpec
^ versionSpec!
----- Method: MetacelloMCVersionSpecLoader>>versionSpec: (in category 'accessing') -----
versionSpec: anObject
versionSpec := anObject!
----- Method: MetacelloMCVersionSpecLoader>>versionString (in category 'spec compatibility') -----
versionString
^self versionSpec versionString!
Object subclass: #MetacelloVisitedPackages
instanceVariableNames: 'groups packages projects'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
----- Method: MetacelloVisitedPackages>>initialize (in category 'initialize-release') -----
initialize
groups := Set new.
packages := Set new.
projects := Set new.!
----- Method: MetacelloVisitedPackages>>pushProject: (in category 'visiting') -----
pushProject: aBlock
| oldGroups oldPackages oldProjects |
oldGroups := groups.
oldPackages := packages.
oldProjects := projects.
groups := Set new.
packages := Set new.
^aBlock ensure: [
groups := oldGroups.
packages := oldPackages.
projects := oldProjects ]!
----- Method: MetacelloVisitedPackages>>visit:doing: (in category 'visiting') -----
visit: aSpec doing: aBlock
aSpec
projectDo: [:spec |
(projects includes: spec name) ifTrue: [ ^self ].
projects add: spec name ]
packageDo: [:spec |
(packages includes: spec name) ifTrue: [ ^self ].
packages add: spec name ]
groupDo: [:spec |
(groups includes: spec name) ifTrue: [ ^self ].
groups add: spec name ].
aBlock value: aSpec!
----- Method: Object class>>lastMetacelloVersionLoad (in category '*metacello-mc') -----
lastMetacelloVersionLoad
"Answer the last version loaded and the list of packages loaded for that version.
See MetacelloConfigTemplate."
^nil -> 'default'!
----- Method: Object class>>metacelloVersion:loads: (in category '*metacello-mc') -----
metacelloVersion: versionString loads: anArrayOrString
"Stash the last version loaded and the list of packages loaded for that version. The list
of packages will be used by the tools when doing 'Load Package Version'.
See MetacelloConfigTemplate for example"
"noop by default"!
----- Method: GoferResolvedReference>>asMetacelloCachingResolvedReference (in category '*metacello-mc') -----
asMetacelloCachingResolvedReference
^MetacelloCachingGoferResolvedReference name: self name repository: self repository!
GoferResolvedReference subclass: #MetacelloCachingGoferResolvedReference
instanceVariableNames: 'cachedVersion'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Gofer'!
----- Method: MetacelloCachingGoferResolvedReference>>version (in category 'accessing') -----
version
"Answer a Monticello version of the receiver."
cachedVersion == nil ifTrue: [ cachedVersion := super version ].
^cachedVersion!
----- Method: MetacelloCachingGoferResolvedReference>>workingCopy (in category 'querying') -----
workingCopy
"Answer a working copy or throw an error if not present."
| pName |
cachedVersion == nil ifTrue: [ ^super workingCopy ].
pName := cachedVersion package name.
^MCWorkingCopy allManagers
detect: [ :each | pName = each packageName ]
ifNone: [ self error: 'Working copy for ' , self name , ' not found' ]!
MetacelloProject subclass: #MetacelloMCProject
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Model'!
MetacelloMCProject subclass: #MetacelloMCBaselineProject
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Model'!
!MetacelloMCBaselineProject commentStamp: 'dkh 5/5/2012 08:47' prior: 0!
The **MetacelloMCBaselineProject** is a wrapper for the **BaselineOf** version specification for file-based repositories.
There is a single version in a **MetacelloMCBaselineProject**, named *'baseline'*.
A typical **BaselineOf** is specification:
```Smalltalk
baseline: spec
<baseline>
spec
package: 'External-Core';
package: 'External-Tests' with: [ spec requires: 'External-Core' ];
yourself.
spec
group: 'Core' with: #('External-Core');
group: 'default' with: #('Core');
group: 'Tests' with: #('External-Tests');
yourself
```
The `<baseline>` pragma marks the method containing the baseline specification.!
----- Method: MetacelloMCBaselineProject class>>singletonVersionName (in category 'accessing') -----
singletonVersionName
^ 'baseline'!
----- Method: MetacelloMCBaselineProject class>>versionConstructorClass (in category 'accessing') -----
versionConstructorClass
^ MetacelloBaselineConstructor!
----- Method: MetacelloMCBaselineProject>>asBaselineProject (in category 'scripting') -----
asBaselineProject
^ self!
----- Method: MetacelloMCBaselineProject>>asConfigurationProject (in category 'scripting') -----
asConfigurationProject
^ MetacelloMCProject new!
----- Method: MetacelloMCBaselineProject>>bleedingEdge (in category 'versions') -----
bleedingEdge
^ nil!
----- Method: MetacelloMCBaselineProject>>currentVersion (in category 'versions') -----
currentVersion
^ self version isSomethingLoaded
ifTrue: [ self version ]
ifFalse: [ nil ]!
----- Method: MetacelloMCBaselineProject>>currentVersionAgainst: (in category 'versions') -----
currentVersionAgainst: resolvedPackageAndProjectNames
^ nil!
----- Method: MetacelloMCBaselineProject>>development (in category 'versions') -----
development
^ nil!
----- Method: MetacelloMCBaselineProject>>hasVersion: (in category 'versions') -----
hasVersion: versionString
^ versionString = 'baseline'!
----- Method: MetacelloMCBaselineProject>>lastVersion (in category 'versions') -----
lastVersion
^ self version!
----- Method: MetacelloMCBaselineProject>>latestVersion (in category 'versions') -----
latestVersion
^ self version!
----- Method: MetacelloMCBaselineProject>>latestVersion: (in category 'versions') -----
latestVersion: blessing
^ nil!
----- Method: MetacelloMCBaselineProject>>latestVersionMatching: (in category 'versions') -----
latestVersionMatching: versionPatternString
^ nil!
----- Method: MetacelloMCBaselineProject>>latestVersionMatching:excludedBlessings: (in category 'versions') -----
latestVersionMatching: versionPatternString excludedBlessings: excluded
^ nil!
----- Method: MetacelloMCBaselineProject>>latestVersionMatching:includedBlessings: (in category 'versions') -----
latestVersionMatching: versionPatternString includedBlessings: included
^ nil!
----- Method: MetacelloMCBaselineProject>>latestVersionMatching:includedBlessings:excludedBlessings: (in category 'versions') -----
latestVersionMatching: versionPatternString includedBlessings: included excludedBlessings: excludedBlessings
^ nil!
----- Method: MetacelloMCBaselineProject>>projectForScriptEngine:unconditionalLoad: (in category 'scripting') -----
projectForScriptEngine: aMetacelloScriptEngine unconditionalLoad: aBool
"see https://github.com/dalehenrich/metacello-work/issues/244 ... uncoditionally load
baseline"
^ aMetacelloScriptEngine getBaselineProjectUnconditionalLoad: true!
----- Method: MetacelloMCBaselineProject>>setBaselineRepositoryDescription: (in category 'as yet unclassified') -----
setBaselineRepositoryDescription: aListOrRepositoryDescriptions
"set #version repositories to < aListOrRepositoryDescriptions>. Should be the directory where the BaselineOf is located."
aListOrRepositoryDescriptions do: [:desc | self version spec repository: desc]!
----- Method: MetacelloMCBaselineProject>>singletonVersionName (in category 'versions') -----
singletonVersionName
^ self class singletonVersionName!
----- Method: MetacelloMCBaselineProject>>stableVersion (in category 'versions') -----
stableVersion
^ nil!
----- Method: MetacelloMCBaselineProject>>symbolicVersionSymbols (in category 'versions') -----
symbolicVersionSymbols
^ nil!
----- Method: MetacelloMCBaselineProject>>version (in category 'versions') -----
version
^ self version: self singletonVersionName!
----- Method: MetacelloMCBaselineProject>>versions (in category 'versions') -----
versions
^ [ {(self version)} ]
on: MetacelloVersionDoesNotExistError
do: [ :ex | ^ #() ]!
----- Method: MetacelloMCProject>>asBaselineProject (in category 'scripting') -----
asBaselineProject
^ MetacelloMCBaselineProject new!
----- Method: MetacelloMCProject>>asConfigurationProject (in category 'scripting') -----
asConfigurationProject
^ self!
----- Method: MetacelloMCProject>>baselineOfProjectSpecClass (in category 'spec classes') -----
baselineOfProjectSpecClass
^ MetacelloMCBaselineOfProjectSpec!
----- Method: MetacelloMCProject>>configurationOfProjectSpecClass (in category 'spec classes') -----
configurationOfProjectSpecClass
^ MetacelloMCConfigurationOfProjectSpec!
----- Method: MetacelloMCProject>>createRepository: (in category 'repository creation') -----
createRepository: aRepositorySpec
^ MetacelloPlatform current createRepository: aRepositorySpec!
----- Method: MetacelloMCProject>>defaultLoaderClass (in category 'spec classes') -----
defaultLoaderClass
^MetacelloLoadingMCSpecLoader!
----- Method: MetacelloMCProject>>fetchProject (in category 'development support') -----
fetchProject
"fetch the latest version of the configuration package"
^self fetchProject: MetacelloLoaderPolicy new!
----- Method: MetacelloMCProject>>fetchProject: (in category 'development support') -----
fetchProject: aLoaderPolicy
"fetch the latest version of the configuration package"
| mcLoader |
(mcLoader := self loader) == nil
ifTrue: [ mcLoader := self project loaderClass on: nil ].
mcLoader loaderPolicy: aLoaderPolicy.
mcLoader doingLoads: [
MCWorkingCopy
managersForClass: self configuration class
do: [:mgr | | pkg |
pkg := self packageSpec.
mgr repositoryGroup repositories do: [:repo | pkg repositories repository: (repo asRepositorySpecFor: self) ].
pkg name: mgr packageName.
pkg fetchUsing: mcLoader.
^true ]].
^true!
----- Method: MetacelloMCProject>>goferBranch:project: (in category 'development support') -----
goferBranch: branchName project: commitMessage
| pkgSpec |
pkgSpec := self projectPackage.
pkgSpec file: pkgSpec name , '.' , branchName.
^ pkgSpec goferBranchPackage: branchName message: commitMessage!
----- Method: MetacelloMCProject>>goferCommitProject: (in category 'development support') -----
goferCommitProject: commitMessage
| pkgSpec |
(pkgSpec := self projectPackage) == nil ifTrue: [ ^false ].
^pkgSpec goferCommitPackage: commitMessage!
----- Method: MetacelloMCProject>>packageSpec (in category 'spec classes') -----
packageSpec
^self packageSpecClass for: self!
----- Method: MetacelloMCProject>>packageSpecClass (in category 'spec classes') -----
packageSpecClass
^MetacelloPackageSpec!
----- Method: MetacelloMCProject>>packagesNeedSaving: (in category 'development support') -----
packagesNeedSaving: aVersionString
"Answer a collection of associations (package -> repository) representing the packages
reachable from this project that need to be saved"
| packages |
packages := Set new.
(self version: aVersionString) spec
packagesNeedSavingVisited: (Set with: self configuration class name asString)
into: packages.
^packages!
----- Method: MetacelloMCProject>>pragmaKeywords (in category 'private') -----
pragmaKeywords
^super pragmaKeywords, #(projectPackage:attribute: packages:attribute: repositories:attribute: )!
----- Method: MetacelloMCProject>>projectForScriptEngine:unconditionalLoad: (in category 'scripting') -----
projectForScriptEngine: aMetacelloScriptEngine unconditionalLoad: aBool
^ aMetacelloScriptEngine getConfigurationProjectUnconditionalLoad: aBool!
----- Method: MetacelloMCProject>>projectPackage (in category 'development support') -----
projectPackage
MCWorkingCopy
managersForClass: self configuration class
do: [ :mgr |
| pkgSpec repo |
pkgSpec := self packageSpec
name: mgr packageName;
yourself.
mgr ancestors notEmpty
ifTrue: [ pkgSpec file: mgr ancestors first name ].
repo := mgr repositoryGroup repositories
detect: [ :each | each ~~ MetacelloPlatform current defaultPackageCache ]
ifNone: [
Transcript
cr;
show:
'Using cache repository for ' , self label , ' project package'.
MetacelloPlatform current defaultPackageCache ].
pkgSpec repository: (repo asRepositorySpecFor: self).
^ pkgSpec ].
^ nil!
----- Method: MetacelloMCProject>>projectSpecClass (in category 'spec classes') -----
projectSpecClass
^ MetacelloMCNamelessProjectSpec!
----- Method: MetacelloMCProject>>repositoriesSpec (in category 'spec classes') -----
repositoriesSpec
^self repositoriesSpecClass for: self!
----- Method: MetacelloMCProject>>repositoriesSpecClass (in category 'spec classes') -----
repositoriesSpecClass
^MetacelloRepositoriesSpec!
----- Method: MetacelloMCProject>>repositorySpec (in category 'spec classes') -----
repositorySpec
^self repositorySpecClass for: self!
----- Method: MetacelloMCProject>>repositorySpecClass (in category 'spec classes') -----
repositorySpecClass
^MetacelloRepositorySpec!
----- Method: MetacelloMCProject>>saveProject (in category 'development support') -----
saveProject
| pkgSpec |
(pkgSpec := self projectPackage) == nil ifTrue: [ ^false ].
^pkgSpec savePackage!
----- Method: MetacelloMCProject>>setBaselineRepositoryDescription: (in category 'as yet unclassified') -----
setBaselineRepositoryDescription: aListOrRepositoryDescriptions
"noop "!
----- Method: MetacelloMCProject>>updatePackageRepositoriesFor: (in category 'repository updating') -----
updatePackageRepositoriesFor: versionString
| versionSpec |
(versionSpec := (self version: versionString) versionSpec) packageSpecsInLoadOrder do: [:pkgSpec |
pkgSpec updatePackageRepositoriesFor: versionSpec ].
^true!
----- Method: MetacelloMCProject>>updateProject (in category 'development support') -----
updateProject
"load the latest version of the configuration package"
"WARNING: don't forget to refresh your project instance after doing an #updateProject,
otherwise your instance won't reflect the info in the freshly loaded configuration"
^self updateProject: MetacelloLoaderPolicy new!
----- Method: MetacelloMCProject>>updateProject: (in category 'development support') -----
updateProject: aLoaderPolicy
"load the latest version of the configuration package"
"WARNING: don't forget to refresh your project instance after doing an #updateProject,
otherwise your instance won't reflect the info in the freshly loaded configuration"
| mcLoader |
(mcLoader := self loader) == nil
ifTrue: [ mcLoader := self project loaderClass on: nil ].
mcLoader loaderPolicy: aLoaderPolicy.
mcLoader
doingLoads: [
MCWorkingCopy
managersForClass: self configuration class
do: [ :mgr |
| pkg ar |
pkg := self packageSpec.
mgr repositoryGroup repositories do: [ :repo | pkg repositories repository: (repo asRepositorySpecFor: self) ].
ar := mgr metacelloPackageNameWithBranch.
pkg name: (ar at: 1).
(ar at: 2) notEmpty
ifTrue: [ pkg file: (ar at: 2) ].
pkg load.
^ true ] ].
^ true!
----- Method: MetacelloMCProject>>versionSpecClass (in category 'spec classes') -----
versionSpecClass
^MetacelloMCVersionSpec!
----- Method: MCVersionLoader>>versions (in category '*metacello-mc') -----
versions
^versions!
----- Method: GoferVersionReference>>compare:using: (in category '*metacello-mc') -----
compare: aLoadableReference using: aComparisonOperator
"Compare versions using <aComparisonOperator>. package names #= then compare based upon version number
Branches and Author names are used in the case of a version number tie, because we need to avoid seesaw loading."
self packageName = aLoadableReference packageName
ifFalse: [ ^false ].
self versionNumber = aLoadableReference versionNumber
ifFalse: [ ^ self versionNumber perform: aComparisonOperator with: aLoadableReference versionNumber ].
self branch = aLoadableReference branch
ifFalse: [ ^ self branch perform: aComparisonOperator with: aLoadableReference branch ].
^ self author perform: aComparisonOperator with: aLoadableReference author!
----- Method: GoferVersionReference>>matchesMetacelloGoferPackage: (in category '*metacello-mc') -----
matchesMetacelloGoferPackage: aMetacelloGoferPackage
| ref |
(super matchesMetacelloGoferPackage: aMetacelloGoferPackage)
ifFalse: [ ^ false ].
ref := self class name: aMetacelloGoferPackage packageFilename.
ref versionNumber = 0
ifTrue: [ ^ true ].
^ self versionNumber = ref versionNumber!
----- Method: GoferVersionReference>>metacelloPackageNameWithBranch (in category '*metacello-mc') -----
metacelloPackageNameWithBranch
"answer array with package name and package name with branch name"
self branch isEmpty
ifTrue: [
^ {(self packageName).
(self packageName)} ].
^ {(self packageName).
(self packageName , '.' , self branch)}!
MetacelloVersionSpec subclass: #MetacelloMCVersionSpec
instanceVariableNames: 'repositories packages'
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
----- Method: MetacelloMCVersionSpec>>computeVersionStatus: (in category 'accessing') -----
computeVersionStatus: matchBlock
self computeVersionStatus: (self expandToLoadableSpecNames: #('ALL')) matchBlock: matchBlock!
----- Method: MetacelloMCVersionSpec>>computeVersionStatus:matchBlock: (in category 'accessing') -----
computeVersionStatus: resolvedPackageAndProjectNames matchBlock: matchBlock
| status |
status := resolvedPackageAndProjectNames isNil
ifTrue: [ self isPartiallyCurrent ]
ifFalse: [ self isPartiallyCurrentAgainst: resolvedPackageAndProjectNames ].
status isAllLoadedToSpec: matchBlock.
status isLoadedToSpec: matchBlock.
status isLoadedMatchConstraints: matchBlock.
status isSomethingLoaded: matchBlock!
----- Method: MetacelloMCVersionSpec>>configMethodOn:last:indent: (in category 'printing') -----
configMethodOn: aStream last: last indent: indent
| spec hasRepositories hasPackageSpecs hasImport |
hasRepositories := (spec := self repositoriesSpec) ~~ nil and: [ spec list isEmpty not ].
hasImport := self import ~~ nil.
hasPackageSpecs := false.
self packagesSpec list
do: [ :member |
member spec
projectDo: [ :proj |
member spec name ~~ nil
ifTrue: [ hasPackageSpecs := true ] ]
packageDo: [ :package |
member spec name ~~ nil
ifTrue: [ hasPackageSpecs := true ] ]
groupDo: [ :group |
member spec name ~~ nil
ifTrue: [ hasPackageSpecs := true ] ] ].
self configMethodBasicOn: aStream last: (hasRepositories | hasPackageSpecs | hasImport) not indent: indent.
hasImport
ifTrue: [
self
configMethodValueOn: aStream
for: self import
selector: 'import:'
last: (hasRepositories | hasPackageSpecs) not
indent: indent ].
hasRepositories
ifTrue: [
spec map values size = 1
ifTrue: [
aStream
tab: indent;
nextPutAll: 'spec repository: ';
nextPutAll: spec map values first description printString , '.'.
hasPackageSpecs
ifTrue: [ aStream cr ] ]
ifFalse: [
self
configMethodOn: aStream
for: spec
selector: 'repositories:'
last: hasPackageSpecs not
indent: indent ] ].
self configPackagesSpecMethodOn: aStream indent: indent.
last
ifFalse: [ aStream cr ]!
----- Method: MetacelloMCVersionSpec>>configSpawnMethodOn:indent: (in category 'printing') -----
configSpawnMethodOn: aStream indent: indent
super configSpawnMethodOn: aStream indent: indent.
self configPackagesSpecMethodOn: aStream indent: indent.!
----- Method: MetacelloMCVersionSpec>>currentlyLoadedClassesInVersion (in category 'querying') -----
currentlyLoadedClassesInVersion
| classes |
classes := Set new.
self
projectDo: [ :ignored | ]
packageDo: [ :packageSpec |
| wc |
wc := [ packageSpec workingCopy ]
on: Error
do: [ :ex | ex return: nil ].
wc ~~ nil
ifTrue: [ classes addAll: (MetacelloPlatform current packageInfoFor: wc) classes ] ]
groupDo: [ :ignored | ].
^ classes!
----- Method: MetacelloMCVersionSpec>>currentlyLoadedExtensionClassesInVersion (in category 'querying') -----
currentlyLoadedExtensionClassesInVersion
| classes |
classes := Dictionary new.
self
projectDo: [ :ignored | ]
packageDo: [ :packageSpec |
| wc |
wc := [ packageSpec workingCopy ]
on: Error
do: [ :ex | ex return: nil ].
wc ~~ nil
ifTrue: [
| packageInfo |
packageInfo := MetacelloPlatform current packageInfoFor: wc.
packageInfo extensionClasses
do: [ :cl | classes at: cl put: (packageInfo extensionCategoriesForClass: cl) ] ] ]
groupDo: [ :ignored | ].
^ classes!
----- Method: MetacelloMCVersionSpec>>difference: (in category 'querying') -----
difference: otherVersionSpec
"Return a dictionary of additions, removals and modifications"
| report myProjectSpecs myPackageSpecs otherProjectSpecs otherPackageSpecs |
report := MetacelloVersionDiffReport new.
myProjectSpecs := Dictionary new.
myPackageSpecs := Dictionary new.
self
projectDo: [ :projectSpec | myProjectSpecs at: projectSpec name put: projectSpec ]
packageDo: [ :packageSpec | myPackageSpecs at: packageSpec name put: packageSpec ]
groupDo: [ :ignored | ].
otherProjectSpecs := Dictionary new.
otherPackageSpecs := Dictionary new.
otherVersionSpec
projectDo: [ :projectSpec | otherProjectSpecs at: projectSpec name put: projectSpec ]
packageDo: [ :packageSpec | otherPackageSpecs at: packageSpec name put: packageSpec ]
groupDo: [ :ignored | ].
myProjectSpecs
valuesDo: [ :myProjectSpec |
| otherProjectSpec |
otherProjectSpec := otherProjectSpecs at: myProjectSpec name ifAbsent: [ ].
otherProjectSpec == nil
ifTrue: [
report removals
at: myProjectSpec name
put:
{(myProjectSpec versionString).
''} ]
ifFalse: [
myProjectSpec versionString = otherProjectSpec versionString
ifFalse: [
report modifications
at: myProjectSpec name
put:
{(myProjectSpec versionString).
(otherProjectSpec versionString)} ] ] ].
otherProjectSpecs
valuesDo: [ :otherProjectSpec |
(myProjectSpecs at: otherProjectSpec name ifAbsent: [ ]) == nil
ifTrue: [
report additions
at: otherProjectSpec name
put:
{''.
(otherProjectSpec versionString)} ] ].
myPackageSpecs
valuesDo: [ :myPackageSpec |
| otherPackageSpec |
otherPackageSpec := otherPackageSpecs at: myPackageSpec name ifAbsent: [ ].
otherPackageSpec == nil
ifTrue: [
report removals
at: myPackageSpec name
put:
{(myPackageSpec file).
''} ]
ifFalse: [
myPackageSpec file = otherPackageSpec file
ifFalse: [
report modifications
at: myPackageSpec name
put:
{(myPackageSpec file).
(otherPackageSpec file)} ] ] ].
otherPackageSpecs
valuesDo: [ :otherPackageSpec |
(myPackageSpecs at: otherPackageSpec name ifAbsent: [ ]) == nil
ifTrue: [
report additions
at: otherPackageSpec name
put:
{''.
(otherPackageSpec file)} ] ].
^ report!
----- Method: MetacelloMCVersionSpec>>forceUpdatedPackageSpecs (in category 'development support') -----
forceUpdatedPackageSpecs
| updatedSpecs mcLoader |
updatedSpecs := Dictionary new.
mcLoader := self loader.
self packages map valuesDo: [:pkg | pkg forceUpdatePackageSpec: updatedSpecs using: mcLoader].
^updatedSpecs!
----- Method: MetacelloMCVersionSpec>>isAllLoadedToSpec (in category 'testing') -----
isAllLoadedToSpec
"all projects and packages are loaded and match specification"
self isPartiallyCurrent isAllLoadedToSpec: [ :ignored | ^ true ].
^ false!
----- Method: MetacelloMCVersionSpec>>isAllLoadedToSpecAgainst: (in category 'testing') -----
isAllLoadedToSpecAgainst: resolvedPackageAndProjectNames
"all projects and packages are loaded and match specification"
(self isPartiallyCurrentAgainst: resolvedPackageAndProjectNames) isAllLoadedToSpec: [ :ignored | ^ true ].
^ false!
----- Method: MetacelloMCVersionSpec>>isLoadedMatchConstraints (in category 'testing') -----
isLoadedMatchConstraints
"all loaded projects and packages match constraints (at least one package loaded)"
self isPartiallyCurrent isLoadedMatchConstraints: [ :ignored | ^ true ].
^ false!
----- Method: MetacelloMCVersionSpec>>isLoadedMatchConstraintsAgainst: (in category 'testing') -----
isLoadedMatchConstraintsAgainst: resolvedPackageAndProjectNames
"all loaded projects and packages match constraints (at least one package loaded)"
(self isPartiallyCurrentAgainst: resolvedPackageAndProjectNames) isLoadedMatchConstraints: [ :ignored | ^ true ].
^ false!
----- Method: MetacelloMCVersionSpec>>isLoadedToSpec (in category 'testing') -----
isLoadedToSpec
"all loaded projects and packages match specifications (at least one package loaded)"
self isPartiallyCurrent isLoadedToSpec: [ :ignored | ^ true ].
^ false!
----- Method: MetacelloMCVersionSpec>>isLoadedToSpecAgainst: (in category 'testing') -----
isLoadedToSpecAgainst: resolvedPackageAndProjectNames
"all loaded projects and packages match specifications (at least one package loaded)"
(self isPartiallyCurrentAgainst: resolvedPackageAndProjectNames) isLoadedToSpec: [ :ignored | ^ true ].
^ false!
----- Method: MetacelloMCVersionSpec>>isPartiallyCurrent (in category 'testing') -----
isPartiallyCurrent
^self isPartiallyCurrentAgainst: (self expandToLoadableSpecNames: #('ALL'))!
----- Method: MetacelloMCVersionSpec>>isPartiallyCurrentAgainst: (in category 'testing') -----
isPartiallyCurrentAgainst: resolvedPackageAndProjectNames
| mcLoader status |
status := MetacelloMCPartiallyLoadedStatus new.
mcLoader := self loader.
self
specsNamed: resolvedPackageAndProjectNames
projectDo: [ :prj |
| vrsn currentVersion |
status hasNoProject: false.
vrsn := prj versionOrNil.
vrsn ~~ nil
ifTrue: [
(currentVersion := prj relativeCurrentVersion) ~~ nil
ifTrue: [ status vrsnStatus add: currentVersion versionStatus ] ].
currentVersion ~~ nil
ifTrue: [
status aProjectIsLoaded: true.
(currentVersion perform: #= with: vrsn)
ifTrue: [ status aLoadedProjectIsExact: true ]
ifFalse: [
(currentVersion perform: prj projectReference operator with: vrsn)
ifTrue: [ status aLoadedProjectIsCurrent: true ]
ifFalse: [ status aLoadedProjectIsNotCurrent: true ] ] ]
ifFalse: [ status aProjectNotLoaded: true ] ]
packageDo: [ :pkg |
status hasNoPackage: false.
pkg
currentPackageLoaded: [ :versionInfos :file |
| wcName wcRef fileRef exact current |
status aPackageIsLoaded: true.
versionInfos isEmpty
ifTrue: [ status aLoadedPackageIsNotCurrent: true ]
ifFalse: [
exact := current := false.
versionInfos
do: [ :vi |
wcName := vi name.
fileRef := GoferResolvedReference name: file.
wcRef := GoferResolvedReference name: wcName.
(wcRef compare: fileRef using: #=)
ifTrue: [ exact := true ] ].
exact
ifTrue: [ status aLoadedPackageIsExact: true ]
ifFalse: [
versionInfos
do: [ :vi |
wcName := vi name.
fileRef := GoferResolvedReference name: file.
wcRef := GoferResolvedReference name: wcName.
(wcRef compare: fileRef using: #>=)
ifTrue: [ current := true ] ].
current
ifTrue: [ status aLoadedPackageIsCurrent: true ]
ifFalse: [ status aLoadedPackageIsNotCurrent: true ] ] ] ]
notLoaded: [ status aPackageNotLoaded: true ]
using: mcLoader ]
groupDo: [ :ignoredGroup |
"if we encounter a group, trouble"
status abort: true.
^ status ].
^ status!
----- Method: MetacelloMCVersionSpec>>isPossibleBaseline (in category 'testing') -----
isPossibleBaseline
self
projectDo: [:prj | prj isPossibleBaseline ifFalse: [ ^false ]]
packageDo: [:pkg | pkg isPackageLoaded ifFalse: [ ^false ]]
groupDo: [:ignored | ].
^true!
----- Method: MetacelloMCVersionSpec>>isSomethingLoaded (in category 'testing') -----
isSomethingLoaded
"at least one package loaded"
self isPartiallyCurrent isSomethingLoaded: [ :ignored | ^ true ].
^ false!
----- Method: MetacelloMCVersionSpec>>isSomethingLoadedAgainst: (in category 'testing') -----
isSomethingLoadedAgainst: resolvedPackageAndProjectNames
"at least one package loaded"
(self isPartiallyCurrentAgainst: resolvedPackageAndProjectNames) isSomethingLoaded: [ :ignored | ^ true ].
^ false!
----- Method: MetacelloMCVersionSpec>>mergeMap (in category 'merging') -----
mergeMap
| map |
map := super mergeMap.
map at: #'repositories' put: self repositories.
^ map!
----- Method: MetacelloMCVersionSpec>>mergeSpec: (in category 'merging') -----
mergeSpec: anotherSpec
| newSpec map anotherRepositories |
newSpec := super mergeSpec: anotherSpec.
map := anotherSpec mergeMap.
(anotherRepositories := map at: #'repositories') isEmpty not
ifTrue: [
newSpec
repositories:
(self repositories isEmpty
ifTrue: [ anotherRepositories ]
ifFalse: [ self repositories mergeSpec: anotherRepositories ]) ].
^ newSpec!
----- Method: MetacelloMCVersionSpec>>nonOverridable (in category 'merging') -----
nonOverridable
^ super nonOverridable , #(#'repositories')!
----- Method: MetacelloMCVersionSpec>>package:constructor: (in category 'construction') -----
package: aString constructor: aVersionConstructor
aVersionConstructor packageForVersion: aString!
----- Method: MetacelloMCVersionSpec>>package:overrides:constructor: (in category 'construction') -----
package: aString overrides: aBlock constructor: aVersionConstructor
aVersionConstructor packageForVersion: aString overrides: aBlock!
----- Method: MetacelloMCVersionSpec>>package:with:constructor: (in category 'construction') -----
package: packageName with: aBlockOrString constructor: aVersionConstructor
aVersionConstructor packageForVersion: packageName with: aBlockOrString!
----- Method: MetacelloMCVersionSpec>>packageNames (in category 'querying') -----
packageNames
"leave reference to packages for upgrade purposes"
packages == nil
ifTrue: [ ^ super packageNames ].
^ self packages map keys asSet!
----- Method: MetacelloMCVersionSpec>>packageSpecsInLoadOrderForMap: (in category 'querying') -----
packageSpecsInLoadOrderForMap: packageMap
| loadOrder pkgs packageNames importNames importSpec importProjectSpecs importProjectNameMap |
loadOrder := self packageSpecsInLoadOrder.
importNames := (packageNames := (packageMap values
collect: [ :pkg | pkg name ]) asSet) copy.
(self import isNil and: [ self importArray isNil ])
ifTrue: [ ^ loadOrder select: [ :pkg | packageNames includes: pkg name ] ].
loadOrder do: [ :pkg | importNames remove: pkg name ifAbsent: [ ] ].
pkgs := OrderedCollection new.
importProjectSpecs := Dictionary new.
importProjectNameMap := Dictionary new.
importArray
ifNotNil: [
loadOrder
do: [ :pkg |
importArray
do: [ :assoc |
assoc key = pkg name
ifTrue: [
importProjectSpecs at: pkg name put: pkg.
(assoc value select: [ :each | importNames includes: each ])
do: [ :each |
(importProjectNameMap
at: pkg name
ifAbsent: [ importProjectNameMap at: pkg name put: Set new ])
add: each ] ] ] ] ].
self import
ifNotNil: [
loadOrder
do: [ :pkg |
pkg name = self import
ifTrue: [
importProjectSpecs at: pkg name put: pkg.
importProjectNameMap at: pkg name put: importNames ] ] ].
loadOrder
do: [ :pkg |
(packageNames includes: pkg name)
ifTrue: [ pkgs add: pkg ].
importProjectSpecs
at: pkg name
ifPresent: [ :importProjectSpec |
"insert the imports at this point"
(importProjectNameMap at: pkg name ifAbsent: [ #() ])
do: [ :importedName |
pkgs
add:
(importSpec := importProjectSpec copy
name: importedName;
mergeImportLoads: {importedName};
yourself).
importSpec projectReference name: importedName ] ] ].
^ pkgs!
----- Method: MetacelloMCVersionSpec>>packages (in category 'accessing') -----
packages
"leave reference to packages for upgrade purposes"
packages == nil
ifTrue: [ ^ super packages ].
^ packages!
----- Method: MetacelloMCVersionSpec>>packagesNeedSavingVisited:into: (in category 'development support') -----
packagesNeedSavingVisited: visitedProjects into: aCollection
self packages map valuesDo: [:pkg | pkg packagesNeedSavingVisited: visitedProjects using: self repositories map values into: aCollection ].!
----- Method: MetacelloMCVersionSpec>>postCopy (in category 'copying') -----
postCopy
super postCopy.
repositories := repositories copy.
packages := packages copy "leave reference to packages for upgrade purposes"!
----- Method: MetacelloMCVersionSpec>>removePackage:constructor: (in category 'construction') -----
removePackage: aString constructor: aVersionConstructor
aVersionConstructor removePackageForVersion: aString!
----- Method: MetacelloMCVersionSpec>>repositories (in category 'accessing') -----
repositories
repositories == nil ifTrue: [ repositories := self project repositoriesSpec ].
^ repositories!
----- Method: MetacelloMCVersionSpec>>repositories: (in category 'accessing') -----
repositories: anObject
repositories := anObject!
----- Method: MetacelloMCVersionSpec>>repositoriesSpec (in category 'accessing') -----
repositoriesSpec
^self repositories!
----- Method: MetacelloMCVersionSpec>>repository: (in category 'accessing') -----
repository: aString
self repositoriesSpec add: aString!
----- Method: MetacelloMCVersionSpec>>repository:username:password: (in category 'accessing') -----
repository: aString username: username password: password
self repositoriesSpec repository: aString username: username password: password!
----- Method: MetacelloMCVersionSpec>>repositorySpecs (in category 'loading') -----
repositorySpecs
^self repositories map values!
----- Method: MetacelloMCVersionSpec>>specListProjectDo:packageDo:groupDo: (in category 'enumerating') -----
specListProjectDo: projectBlock packageDo: packageBlock groupDo: groupBlock
self packages specListDo: [:pkgSpec |
pkgSpec projectDo: projectBlock packageDo: packageBlock groupDo: groupBlock ]!
----- Method: MetacelloMCVersionSpec>>specsNamed:projectDo:packageDo:groupDo: (in category 'enumerating') -----
specsNamed: packageAndProjectNames projectDo: projectBlock packageDo: packageBlock groupDo: groupBlock
| map |
map := self packages map.
packageAndProjectNames do: [:name | | pkgSpec |
(pkgSpec := map at: name ifAbsent: [ ]) ~~ nil
ifTrue: [ pkgSpec projectDo: projectBlock packageDo: packageBlock groupDo: groupBlock ]]!
----- Method: MetacelloMCVersionSpec>>updateForSpawnMethod: (in category 'development support') -----
updateForSpawnMethod: sourceSpec
"This means that this spec was used in a baseline and will be used in a version .... drop all information that isn't useful"
repositories := preLoadDoIt := postLoadDoIt := nil.!
----- Method: MetacelloMCVersionSpec>>updatedPackageSpecs (in category 'development support') -----
updatedPackageSpecs
| updatedSpecs mcLoader |
updatedSpecs := Dictionary new.
mcLoader := self loader.
self packages map valuesDo: [:pkg | pkg updatePackageSpec: updatedSpecs using: mcLoader].
^updatedSpecs!
----- Method: MetacelloMCVersionSpec>>versionClass (in category 'private') -----
versionClass
^MetacelloMCVersion!
Gofer subclass: #MetacelloGofer
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Gofer'!
----- Method: MetacelloGofer>>basicReferencesIn: (in category 'private') -----
basicReferencesIn: aRepository
((aRepository respondsTo: #cacheReferences) not or: [aRepository cacheReferences not])
ifTrue: [^ super basicReferencesIn: aRepository ].
"Use cache for network-based repositories - the contents of repository is cached based on first access
and is _not_ updated afterword, so any mcz files added after the initial cache is created won't be seen"
^ MetacelloPlatform current
stackCacheFor: #goferRepository
cacheClass: IdentityDictionary
at: aRepository
doing: [ :cache |
^ cache at: aRepository put: (super basicReferencesIn: aRepository) ]!
----- Method: MetacelloGofer>>interactiveCommit (in category 'operations') -----
interactiveCommit
^ self execute: MetacelloGoferCommit!
MetacelloMemberListSpec subclass: #MetacelloRepositoriesSpec
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Metacello-MC-Specs'!
----- Method: MetacelloRepositoriesSpec>>add: (in category 'actions') -----
add: aStringOrSpec
aStringOrSpec addToMetacelloRepositories: self!
----- Method: MetacelloRepositoriesSpec>>canUpgradeTo: (in category 'scripting') -----
canUpgradeTo: aMetacelloRepositoriesSpec
| repositorySpecs anotherRepositorySpecs |
repositorySpecs := self map values
sort: [ :a :b | a description <= b description ].
anotherRepositorySpecs := aMetacelloRepositoriesSpec map values
sort: [ :a :b | a description <= b description ].
repositorySpecs size ~= anotherRepositorySpecs size
ifTrue: [ ^ false ].
1 to: repositorySpecs size do: [ :index |
| repoSpec anotherRepoSpec |
repoSpec := repositorySpecs at: index.
anotherRepoSpec := anotherRepositorySpecs at: index.
(repoSpec canUpgradeTo: anotherRepoSpec)
ifTrue: [ ^ true ] ].
^ false!
----- Method: MetacelloRepositoriesSpec>>compareEqual: (in category 'scripting') -----
compareEqual: aMetacelloProjectSpec
| repositorySpecs anotherRepositorySpecs |
repositorySpecs := (self map values sort: [ :a :b | a description <= b description ])
collect: [ :each | each description ].
anotherRepositorySpecs := (aMetacelloProjectSpec map values sort: [ :a :b | a description <= b description ])
collect: [ :each | each description ].
^ repositorySpecs = anotherRepositorySpecs!
----- Method: MetacelloRepositoriesSpec>>configMethodCascadeOn:indent: (in category 'printing') -----
configMethodCascadeOn: aStream indent: indent
| repositorySpecs |
repositorySpecs := self map values sort: [:a :b | a description <= b description ].
repositorySpecs size = 1
ifTrue: [ repositorySpecs first configMethodCascadeOn: aStream lastCascade: true ]
ifFalse: [
1 to: repositorySpecs size do: [:index | | repositorySpec |
aStream tab: indent + 1.
(repositorySpecs at: index)
configMethodCascadeOn: aStream
lastCascade: index >= repositorySpecs size ]]!
----- Method: MetacelloRepositoriesSpec>>configMethodOn:indent: (in category 'printing') -----
configMethodOn: aStream indent: indent
aStream
tab: indent;
nextPutAll: 'spec';
cr.
self configMethodCascadeOn: aStream indent: indent!
----- Method: MetacelloRepositoriesSpec>>hasNoLoadConflicts: (in category 'scripting') -----
hasNoLoadConflicts: aMetacelloRepositoriesSpec
| repositorySpecs anotherRepositorySpecs |
repositorySpecs := self map values
sort: [ :a :b | a description <= b description ].
anotherRepositorySpecs := aMetacelloRepositoriesSpec map values
sort: [ :a :b | a description <= b description ].
repositorySpecs size ~= anotherRepositorySpecs size
ifTrue: [ ^ false ].
1 to: repositorySpecs size do: [ :index |
| repoSpec anotherRepoSpec |
repoSpec := repositorySpecs at: index.
anotherRepoSpec := anotherRepositorySpecs at: index.
(repoSpec hasNoLoadConflicts: anotherRepoSpec)
ifFalse: [ ^ false ] ].
^ true!
----- Method: MetacelloRepositoriesSpec>>merge: (in category 'actions') -----
merge: aRepositorySpec
aRepositorySpec mergeIntoMetacelloRepositories: self!
----- Method: MetacelloRepositoriesSpec>>metacelloRegistrationHash (in category 'scripting') -----
metacelloRegistrationHash
^ ((self map values sort: [ :a :b | a description <= b description ]) collect: [ :each | each description ]) hash!
----- Method: MetacelloRepositoriesSpec>>remove: (in category 'actions') -----
remove: aRepositorySpec
aRepositorySpec removeFromMetacelloRepositories: self!
----- Method: MetacelloRepositoriesSpec>>repository: (in category 'actions') -----
repository: aStringOrSpec
aStringOrSpec addToMetacelloRepositories: self!
----- Method: MetacelloRepositoriesSpec>>repository:constructor: (in category 'construction') -----
repository: anObject constructor: aVersionConstructor
aVersionConstructor repositoryForRepositories: anObject!
----- Method: MetacelloRepositoriesSpec>>repository:username:password: (in category 'actions') -----
repository: description username: username password: password
| spec |
spec :=
(self project repositorySpec)
description: description;
username: username;
password: password;
yourself.
self addMember:
(self addMember
name: spec name;
spec: spec;
yourself)!
----- Method: MetacelloRepositoriesSpec>>repository:username:password:constructor: (in category 'construction') -----
repository: aString username: username password: password constructor: aVersionConstructor
aVersionConstructor repositoryForRepositories: aString username: username password: password!
----- Method: MCWorkingCopy>>metacelloPackageNameWithBranch (in category '*metacello-mc') -----
metacelloPackageNameWithBranch
"answer array with package name and package name with branch name"
ancestry ancestors isEmpty
ifTrue: [
^ {(package name).
(package name)} ].
^ (GoferVersionReference name: self ancestors first name) metacelloPackageNameWithBranch!
----- Method: MCHttpRepository>>asRepositorySpecFor: (in category '*metacello-mc') -----
asRepositorySpecFor: aMetacelloMCProject
^(aMetacelloMCProject repositorySpec)
description: self description;
type: 'http';
yourself!
----- Method: MCHttpRepository>>username: (in category '*metacello-mc') -----
username: aString
"For compatibility with MetacelloRepositorySpec"
^ self user: aString!
----- Method: MetacelloProjectReferenceSpec>>loadUsing:gofer: (in category '*metacello-mc') -----
loadUsing: aLoader gofer: ignored
| required |
required := self resolveToLoadableSpec.
required loader: aLoader.
^required load!
----- Method: MetacelloProjectReferenceSpec>>packagesNeedSavingVisited:using:into: (in category '*metacello-mc') -----
packagesNeedSavingVisited: visitedProjects using: repos into: aCollection
| prjct clsName vrsn |
prjct := self resolveToLoadableSpec.
(visitedProjects includes: (clsName := prjct className)) ifTrue: [ ^self ].
visitedProjects add: clsName.
(vrsn := self versionOrNil) == nil ifTrue: [ ^self ].
vrsn spec
packagesNeedSavingVisited: visitedProjects
into: aCollection!
----- Method: MetacelloProjectReferenceSpec>>repository: (in category '*metacello-mc') -----
repository: aStringOrMetacelloRepositorySpec
^ self projectReference repository: aStringOrMetacelloRepositorySpec!
----- Method: MetacelloProjectReferenceSpec>>resolveProjectSpec (in category '*metacello-mc') -----
resolveProjectSpec
^self projectReference!
----- Method: MetacelloProjectReferenceSpec>>resolveToAllPackagesIn:into:visited: (in category '*metacello-mc') -----
resolveToAllPackagesIn: aVersionSpec into: packages visited: visited
(self resolveProjectSpec resolveToAllPackagesIn: aVersionSpec visited: visited) do: [:pkg |
packages at: pkg put: pkg ]!
----- Method: MetacelloProjectReferenceSpec>>resolveToLoadableSpec (in category '*metacello-mc') -----
resolveToLoadableSpec
^self resolveProjectSpec resolveToLoadableSpec!
----- Method: MetacelloProjectReferenceSpec>>resolveToPackagesIn:andProjects:visited: (in category '*metacello-mc') -----
resolveToPackagesIn: aVersionSpec andProjects: andProjectsBool visited: visited
^ andProjectsBool
ifTrue: [ {self} ]
ifFalse: [ self resolveToPackagesIn: aVersionSpec visited: visited ]!
----- Method: MetacelloProjectReferenceSpec>>resolveToPackagesIn:visited: (in category '*metacello-mc') -----
resolveToPackagesIn: aVersionSpec visited: visited
^#()!
----- Method: MetacelloProjectReferenceSpec>>updateForSpawnMethod: (in category '*metacello-mc') -----
updateForSpawnMethod: sourceSpec
"This means that this spec was used in a baseline and will be used in a version .... drop all information that isn't useful"
| nm |
nm := name.
self projectReference updateForSpawnMethod: sourceSpec.
super updateForSpawnMethod: sourceSpec.
name := nm.!
----- Method: MetacelloProjectReferenceSpec>>updatePackageSpec:using: (in category '*metacello-mc') -----
updatePackageSpec: updatedSpecs using: anMCLoader
"Add project copy to updatedSpecs if the current version of the project
is different from the receiver's version"
self projectReference updatePackageSpec: updatedSpecs!
----- Method: MetacelloProjectReferenceSpec>>versionString (in category '*metacello-mc') -----
versionString
^self projectReference versionString!
----- Method: MCFileBasedRepository>>versionInfoFromVersionNamed: (in category '*metacello-mc') -----
versionInfoFromVersionNamed: aString
| versions |
versions := self allVersionNames
select: [ :each | each beginsWith: aString ].
versions isEmpty ifTrue: [ ^ nil ].
versions := versions asSortedCollection: [ :a :b |
([ (a copyAfterLast: $.) asNumber ] on: Error do: [:ex | ex return: 0 ]) <=
([ (b copyAfterLast: $.) asNumber ] on: Error do: [:ex | ex return: 0 ]) ].
^ self versionInfoFromFileNamed: versions last , '.mcz'!
----- Method: MCRepository>>asRepositorySpecFor: (in category '*metacello-mc') -----
asRepositorySpecFor: aMetacelloMCProject
self subclassResponsibility!
----- Method: MCRepository>>cacheReferences (in category '*metacello-mc') -----
cacheReferences
^ true!
----- Method: MCRepository>>metacelloProjectClassFor: (in category '*metacello-mc') -----
metacelloProjectClassFor: aScriptEngine
^ MetacelloMCProject!
----- Method: MCRepository>>projectVersion: (in category '*metacello-mc') -----
projectVersion: aString
"noop"!
More information about the Squeak-dev
mailing list
|