core/MetacelloProject.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Wed, 19 Sep 2012 01:38:26 +0000
changeset 20 8caf2f257260
parent 16 25ac697dc747
child 22 e1678fee6b03
permissions -rw-r--r--
- fixes for package support

"{ Package: 'stx:goodies/metacello/core' }"

Object subclass:#MetacelloProject
	instanceVariableNames:'versionMap symbolicVersionMap errorMap loader loaderClass
		loadType configuration projectAttributes versionNumberClass'
	classVariableNames:''
	poolDictionaries:''
	category:'Metacello-Core-Model'
!


!MetacelloProject class methodsFor:'instance creation'!

new

	| inst |
	inst := self basicNew.
	^inst configuration: inst; yourself
!

on: aConfig

	^self basicNew configuration: aConfig; yourself
! !

!MetacelloProject class methodsFor:'accessing'!

versionConstructorClass
    ^ MetacelloVersionConstructor
! !

!MetacelloProject methodsFor:'accessing'!

configuration
	^ configuration
!

configuration: anObject
	configuration := anObject
!

defaultBlessing

	^#release
!

errorMap
	^ errorMap
!

errorMap: anObject
    errorMap ifNil: [ errorMap := Dictionary new ].
    errorMap := anObject
!

label

	^self configuration class name
!

loadType
	"#atomic or #linear"

	loadType == nil ifTrue: [ ^#atomic ].
	^loadType
!

loadType: aSymbol
	"#atomic or #linear"

	loadType := aSymbol
!

map
	versionMap ifNil: [ ^ Dictionary new ].
	^ versionMap
!

map: aDictionary

	versionMap := aDictionary
!

project

	^self
!

symbolicVersionMap

	^symbolicVersionMap
				
				
!

symbolicVersionMap: aDictionary

	symbolicVersionMap := aDictionary
				
				
! !

!MetacelloProject methodsFor:'loading'!

load: aVersionString

	^(self version: aVersionString) load
! !

!MetacelloProject methodsFor:'printing'!

printOn: aStream
	| label |
	self configuration class printOn: aStream.
	aStream nextPut: $(.
	self versions
		do: [ :vrsn | 
			aStream nextPutAll: vrsn versionString.
			vrsn spec ~~ nil
				ifTrue: [ 
					(label := vrsn spec projectLabel) isEmpty
						ifFalse: [ aStream nextPutAll: ' [' , label , ']' ] ].
			aStream
				nextPut: $,;
				space ].
	aStream nextPut: $)
! !

!MetacelloProject methodsFor:'private'!

attributes

	^(OrderedCollection with: #common)
		addAll: self platformAttributes;
		yourself
!

defaultPlatformAttributes

	^ MetacelloPlatform current defaultPlatformAttributes
!

excludeFromLatestVersion

	^#(development broken baseline)
!

lookupVersion: aVersionString ifAbsent: aBlock
    "please use version:...this is a private method"

    ^ self map
        at: aVersionString
        ifAbsent: [ 
            (MetacelloVersionDefinitionError project: self project versionString: aVersionString)
                exception: (self errorMap at: aVersionString ifAbsent: [ ^ aBlock value ]);
                raise ]

    "Modified: / 19-09-2012 / 02:14:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

platformAttributes

	 ^self projectPlatformAttributes
!

pragmaKeywords

	^#(version:attribute: blessing:attribute: description:attribute: required:attribute: groups:attribute: doits:attribute:)
!

projectAttributes

	projectAttributes ~~ nil ifTrue: [ ^projectAttributes ].
	^#()
!

projectAttributes: aList

	projectAttributes := aList
!

projectPlatformAttributes

	| list aBlock |
	list := OrderedCollection new.
	(aBlock := self projectAttributes) ~~ nil 
		ifTrue: [ list addAll: aBlock value ].
	^self defaultPlatformAttributes, list
!

sortedAndFilteredVersions

		^(self map values asArray sort: [:a :b | a >= b ]) select: [:vrsn | (#(broken baseline) includes: vrsn blessing) not ].
! !

!MetacelloProject methodsFor:'scripting'!

projectForScriptEngine: aMetacelloScriptEngine
    ^ self projectForScriptEngine: aMetacelloScriptEngine unconditionalLoad: false
!

projectForScriptEngine: aMetacelloScriptEngine unconditionalLoad: aBool
    ^ self subclassResponsibility
! !

!MetacelloProject methodsFor:'spec classes'!

baselineOfProjectSpec
    ^ self baselineOfProjectSpecClass for: self
!

baselineOfProjectSpecClass
    ^ self subclassResponsibility
!

baselineOfVersionSpecClass
    ^ self subclassResponsibility
!

configurationOfProjectSpec
    ^ self configurationOfProjectSpecClass for: self
!

configurationOfProjectSpecClass
    ^ self subclassResponsibility
!

defaultLoaderClass

	^MetacelloSpecLoader
!

groupSpec

	^self groupSpecClass for: self
!

groupSpecClass

	^MetacelloGroupSpec
!

loader

	^loader
!

loader: aLoader

	loader := aLoader
!

loaderClass

	loaderClass == nil ifTrue: [ loaderClass := self defaultLoaderClass ].
	^loaderClass
!

loaderClass: aMetacelloSpecLoader

	loaderClass := aMetacelloSpecLoader
!

packagesSpec

	^self packagesSpecClass for: self
!

packagesSpecClass

	^MetacelloPackagesSpec
!

projectReferenceSpec

	^self projectReferenceSpecClass for: self
!

projectReferenceSpecClass

	^MetacelloProjectReferenceSpec
!

projectSpec

	^self projectSpecClass for: self
!

projectSpecClass
    ^ MetacelloProjectSpec
!

valueHolderSpec

	^self valueHolderSpecClass for: self
!

valueHolderSpecClass

	^MetacelloValueHolderSpec
!

versionSpec

	^self versionSpecClass for: self
!

versionSpecClass

	^MetacelloVersionSpec
! !

!MetacelloProject methodsFor:'versions'!

bleedingEdge

	^self version: #bleedingEdge
!

currentVersion
	| cacheKey cv |
	cacheKey := self configuration class.
	^ MetacelloPlatform current
		stackCacheFor: #currentVersion
		at: cacheKey
		doing: [ :cache | 
			cv := self currentVersionAgainst: nil.
			^ cache at: cacheKey put: cv ]
!

currentVersionAgainst: resolvedPackageAndProjectNames
	| cacheKey |
	cacheKey := resolvedPackageAndProjectNames isNil
		ifTrue: [ Array with: self configuration class with: nil ]
		ifFalse: [ Array with: self configuration class with: (resolvedPackageAndProjectNames sort: [ :a :b | a <= b ]) ].
	^ MetacelloPlatform current
		stackCacheFor: #currentVersionAgainst:
		at: cacheKey
		doing: [ :cache | 
			| cv versions latestSomethingLoaded |
			cv := nil.
			versions := self sortedAndFilteredVersions.
			versions
				do: [ :version | 
					| status matchBlock |
					status := resolvedPackageAndProjectNames isNil
						ifTrue: [ version spec isPartiallyCurrent ]
						ifFalse: [ version spec isPartiallyCurrentAgainst: resolvedPackageAndProjectNames ].
					matchBlock := [ :matchStatus | 
					cv := version copy.
					cv versionStatus: matchStatus.
					^ cache at: cacheKey put: cv ].
					status isAllLoadedToSpec: matchBlock.
					status isLoadedToSpec: matchBlock.
					status isLoadedMatchConstraints: matchBlock.
					status
						isSomethingLoaded: [ :matchStatus | 
							latestSomethingLoaded isNil
								ifTrue: [ 
									cv := version copy.
									cv versionStatus: matchStatus.
									latestSomethingLoaded := cv ] ] ].
			latestSomethingLoaded ifNotNil: [ ^ cache at: cacheKey put: latestSomethingLoaded ].
			^ cache at: cacheKey put: nil ]
!

development

	^self version: #development
!

hasVersion: versionString

	self version: versionString ifAbsent: [ ^false ].
	^true
!

lastVersion

	| coll |
	coll := (self map values asArray sort: [:a :b | a <= b ]) asOrderedCollection.
	coll isEmpty ifTrue: [ ^nil ].
	^coll last
!

latestVersion

	| excluded |
"	self deprecated: 'Please use #stableVersion instead.'.
"	self flag: 'deprecate after version 1.0'.
	excluded := self excludeFromLatestVersion.
	^(self map values select: [:version |  
		(excluded includes: version blessing) not ]) detectMax: [:version | version ]
!

latestVersion: blessing

	^(self map values select: [:version | blessing = version blessing ]) detectMax: [:version | version ]
!

latestVersionMatching: versionPatternString
	"Answer whether the version number of the receiver matches the given pattern string.

	 A Metacello version number is made up of version sequences delimited by the characters $. and $-.
	 The $. introduces a numeric version sequence and $- introduces an alphanumeric version sequence.
	 
	 A version pattern is made up of version pattern match sequences. also delimited by the characters $. 
	 and $-.. Each pattern match sequence is tested against the corresponding version sequence of the 
	 receiver, using the 'standard' pattern matching rules. All sequences must answer true for a match.
	
	 The special pattern sequence '?' is a match for the corresponding version sequence and all subsequent 
	 version sequences. '?' as the version pattern matches all versions. No more version pattern 
	 sequences are permitted once the '?' sequence is used. If used, it is the last version pattern
	 sequence."

	^self 
		latestVersionMatching: versionPatternString 
		includedBlessings: #()
		excludedBlessings: self excludeFromLatestVersion
!

latestVersionMatching: versionPatternString excludedBlessings: excluded

	^self 
		latestVersionMatching: versionPatternString 
		includedBlessings: #()
		excludedBlessings: excluded
!

latestVersionMatching: versionPatternString includedBlessings: included

	^self 
		latestVersionMatching: versionPatternString 
		includedBlessings: included
		excludedBlessings: self excludeFromLatestVersion
!

latestVersionMatching: versionPatternString includedBlessings: included excludedBlessings: excludedBlessings

	| excluded |
	excluded := excludedBlessings asSet copy.
	excluded removeAllFoundIn: included.
	^(self map values select: [:version |
		(included isEmpty or: [ included includes: version blessing ]) 
			and: [ (excluded includes: version blessing) not 
				and: [ version versionNumber match: versionPatternString ]]])
		detectMax: [:version | version ]
!

stableVersion

	^self version: #stable
!

symbolicVersionSymbols

	^self symbolicVersionMap keys asArray sort: [:a :b | a <= b ]
!

version: aVersionString
    | vrsn |
    aVersionString isSymbol
        ifTrue: [ 
            | symbolicVersionString |
            symbolicVersionString := self symbolicVersionMap
                at: aVersionString
                ifAbsent: [ (MetacelloSymbolicVersionDoesNotExistError project: self project versionString: aVersionString) signal ].
            symbolicVersionString == #'notDefined'
                ifTrue: [ (MetacelloSymbolicVersionNotDefinedError project: self project versionString: aVersionString) signal ].
            ^ self
                lookupVersion: symbolicVersionString
                ifAbsent: [ (MetacelloSymbolicVersionDoesNotExistError project: self project versionString: symbolicVersionString) signal ] ].
    ^ self
        lookupVersion: aVersionString
        ifAbsent: [ (MetacelloVersionDoesNotExistError project: self project versionString: aVersionString) signal ]
!

version: aVersionString ifAbsent: aBlock

	^[ self version: aVersionString ] on: MetacelloVersionDoesNotExistError do: [:ex | aBlock value ].
!

versionNumberClass
    versionNumberClass ifNil: [ versionNumberClass := MetacelloVersionNumber ].
    ^ versionNumberClass
!

versionNumberClass: aClass
    versionNumberClass := aClass
!

versions

	^self map values asArray sort: [:a :b | a <= b ]
! !

!MetacelloProject class methodsFor:'documentation'!

version_SVN
    ^ '$Id::                                                                                                                        $'
! !