core/MetacelloAbstractVersionConstructor.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Tue, 18 Sep 2012 18:24:44 +0000
changeset 16 25ac697dc747
parent 14 f01fe37493e9
permissions -rw-r--r--
- Updated from branch master

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

MetacelloAbstractConstructor subclass:#MetacelloAbstractVersionConstructor
	instanceVariableNames:'root configuration project attributeMap attributeOrder
		symbolicVersion currentContext'
	classVariableNames:''
	poolDictionaries:''
	category:'Metacello-Core-Constructors'
!


!MetacelloAbstractVersionConstructor class methodsFor:'method generation'!

symbolicMethodSelectorAndPragma: selector symbolicVersionSymbol: symbolicVersionSymbol on: strm
	strm
		nextPutAll: selector asString , ' spec';
		cr;
		tab;
		nextPutAll: '<symbolicVersion: #' , symbolicVersionSymbol asString printString;
		nextPutAll: '>';
		cr
! !

!MetacelloAbstractVersionConstructor methodsFor:'accessing'!

addAttribute: anAttribute

	self attributeOrder add: anAttribute
!

attributeMap

	attributeMap == nil ifTrue: [ attributeMap := Dictionary new ].
	^attributeMap
!

attributeOrder

	attributeOrder == nil ifTrue: [ attributeOrder := OrderedCollection new ].
	^attributeOrder
!

configuration

	^configuration
!

configuration: aConfig

	configuration := aConfig
!

configurationClass

	^self configuration class
!

project
    ^project

    "Created: / 18-09-2012 / 19:08:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

root

	^root
!

root: aMetacelloSpec
    root := aMetacelloSpec
!

setProject: aProject

	project := aProject
!

symbolicVersion

	^symbolicVersion
!

symbolicVersion: aSymbol

	symbolicVersion := aSymbol
! !

!MetacelloAbstractVersionConstructor methodsFor:'api'!

author: aBlockOrString
    "Define author field of version spec (MetacelloMCVersionSpec).
	 If <aBlockOrString> is a String, the version spec author is set to the String.
	If <aBlockOrString> is a Block, the specifications in <aBlockOrString> are applied to the author spec (MetacelloValueHolderSpec). Not Recommended!!
	
		spec author: 'dkh'.
		
		spec author: [
			spec value: 'dkh'. ].
	 "

    self root author: aBlockOrString constructor: self
!

baseline: aString
    self root baseline: aString constructor: self
!

baseline: aString with: aBlockOrString
    self root baseline: aString with: aBlockOrString constructor: self
!

blessing: aBlockOrString
    "Define blessing field of version spec (MetacelloMCVersionSpec).
	 If <aBlockOrString> is a String, the version spec blessing is set to the String. It is recommended to use a Symbol.
	If <aBlockOrString> is a Block, the specifications in <aBlockOrString> are applied to the blessing spec (MetacelloValueHolderSpec). Not Recommended!!
	
		spec blessing: #release.
		
		spec blessing: [
			spec value: #release. ].
	
	The blessing should typically be set to one of three values:
		#baseline - indicating that the version spec is specifying a baseline version
		#development - indicating that the version spec is not stabilized and will change over time
		#release - indicating that the version spec has stabilized and will NOT change over time
	 "

    self root blessing: aBlockOrString constructor: self
!

className: aString
    "Define className field of a project spec (MetacelloMCProjectSpec).
	
		spec project: 'CoolBrowser' with: [
			spec className: 'ConfigurationOfCoolBrowser'. ].

	The className field is OPTIONAL in the project spec. If omitted, the className will be created by prepending 'ConfigurationOf' to the project name.
	 "

    self root className: aString constructor: self
!

configuration: aString with: aBlockOrString
    self root configuration: aString with: aBlockOrString constructor: self
!

description: aBlockOrString
    "Define description field of version spec (MetacelloMCVersionSpec).
	 If <aBlockOrString> is a String, the version spec blessing is set to the String. It is recommended to use a Symbol.
	If <aBlockOrString> is a Block, the specifications in <aBlockOrString> are applied to the blessing spec (MetacelloValueHolderSpec). Not Recommended!!
	
		spec description: 'Descriptive comment'.
		
		spec description: [
			spec value: 'Descriptive comment'.
	 "

    self root description: aBlockOrString constructor: self
!

file: aString
    "Define file field of a package spec (MetacelloPackageSpec) or project spec (MetacelloMCProjectSpec).

	For a package spec, the file: field is optional in a baseline. In a baseline, the file field may be used to specify a package branch for the package:
	
		spec package: 'MyPackage' with: [
			spec file: 'MyPackage.gemstone'. ]'.

	The file: field is required in a version. In a version, the file field defines the explicit version of the package to be loaded:
	
		spec package: 'MyPackage' with: [
			spec file: 'MyPackage.gemstone-dkh.1'. ]'.

	The following may be used as a short cut for specifying the file field in a version:

		spec package: 'MyPackage' with: 'MyPackage.gemstone-dkh.1'.

	For a project spec, the file field specifies the name of the Monticello package that contains the configuration. If you are using the convention of 
	naming the class and package usingthe  'ConfigurationOf' prefix, then there is no need to specify the file field:
	
		spec project: 'MyProject' with: [
			spec file: 'ConfigurationMyProject'.

	It should only be used when the package name for the configuration is different from the name of the project:

		spec project: 'MyProject' with: [
			spec file: 'MyProject-Metacello'.
	 "

    self root file: aString constructor: self
!

for: attribute do: aBlock
	"conditional version support"

	| blockList |
	blockList := self attributeMap
		at: attribute
		ifAbsent: [ self attributeMap at: attribute put: (blockList := OrderedCollection new) ].
	blockList add: aBlock.
	self addAttribute: attribute
!

for: attribute version: aString
	"conditional symbolicVersion support"

	self attributeMap at: attribute put: aString.
	self addAttribute: attribute
!

group: aString overrides: aStringOrCollection
    self root group: aString overrides: aStringOrCollection constructor: self
!

group: aString with: aStringOrCollection
    self root group: aString with: aStringOrCollection constructor: self
!

import: aString
    "import names defined in baseline <aString> to be used when loading the version

		spec baseline: 'Sample' with: [ spec repository: 'github://dalehenrich/sample:master/repository' ].
		spec import: 'Sample' ]
	 "

    self root import: aString constructor: self
!

includes: anObject
    self root includes: anObject constructor: self
!

loads: anObject
    self root loads: anObject constructor: self
!

name: anObject
    self root name: anObject constructor: self
!

operator: anObject
    self root operator: anObject constructor: self
!

package: aString
    self root package: aString constructor: self
!

package: aString overrides: aBlock
    self root package: aString overrides: aBlock constructor: self
!

package: packageName with: aBlockOrString
    "Define specification for package <packageName>.
	 If <aBlockOrString> is a String (or Symbol), the String is expected to be a version (or symbolic version).
	If <aBlockOrString> is a Block, the specifications in <aBlockOrString> are applied to the project:
	
		spec package: 'MyPackage' with: '1.0'.
		
		spec package: 'MyPackage' with: [
			spec file:'MyPackage-dkh.1'.
			spec repository: '/opt/gemstone/repository'.
	 "

    self root package: packageName with: aBlockOrString constructor: self
!

postLoadDoIt: aSymbol
    self root postLoadDoIt: aSymbol constructor: self
!

preLoadDoIt: aSymbol
    self root preLoadDoIt: aSymbol constructor: self
!

project: aString
    self root project: aString constructor: self
!

project: aString copyFrom: oldSpecName with: aBlock
    self root
        project: aString
        copyFrom: oldSpecName
        with: aBlock
        constructor: self
!

project: aString overrides: aBlock
    self root project: aString overrides: aBlock constructor: self
!

project: aString with: aBlockOrString
    self root project: aString with: aBlockOrString constructor: self
!

projectPackage: aBlock
    "projectPackage spec data folded into project spec"

    self root projectPackage: aBlock constructor: self
!

removeGroup: aString
    self root removeGroup: aString constructor: self
!

removePackage: aString
    self root removePackage: aString constructor: self
!

removeProject: aString
    self root removeProject: aString constructor: self
!

repositories: aBlock
    self root repositories: aBlock constructor: self
!

repository: anObject
    self root repository: anObject constructor: self
!

repository: description username: username password: password
    self root
        repository: description
        username: username
        password: password
        constructor: self
!

requires: anObject
    self root requires: anObject constructor: self
!

supplyingAnswers: aCollection
    self root supplyingAnswers: aCollection constructor: self
!

timestamp: aBlockOrStringOrDateAndTime
    "Define timestamp field of version spec (MetacelloMCVersionSpec).
	 If <aBlockOrStringOrDateAndTime> is a String, the version spec timetamp is set to the String.
	 If <aBlockOrStringOrDateAndTime> is a DateAndTime, the version spec timetamp is set to the printString of the DateAndTime.
	If <aBlockOrStringOrDateAndTime> is a Block, the specifications in <aBlockOrStringOrDateAndTime> are applied to the timestamp spec (MetacelloValueHolderSpec). Not Recommended!!
	
		spec timestamp: '10/7/2009 14:40'.
		
		spec timestamp: DateAndTime now'.
		
		spec timestamp: [
			spec value: '10/7/2009 14:40'. ].
    "

    self root timestamp: aBlockOrStringOrDateAndTime constructor: self
!

value: anObject
    self root value: anObject constructor: self
!

version: anObject
    self root version: anObject constructor: self
!

versionString: anObject
    self root versionString: anObject constructor: self
! !

!MetacelloAbstractVersionConstructor methodsFor:'api callbacks'!

setAuthorWithBlock: aBlock

	| spec |
	(spec := self root getAuthor) == nil
		ifTrue: [ 
			spec := self project valueHolderSpec.
			self root setAuthor: spec ].
	self with: spec during: aBlock
!

setAuthorWithString: aString

	self root author: aString
!

setBaseline: aString
    | spec projectSpec |
    projectSpec := self project baselineOfProjectSpec
        name: aString;
        className: 'BaselineOf' , aString;
        yourself.
    spec := self project projectReferenceSpec
        name: aString;
        projectReference: projectSpec;
        yourself.
    self root packages merge: spec.
    ^ projectSpec
!

setBaseline: aString withBlock: aBlock
    | projectSpec |
    projectSpec := self setBaseline: aString.
    self with: projectSpec during: aBlock
!

setBlessingWithBlock: aBlock

	| spec |
	(spec := self root getBlessing) == nil
		ifTrue: [ 
			spec := self project valueHolderSpec.
			self root setBlessing: spec ].
	self with: spec during: aBlock
!

setBlessingWithString: aString

	self root blessing: aString
!

setConfiguration: aString withBlock: aBlock
    | spec projectSpec |
    projectSpec := self project configurationOfProjectSpec
        name: aString;
        yourself.
    spec := self project projectReferenceSpec
        name: aString;
        projectReference: projectSpec;
        yourself.
    self root packages merge: spec.
    self with: projectSpec during: aBlock
!

setDescriptionWithBlock: aBlock

	| spec |
	(spec := self root getDescription) == nil
		ifTrue: [ 
			spec := self project valueHolderSpec.
			self root setDescription: spec ].
	self with: spec during: aBlock
!

setDescriptionWithString: aString

	self root description: aString
!

setPackage: aString withBlock: aBlock

	| spec |
	spec := 
		(self project packageSpec)
			name: aString;
			yourself.
	self root packages merge: spec.
	self with: spec during: aBlock
!

setPackage: aString withString: aFile

	| spec |
	spec := 
		(self project packageSpec)
			name: aString;
			file: aFile;
			yourself.
	self root packages merge: spec.
!

setProject: aString withBlock: aBlock
    | spec projectSpec |
    projectSpec := self project projectSpec
        name: aString;
        yourself.
    spec := self project projectReferenceSpec
        name: aString;
        projectReference: projectSpec;
        yourself.
    self root packages merge: spec.
    self with: projectSpec during: aBlock
!

setProject: aString withString: versionString

	| spec projectSpec |
	projectSpec := 
		(self project projectSpec)
			name: aString;
			versionString: versionString;
			yourself.
	spec := 
		(self project projectReferenceSpec)
			name: aString;
			projectReference: projectSpec;
			yourself.
	self root packages merge: spec.
!

setTimestampWithBlock: aBlock

	| spec |
	(spec := self root getTimestamp) == nil
		ifTrue: [ 
			spec := self project valueHolderSpec.
			self root setTimestamp: spec ].
	self with: spec during: aBlock
!

setTimestampWithString: aString

	self root timestamp: aString
! !

!MetacelloAbstractVersionConstructor methodsFor:'api spec callbacks'!

authorForVersion: aBlockOrString
    aBlockOrString setAuthorInMetacelloConfig: self
!

baselineForVersion: aString
    self setBaseline: aString
!

baselineForVersion: aString with: aBlock
    aBlock setBaseline: aString withInMetacelloConfig: self
!

blessingForVersion: aBlockOrString
    aBlockOrString setBlessingInMetacelloConfig: self
!

classNameForProject: aString
    self root className: aString
!

configurationForVersion: aString with: aBlock
    aBlock setConfiguration: aString withInMetacelloConfig: self
!

descriptionForVersion: aBlockOrString
    aBlockOrString setDescriptionInMetacelloConfig: self
!

fileForPackage: aString
    self root file: aString
!

fileForProject: aString
    self root file: aString
!

groupForVersion: aString overrides: aStringOrCollection
    | spec |
    spec := self project groupSpec
        name: aString;
        includes: aStringOrCollection;
        yourself.
    self root packages add: spec
!

groupForVersion: aString with: aStringOrCollection
    | spec |
    spec := self project groupSpec
        name: aString;
        includes: aStringOrCollection;
        yourself.
    self root packages merge: spec
!

importForVersion: aString
    self root import: aString
!

includesForPackage: anObject
    self root includes: anObject
!

loadsForProject: anObject
    self root loads: anObject
!

nameForProject: aString
    self root name: aString
!

operatorForProject: anObject
    self root operator: anObject
!

packageForVersion: aString
    | spec |
    spec := self project packageSpec
        name: aString;
        yourself.
    self root packages add: spec
!

packageForVersion: aString overrides: aBlock
    | spec |
    spec := self project packageSpec
        name: aString;
        yourself.
    self root packages add: spec.
    self with: spec during: aBlock
!

packageForVersion: packageName with: aBlockOrString
    aBlockOrString setPackage: packageName withInMetacelloConfig: self
!

postLoadDoItForPackage: aSymbol
    self postLoadDoItForSpec: aSymbol
!

postLoadDoItForProject: aSymbol
    self postLoadDoItForSpec: aSymbol
!

postLoadDoItForSpec: aSymbol
    self validateDoItSelector: aSymbol.
    self root postLoadDoIt: aSymbol
!

postLoadDoItForVersion: aSymbol
    self postLoadDoItForSpec: aSymbol
!

preLoadDoItForPackage: aSymbol
    self preLoadDoItForSpec: aSymbol
!

preLoadDoItForProject: aSymbol
    self preLoadDoItForSpec: aSymbol
!

preLoadDoItForSpec: aSymbol
    self validateDoItSelector: aSymbol.
    self root preLoadDoIt: aSymbol
!

preLoadDoItForVersion: aSymbol
    self preLoadDoItForSpec: aSymbol
!

projectForVersion: aString
    self project: aString with: ''
!

projectForVersion: aString copyFrom: oldSpecName with: aBlock
    | spec projectSpec |
    projectSpec := self project projectSpec
        name: aString;
        yourself.
    spec := self project projectReferenceSpec
        name: aString;
        projectReference: projectSpec;
        yourself.
    self root packages copy: oldSpecName to: spec.
    self with: projectSpec during: aBlock
!

projectForVersion: aString overrides: aBlock
    | spec projectSpec |
    projectSpec := self project projectSpec
        name: aString;
        yourself.
    spec := self project projectReferenceSpec
        name: aString;
        projectReference: projectSpec;
        yourself.
    self root packages add: spec.
    self with: projectSpec during: aBlock
!

projectForVersion: aString with: aBlockOrString
    aBlockOrString setProject: aString withInMetacelloConfig: self
!

projectPackageForProject: aBlock
    self with: self root during: aBlock
!

removeGroupForVersion: aString
    | spec |
    spec := self project groupSpec
        name: aString;
        yourself.
    self root packages remove: spec
!

removePackageForVersion: aString
    | spec |
    spec := self project packageSpec
        name: aString;
        yourself.
    self root packages remove: spec
!

removeProjectForVersion: aString
    | spec |
    spec := self project projectReferenceSpec
        name: aString;
        yourself.
    self root packages remove: spec
!

repositoriesForPackage: aBlock
    self repositoriesForSpec: aBlock
!

repositoriesForProject: aBlock
    self repositoriesForSpec: aBlock
!

repositoriesForSpec: aBlock
    self with: self root repositories during: aBlock
!

repositoriesForVersion: aBlock
    self repositoriesForSpec: aBlock
!

repositoryForPackage: anObject
    self repositoryForSpec: anObject
!

repositoryForPackage: aString username: username password: password
    self repositoryForSpec: aString username: username password: password
!

repositoryForProject: anObject
    self repositoryForSpec: anObject
!

repositoryForProject: aString username: username password: password
    self repositoryForSpec: aString username: username password: password
!

repositoryForRepositories: anObject
    self repositoryForSpec: anObject
!

repositoryForRepositories: aString username: username password: password
    self repositoryForVersion: aString username: username password: password
!

repositoryForSpec: anObject
    self root repository: anObject
!

repositoryForSpec: aString username: username password: password
    self root repository: aString username: username password: password
!

repositoryForVersion: anObject
    self repositoryForSpec: anObject
!

repositoryForVersion: aString username: username password: password
    self repositoryForSpec: aString username: username password: password
!

requiresForPackage: anObject
    self root requires: anObject
!

supplyingAnswersForPackage: anObject
    self root answers: anObject
!

timestampForVersion: aBlockOrStringOrDateAndTime
    aBlockOrStringOrDateAndTime setTimestampInMetacelloConfig: self
!

valueForValueHolder: anObject
    self root value: anObject
!

versionForProject: anObject
    self versionStringForProject: anObject
!

versionForVersion: anObject
    self versionStringForVersion: anObject
!

versionStringForProject: anObject
    self root versionString: anObject
!

versionStringForVersion: anObject
    self versionStringForProject: anObject
! !

!MetacelloAbstractVersionConstructor methodsFor:'initialization'!

reset
    attributeMap := attributeOrder := nil
! !

!MetacelloAbstractVersionConstructor methodsFor:'private'!

evaluatePragma: pragma
	currentContext := pragma.
	[ self configuration perform: pragma selector with: self ] ensure: [ currentContext := nil ]
!

with: aMetacelloSpec during: aBlock
    | previousRoot |
    previousRoot := self root.
    self root: aMetacelloSpec.
    aBlock
        ensure: [ self root: previousRoot ]
! !

!MetacelloAbstractVersionConstructor methodsFor:'validation'!

validateDoItSelector: anObject

	anObject == nil ifTrue: [ ^ self ].
	anObject isSymbol ifFalse: [ self error: 'Invalid message selector for doit: ', anObject printString ].
! !

!MetacelloAbstractVersionConstructor class methodsFor:'documentation'!

version_SVN
    ^ '$Id::                                                                                                                        $'
! !