SystemOrganization addCategory: #'Package-Builder-Model'! SystemOrganization addCategory: #'Package-Builder-View'! !String methodsFor: '*package-builder' stamp: 'lr 11/29/2008 12:42'! addToSource: aSource ^ (PackageOrganizer default packageNamed: self ifAbsent: [ self error: 'Unknown package named ' , self printString ]) addToSource: aSource! ! !WAPackage methodsFor: '*package-builder' stamp: 'jf 3/15/2009 16:59'! addToSource: aSource | package | package := PBPackage new title: self name; name: self name; comment: self description; addToSource: aSource. self dependencies do: [ :each | package addDependency: (aSource addPackage: each) ]. ^ package addToSource: aSource! ! WAComponent subclass: #PBBuilderComponent instanceVariableNames: 'children view model selected dependent url' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-View'! PBBuilderComponent class instanceVariableNames: 'distributions'! PBBuilderComponent class instanceVariableNames: 'distributions'! !PBBuilderComponent class methodsFor: 'accessing' stamp: 'lr 12/18/2008 16:16'! distributions ^ distributions ifNil: [ distributions := PBSource load ]! ! !PBBuilderComponent class methodsFor: 'initialization' stamp: 'lr 3/2/2009 12:30'! flush distributions := nil! ! !PBBuilderComponent class methodsFor: 'initialization' stamp: 'lr 3/24/2009 16:46'! initialize | application | application := self registerAsApplication: 'builder'. application configuration at: #resourceBaseUrl put: 'http://builder.seaside.st/' seasideUrl. application addLibrary: JQGoogleLibrary; addLibrary: JQUiGoogleLibrary! ! !PBBuilderComponent class methodsFor: 'initialization' stamp: 'lr 3/24/2009 16:46'! initializeDeployment | application | application := self registerAsApplication: 'builder'. application configuration addParent: WAExceptionFilterConfiguration instance; at: #serverPath put: '/'; at: #rootDecorationClasses put: #(); at: #exceptionHandler put: WAExceptionHandler; at: #libraries put: (Array with: JQGoogleLibrary with: JQUiGoogleLibrary); at: #resourceBaseUrl put: 'http://builder.seaside.st/' seasideUrl! ! !PBBuilderComponent methodsFor: 'actions' stamp: 'lr 2/21/2009 09:39'! addAll: aCollection selected addAll: aCollection. self refresh! ! !PBBuilderComponent methodsFor: 'accessing-dynamic' stamp: 'lr 2/10/2009 21:40'! base ^ self model class baseUrl , '/' , self model name , '/'! ! !PBBuilderComponent methodsFor: 'accessing-dynamic' stamp: 'lr 2/21/2009 00:01'! children ^ children! ! !PBBuilderComponent methodsFor: 'accessing' stamp: 'lr 10/18/2008 15:08'! dependent ^ dependent! ! !PBBuilderComponent methodsFor: 'accessing' stamp: 'lr 11/30/2008 12:32'! dependent: aCollection dependent := aCollection asSet! ! !PBBuilderComponent methodsFor: 'accessing-dynamic' stamp: 'lr 12/18/2008 16:17'! distributions ^ self class distributions! ! !PBBuilderComponent methodsFor: 'actions' stamp: 'lr 2/10/2009 21:39'! download: aBuilder self requestContext response document: (aBuilder build: self model selected: self ordered base: self base url: self url); respond! ! !PBBuilderComponent methodsFor: 'initialization' stamp: 'lr 3/24/2009 15:28'! initialRequest: aRequest super initialRequest: aRequest. aRequest fields at: 'distribution' ifPresent: [ :value | self parseDistributions: value ]. aRequest fields at: 'packages' ifPresent: [ :value | self parsePackages: value ]. aRequest fields at: 'download' ifPresent: [ :value | self parseDownload: value ]! ! !PBBuilderComponent methodsFor: 'initialization' stamp: 'lr 2/21/2009 11:34'! initialize super initialize. self dependent: #(). self selected: #(). children := Array with: (PBSimpleView on: self) with: (PBAdvancedView on: self). view := children first! ! !PBBuilderComponent methodsFor: 'testing' stamp: 'lr 10/4/2008 22:38'! isChecked: aPackage ^ dependent includes: aPackage! ! !PBBuilderComponent methodsFor: 'testing' stamp: 'lr 10/4/2008 22:56'! isDisabled: aPackage (selected includes: aPackage) ifTrue: [ ^ false ]. (dependent includes: aPackage) ifTrue: [ ^ true ]. ^ false ! ! !PBBuilderComponent methodsFor: 'accessing' stamp: 'lr 12/18/2008 16:25'! model ^ model ifNil: [ model := self distributions last ]! ! !PBBuilderComponent methodsFor: 'accessing' stamp: 'lr 12/18/2008 16:25'! model: aSource self initialize. model := aSource! ! !PBBuilderComponent methodsFor: 'accessing-dynamic' stamp: 'lr 12/13/2008 12:58'! ordered "Answer all the packages in the order they should be loaded." | result | result := OrderedCollection new: self dependent size. self selected do: [ :package | package addDependenciesTo: result ]. ^ result asArray! ! !PBBuilderComponent methodsFor: 'initialization' stamp: 'lr 3/24/2009 15:49'! parseDistributions: aString self distributions do: [ :each | each titleAndVersion = aString ifTrue: [ self model: each ] ]! ! !PBBuilderComponent methodsFor: 'initialization' stamp: 'lr 3/24/2009 15:49'! parseDownload: aString | builder | dependent isEmpty ifTrue: [ ^ self ]. PBBuilder allSubclasses do: [ :class | ((builder := class new) title sameAs: aString) ifTrue: [ self session unregister. self download: builder ] ]! ! !PBBuilderComponent methodsFor: 'initialization' stamp: 'lr 3/24/2009 15:28'! parsePackages: aString | package | (aString findTokens: $,) do: [ :name | package := self model packageNamed: name ifAbsent: [ nil ]. package isNil ifFalse: [ self selected add: package. view := self children second ] ]. self refresh! ! !PBBuilderComponent methodsFor: 'actions' stamp: 'lr 11/30/2008 13:31'! refresh dependent := Set new. selected do: [ :package | package addDependenciesTo: dependent ]! ! !PBBuilderComponent methodsFor: 'actions' stamp: 'lr 2/21/2009 09:46'! removeAll: aCollection aCollection do: [ :each | selected remove: each ifAbsent: [ ] ]. self refresh! ! !PBBuilderComponent methodsFor: 'rendering' stamp: 'lr 3/2/2009 12:05'! renderBodyOn: html self renderIntroOn: html. self renderTabsOn: html! ! !PBBuilderComponent methodsFor: 'rendering' stamp: 'lr 12/30/2008 18:11'! renderContentOn: html url := html context actionUrl withoutParameters. html div id: 'page'; with: [ html div id: 'header'; with: [ self renderHeaderOn: html ]. html div id: 'content'; with: [ self renderBodyOn: html ]. html div id: 'footer'; with: [ self renderFooterOn: html ] ]! ! !PBBuilderComponent methodsFor: 'rendering' stamp: 'lr 3/2/2009 12:18'! renderFooterOn: html! ! !PBBuilderComponent methodsFor: 'rendering' stamp: 'lr 12/29/2008 23:18'! renderHeaderOn: html! ! !PBBuilderComponent methodsFor: 'rendering' stamp: 'lr 2/21/2009 00:05'! renderIntroOn: html html paragraph: [ self distributions size = 1 ifTrue: [ html text: 'You are downloading '; text: self model titleAndVersion; text: '.' ] ifFalse: [ html form: [ html text: 'Select the distribution of your choice: '. html select selected: self model; onChange: 'submit()'; list: self distributions; labels: [ :value | value titleAndVersion ]; callback: [ :value | self model: value ] ] ] ]! ! !PBBuilderComponent methodsFor: 'rendering' stamp: 'lr 3/24/2009 16:47'! renderTabsOn: html html div script: (html jQuery new tabs selected: (self children indexOf: self view) - 1); with: [ html unorderedList: [ self children do: [ :each | html listItem: [ html anchor url: (html jQuery ajax callback: [ view := each ]; html: [ :r | r render: each ]; fullUrl); with: each label ] ] ] ]! ! !PBBuilderComponent methodsFor: 'accessing-dynamic' stamp: 'lr 10/18/2008 15:08'! selected ^ selected! ! !PBBuilderComponent methodsFor: 'actions' stamp: 'lr 10/22/2008 21:51'! selected: aCollection selected := Set withAll: aCollection. self refresh! ! !PBBuilderComponent methodsFor: 'actions' stamp: 'lr 12/18/2008 16:31'! toggle: aPackage (self isChecked: aPackage) ifTrue: [ selected remove: aPackage ifAbsent: [ ] ] ifFalse: [ selected add: aPackage ]. self refresh! ! !PBBuilderComponent methodsFor: 'actions' stamp: 'lr 12/18/2008 16:54'! toggleAll: aCollection | count | count := aCollection count: [ :each | selected includes: each ]. count = aCollection size ifFalse: [ selected addAll: aCollection ] ifTrue: [ aCollection do: [ :each | selected remove: each ifAbsent: [ ] ] ]. self refresh! ! !PBBuilderComponent methodsFor: 'updating' stamp: 'lr 2/10/2009 18:50'! updateRoot: aHtmlRoot super updateRoot: aHtmlRoot. aHtmlRoot title: 'The Seaside Builder'. aHtmlRoot stylesheet resourceUrl: 'styles/baseline.css'. aHtmlRoot stylesheet resourceUrl: 'styles/builder.css'. aHtmlRoot script beJavascript; with: 'var gaJsHost=(("https:"==document.location.protocol)?"https://ssl.":"http://www.");document.write(unescape("%3Cscript src=''"+gaJsHost+"google-analytics.com/ga.js'' type=''text/javascript''%3E%3C/script%3E"));'. aHtmlRoot script beJavascript; with: 'try{var pageTracker=_gat._getTracker("UA-2075184-5");pageTracker._trackPageview();}catch(err){}' ! ! !PBBuilderComponent methodsFor: 'accessing-dynamic' stamp: 'lr 12/30/2008 18:23'! url url := url withoutParameters. url addParameter: 'distribution' value: self model titleAndVersion. url addParameter: 'packages' value: (String streamContents: [ :stream | self selected do: [ :each | stream nextPutAll: each title ] separatedBy: [ stream nextPut: $, ] ]). ^ url! ! !PBBuilderComponent methodsFor: 'accessing-dynamic' stamp: 'lr 2/21/2009 11:41'! view ^ view! ! WAComponent subclass: #PBBuilderView instanceVariableNames: 'component' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-View'! PBBuilderView subclass: #PBAdvancedView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-View'! !PBAdvancedView methodsFor: 'accessing' stamp: 'lr 2/20/2009 23:46'! label ^ 'Advanced'! ! !PBAdvancedView methodsFor: 'rendering' stamp: 'lr 3/2/2009 12:27'! renderContentOn: html html table: [ self model groupsDo: [ :group :packages | html tableRow: [ html tableHeading colSpan: 3; with: [ html anchor onClick: (html jQuery getScript script: [ :s | self toggleAll: packages; updateCheckboxesOn: s ]); with: group ] ]. packages do: [ :package | self renderPackage: package on: html ] ] ]. self renderDownload: 'Download' builders: ((PBBuilder allSubclasses collect: [ :each | each new ]) asSortedCollection: [ :a :b | a title < b title ]) on: html! ! !PBBuilderView class methodsFor: 'instance creation' stamp: 'lr 2/21/2009 00:02'! on: aComponent ^ self basicNew initializeOn: aComponent! ! !PBBuilderView methodsFor: 'actions' stamp: 'lr 2/21/2009 09:39'! addAll: aCollection self component addAll: aCollection! ! !PBBuilderView methodsFor: 'accessing' stamp: 'lr 2/21/2009 00:07'! component ^ component! ! !PBBuilderView methodsFor: 'initialization' stamp: 'lr 2/21/2009 00:01'! initializeOn: aComponent self initialize. component := aComponent! ! !PBBuilderView methodsFor: 'testing' stamp: 'lr 2/21/2009 00:09'! isChecked: aPackage ^ self component isChecked: aPackage! ! !PBBuilderView methodsFor: 'testing' stamp: 'lr 2/21/2009 00:09'! isDisabled: aPackage ^ self component isDisabled: aPackage! ! !PBBuilderView methodsFor: 'accessing' stamp: 'lr 2/20/2009 23:46'! label self subclassResponsibility! ! !PBBuilderView methodsFor: 'accessing' stamp: 'lr 2/21/2009 00:02'! model ^ component model! ! !PBBuilderView methodsFor: 'actions' stamp: 'lr 2/21/2009 09:40'! removeAll: aCollection self component removeAll: aCollection! ! !PBBuilderView methodsFor: 'rendering' stamp: 'lr 3/2/2009 12:29'! renderDownload: aString builders: anArray on: html html heading level: 3; with: aString. html unorderedList: [ anArray do: [ :each | html listItem: [ html anchor callback: [ self component download: each ]; with: each title. html html: ' — '. html text: each comment ] ] ]! ! !PBBuilderView methodsFor: 'rendering' stamp: 'lr 2/21/2009 09:38'! renderPackage: aPackage on: html html tableRow title: aPackage title; with: [ html tableData class: 'checkbox'; with: [ html checkbox id: aPackage id; value: (self isChecked: aPackage); disabled: (self isDisabled: aPackage); onChange: (html jQuery getScript script: [ :s | self toggle: aPackage. self updateCheckboxesOn: s ]) ]. html tableData class: 'title'; with: [ html label for: aPackage id; with: aPackage title ]. html tableData class: 'description'; with: aPackage comment ]! ! !PBBuilderView methodsFor: 'actions' stamp: 'lr 2/21/2009 00:10'! selected: aCollection self component selected: aCollection! ! !PBBuilderView methodsFor: 'actions' stamp: 'lr 2/21/2009 00:10'! toggle: aPackage self component toggle: aPackage! ! !PBBuilderView methodsFor: 'actions' stamp: 'lr 2/21/2009 00:10'! toggleAll: aCollection self component toggleAll: aCollection! ! !PBBuilderView methodsFor: 'scripts' stamp: 'lr 2/21/2009 09:14'! updateCheckboxesOn: aScript self model groupsDo: [ :group :packages | packages do: [ :package | aScript << (aScript jQuery id: package id) attributeAt: 'checked' put: (self isChecked: package); attributeAt: 'disabled' put: (self isDisabled: package) ] ]! ! PBBuilderView subclass: #PBSimpleView instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-View'! !PBSimpleView methodsFor: 'accessing' stamp: 'lr 3/2/2009 12:08'! builders ^ Array with: PBLoadScriptBuilder new with: PBConfigMapBuilder new! ! !PBSimpleView methodsFor: 'accessing' stamp: 'lr 2/20/2009 23:46'! label ^ 'Simple'! ! !PBSimpleView methodsFor: 'rendering' stamp: 'lr 3/2/2009 12:09'! renderAdaptorsOn: html | packages adaptors adaptor group | "1. add all the default packages" packages := #('Seaside-Development' 'Seaside-Slime' 'Seaside-Examples') collect: [ :each | self model packageNamed: each ]. self addAll: packages. "2. add a default server adaptor" adaptors := self model packages select: [ :each | (each name includesSubString: 'Adaptors') and: [ (each name includesSubString: 'Tests') not ] ]. adaptor := adaptors detect: [ :each | self isChecked: each ] ifNone: [ nil ]. adaptor isNil ifTrue: [ self addAll: (Array with: adaptors first). adaptor := adaptors first ]. self removeAll: adaptors; addAll: (Array with: adaptor). "3. draw the checkboxes" html tableRow: [ html tableHeading colSpan: 3; with: '1. Select Server Adapter' ]. group := html radioGroup. adaptors do: [ :each | html tableRow: [ html tableData class: 'checkbox'; with: [ html radioButton id: each id; group: group; selected: each = adaptor; onChange: html jQuery ajax serializeThis; callback: [ self removeAll: adaptors; addAll: (Array with: each) ]. html tableData class: 'title'; with: [ html label for: each id; with: each title ]. html tableData class: 'description'; with: each comment ] ] ]! ! !PBSimpleView methodsFor: 'rendering' stamp: 'lr 3/2/2009 12:10'! renderContentOn: html html table: [ self renderAdaptorsOn: html. self renderFeaturesOn: html ]. self renderDownload: '3. Choose Download Format' builders: self builders on: html! ! !PBSimpleView methodsFor: 'rendering-parts' stamp: 'lr 2/21/2009 09:44'! renderFeature: aCollection title: aTitleString description: aDescriptionString on: html | id packages | packages := aCollection collect: [ :each | self model packageNamed: each ]. html tableRow: [ html tableData class: 'checkbox'; with: [ html checkbox id: (id := html nextId); value: (packages allSatisfy: [ :each | self isChecked: each ]); callback: [ :value | value ifTrue: [ self addAll: packages ] ifFalse: [ self removeAll: packages ] ]; onChange: (html jQuery ajax serialize: (html jQuery this parent: 'td'; find: 'input')) ]. html tableData class: 'title'; with: [ html label for: id; with: aTitleString ]. html tableData class: 'description'; with: aDescriptionString ]! ! !PBSimpleView methodsFor: 'rendering' stamp: 'lr 3/2/2009 12:09'! renderFeaturesOn: html html tableHeading colSpan: 3; with: '2. Select Optional Features'. self renderFeature: #('JQuery-Core' 'JQuery-Tests-Core' 'JQuery-UI' 'JQuery-Tests-UI') title: 'jQuery and jQueryUI' description: 'jQuery and jQueryUI integration for Seaside. Designed to change the way you write Javascript.' on: html. self renderFeature: #('Scriptaculous-Core' 'Scriptaculous-Tests-Core' 'Scriptaculous-Components' 'Scriptaculous-Tests-Components') title: 'Prototype and script.aculo.us' description: 'Prototype and script.aculo.us integration for Seaside. Aims to ease development of dynamic web applications.' on: html. self renderFeature: #('RSS-Core' 'RSS-Examples') title: 'RSS' description: 'RSS integration for Seaside. Makes it a snap to create RSS 2.0 feeds.' on: html! ! !PackageInfo methodsFor: '*package-builder' stamp: 'lr 12/18/2008 21:37'! addToSource: aSource ^ (WAPackage packages detect: [ :each | self packageName = each name ] ifNone: [ WAPackage new name: self packageName ]) addToSource: aSource! ! WAPlatformObject subclass: #PBBuilder instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-Model'! !PBBuilder methodsFor: 'building' stamp: 'lr 2/10/2009 19:34'! build: aSource selected: aCollectionOfPackages base: aString url: aUrl self subclassResponsibility! ! !PBBuilder methodsFor: 'accessing' stamp: 'lr 10/4/2008 21:34'! comment self subclassResponsibility! ! !PBBuilder methodsFor: 'private' stamp: 'lr 12/31/2008 10:50'! identifier: aString uppercase: aBoolean | upper input char | upper := aBoolean. input := aString readStream. ^ String streamContents: [ :stream | [ input atEnd ] whileFalse: [ char := input next. char isAlphaNumeric ifTrue: [ stream nextPut: (upper ifTrue: [ char asUppercase ] ifFalse: [ char asLowercase ]). upper := false ]. char = $- ifTrue: [ upper := true ] ] ]! ! !PBBuilder methodsFor: 'utilities' stamp: 'lr 2/10/2009 19:44'! repositoriesOf: aCollectionOfPackages base: aString | repositories | repositories := aCollectionOfPackages collect: [ :each | each location ]. repositories := repositories asSet asArray sort. ^ repositories copyWithFirst: aString! ! !PBBuilder methodsFor: 'accessing' stamp: 'lr 10/4/2008 21:34'! title self subclassResponsibility! ! PBBuilder subclass: #PBConfigMapBuilder instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-Model'! !PBConfigMapBuilder methodsFor: 'building' stamp: 'lr 2/10/2009 19:42'! build: aModel selected: aCollection base: aString url: anUrl ^ WAMimeDocument on: (String streamContents: [ :stream | stream nextPut: $(; cr. (self repositoriesOf: aCollection base: aString) do: [ :each | stream tab; nextPutAll: 'repository ('; print: each; nextPut: $); cr ]. aCollection do: [ :each | stream tab; nextPutAll: 'dependency ('; print: each title; nextPut: $ ; print: each name; nextPut: $ ; print: each uuid; nextPut: $); cr ]. stream nextPut: $); cr. stream nextPut: $"; nextPutAll: aModel title; nextPut: $ ; nextPutAll: aModel version; nextPut: $"; cr. stream nextPut: $"; nextPutAll: anUrl printString; nextPut: $" ]) mimeType: 'application/monticello-map' fileName: aModel title asLowercase , '-' , aModel version , '.mcm'! ! !PBConfigMapBuilder methodsFor: 'accessing' stamp: 'lr 12/24/2008 20:11'! comment ^ 'Creates a Monticello Configuration of the selected packages.'! ! !PBConfigMapBuilder methodsFor: 'accessing' stamp: 'lr 12/24/2008 20:11'! title ^ 'Monticello Configuration'! ! PBBuilder subclass: #PBInstallerBuilder instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-Model'! !PBInstallerBuilder methodsFor: 'building' stamp: 'lr 3/24/2009 14:28'! build: aModel selected: aCollection base: aString url: anUrl ^ WAMimeDocument on: (String streamContents: [ :stream | stream nextPut: $"; nextPutAll: aModel title; nextPut: $ ; nextPutAll: aModel version; nextPut: $"; cr. stream nextPut: $"; nextPutAll: anUrl printString; nextPut: $"; cr. stream nextPut: $!!; cr. stream nextPutAll: '(HTTPSocket httpGet: ''http://installer.pbwiki.com/f/Installer.st'') fileIn.'; cr. stream nextPutAll: '!!'; cr. aCollection do: [ :package | stream nextPutAll: '(Installer monticello http: '; print: aString; nextPut: $); cr. stream nextPutAll: ' install: '; print: package name; cr. stream nextPutAll: '!!'; cr ] ]) mimeType: 'application/smalltalk-changeset' fileName: aModel title asLowercase , '-' , aModel version , '.cs'! ! !PBInstallerBuilder methodsFor: 'accessing' stamp: 'lr 11/29/2008 16:51'! comment ^ 'Creates an Installer script that loads the sources from Monticello.'! ! !PBInstallerBuilder methodsFor: 'accessing' stamp: 'lr 11/29/2008 16:51'! title ^ 'Installer Script'! ! PBBuilder subclass: #PBLoadScriptBuilder instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-Model'! !PBLoadScriptBuilder methodsFor: 'building' stamp: 'lr 2/10/2009 19:44'! build: aModel selected: aCollection base: aString url: anUrl ^ WAMimeDocument on: (String streamContents: [ :stream | stream nextPut: $"; nextPutAll: aModel title; nextPut: $ ; nextPutAll: aModel version; nextPut: $"; cr. stream nextPut: $"; nextPutAll: anUrl printString; nextPut: $"; cr. stream nextPut: $!!; cr. (self repositoriesOf: aCollection base: aString) do: [ :each | stream nextPutAll: 'MCRepositoryGroup default addRepository: ('. stream nextPutAll: (MCHttpRepository creationTemplateLocation: each user: '' password: ''); nextPut: $); cr. stream nextPut: $!!; cr ]. aCollection do: [ :package | stream nextPutAll: '[ (('; nextPutAll: (MCHttpRepository creationTemplateLocation: aString user: '' password: ''); nextPut: $); cr. stream tab; tab; nextPutAll: 'loadVersionFromFileNamed: '; print: package fileName; nextPut: $); cr. stream tab; tab; tab; nextPutAll: 'load ]'; cr. stream tab; nextPutAll: 'on: Warning do: [ :err | err resume ]'; cr. stream nextPut: $!!; cr ] ]) mimeType: 'application/smalltalk-changeset' fileName: aModel title asLowercase , '-' , aModel version , '.cs'! ! !PBLoadScriptBuilder methodsFor: 'accessing' stamp: 'lr 12/24/2008 20:13'! comment ^ 'Creates a Monticello load script of the selected packages.'! ! !PBLoadScriptBuilder methodsFor: 'accessing' stamp: 'lr 12/12/2008 18:41'! title ^ 'Load Script'! ! PBBuilder subclass: #PBSakeBuilder instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-Model'! !PBSakeBuilder methodsFor: 'building' stamp: 'lr 2/10/2009 19:46'! build: aModel selected: aCollection base: aString url: anUrl ^ WAMimeDocument on: (String streamContents: [ :stream | stream nextPut: $"; nextPutAll: aModel title; nextPut: $ ; nextPutAll: aModel version; nextPut: $"; cr. stream nextPut: $"; nextPutAll: anUrl printString; nextPut: $"; cr. stream cr. stream nextPutAll: '(HTTPSocket httpGet: ''http://installer.pbwiki.com/f/Installer.st'') fileIn!!'; cr. stream nextPutAll: 'Installer install: ''Packages''!!'; cr. stream cr. stream nextPutAll: 'Packages subclass: #'; nextPutAll: (self className: aModel); cr. stream tab; nextPutAll: 'instanceVariableNames: '''''; cr. stream tab; nextPutAll: 'classVariableNames: '''''; cr. stream tab; nextPutAll: 'poolDictionaries: '''''; cr. stream tab; nextPutAll: 'category: ''Seaside-Sake''!!'; cr. stream cr. stream nextPut: $!!; nextPutAll: (self className: aModel); nextPutAll: ' class methodsFor: '; print: #accessing; nextPut: $!!; cr. stream nextPutAll: 'findPath'; cr. stream tab; nextPutAll: '^ Array with: self!! !!'; cr. stream cr. aCollection do: [ :package | stream nextPut: $!!; nextPutAll: (self className: aModel); nextPutAll: ' methodsFor: '; print: (package group ifNil: [ #private ]) asLowercase; nextPut: $!!; cr. stream nextPutAll: (self methodName: package); cr. stream tab; nextPutAll: 'self name: '; print: package title; nextPut: $.; cr. stream tab; nextPutAll: 'self version: '; print: aModel version; nextPut: $.; cr. stream tab; nextPutAll: 'self info url: '; print: aString , '/' , package fileName; nextPut: $.; cr. package comment isNil ifFalse: [ stream tab; nextPutAll: 'self info description: '; print: package comment; nextPut: $.; cr ]. package group isNil ifFalse: [ stream tab; nextPutAll: 'self info category: '; print: package group; nextPut: $.; cr ]. package dependencies isEmpty ifFalse: [ stream tab; nextPutAll: 'self dependsOn: #('. package dependencies do: [ :each | stream print: each title ] separatedBy: [ stream nextPut: $ ]. stream nextPutAll: ').'; cr ]. stream tab; nextPutAll: 'self action: self defaultAction'. package postloads do: [ :each | stream nextPut: $.; cr; tab; nextPutAll: 'self addAction: (self class named: '; print: each title; nextPutAll: ') defaultAction' ]. stream nextPutAll: '!! !!'; cr; cr ] ]) mimeType: 'text/smalltalk-filein' fileName: aModel title asLowercase , '-' , aModel version , '.st'! ! !PBSakeBuilder methodsFor: 'private' stamp: 'lr 12/31/2008 09:57'! className: aSource ^ self identifier: aSource titleAndVersion uppercase: true! ! !PBSakeBuilder methodsFor: 'accessing' stamp: 'lr 12/31/2008 10:42'! comment ^ 'Creates a class with the Sake definition of the selected packages.'! ! !PBSakeBuilder methodsFor: 'private' stamp: 'lr 12/31/2008 10:55'! methodName: aPackage ^ aPackage title select: [ :each | each isAlphaNumeric ]! ! !PBSakeBuilder methodsFor: 'accessing' stamp: 'lr 12/31/2008 10:42'! title ^ 'Sake Package Definition'! ! PBBuilder subclass: #PBUniverseBuilder instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-Model'! !PBUniverseBuilder methodsFor: 'building' stamp: 'lr 2/10/2009 19:46'! build: aModel selected: aCollection base: aString url: anUrl ^ WAMimeDocument on: (String streamContents: [ :stream | stream nextPutAll: ''; cr. stream nextPutAll: ''; cr. aCollection do: [ :package | stream nextPutAll: ''; cr. stream tab; nextPutAll: ''; nextPutAll: package title escapeEntities; nextPutAll: ''; cr. stream tab; nextPutAll: ''; nextPutAll: package name escapeEntities; nextPutAll: ''; cr. package group isNil ifFalse: [ stream tab; nextPutAll: ''; nextPutAll: package group escapeEntities; nextPutAll: ''; cr ]. package comment isNil ifFalse: [ stream tab; nextPutAll: ''; nextPutAll: package comment escapeEntities; nextPutAll: ''; cr ]. stream tab; nextPutAll: ''; nextPutAll: (aString , '/' , package fileName) escapeEntities; nextPutAll: ''; cr. stream tab; nextPutAll: 'Seaside Core Development Team'; cr. package dependencies isEmpty ifFalse: [ stream tab; nextPutAll: ''; cr. package dependencies do: [ :each | stream tab; tab; nextPutAll: ''; nextPutAll: each title escapeEntities; nextPutAll: ''; cr ]. stream tab; nextPutAll: ''; cr ]. stream nextPutAll: ''; cr ] ]) mimeType: 'text/xml+universe' fileName: aModel title asLowercase , '-' , aModel version , '.packages'! ! !PBUniverseBuilder methodsFor: 'accessing' stamp: 'lr 12/31/2008 09:25'! comment ^ 'Creates a Package Universe from the selected packages.'! ! !PBUniverseBuilder methodsFor: 'accessing' stamp: 'lr 12/12/2008 15:46'! title ^ 'Package Universe'! ! WAPlatformObject subclass: #PBPackage instanceVariableNames: 'source title comment name uuid location group dependencies postloads' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-Model'! !PBPackage methodsFor: 'querying' stamp: 'lr 11/30/2008 13:32'! addDependenciesTo: aCollection (aCollection includes: self) ifFalse: [ self dependencies do: [ :each | each addDependenciesTo: aCollection ]. aCollection add: self. self postloads do: [ :each | each addDependenciesTo: aCollection ] ]. ^ aCollection! ! !PBPackage methodsFor: 'adding' stamp: 'lr 11/30/2008 13:05'! addDependency: aPackage | package | package := self source addPackage: aPackage. (package isNil or: [ dependencies includes: package ]) ifFalse: [ dependencies := dependencies copyWith: package ]. ^ package! ! !PBPackage methodsFor: 'adding' stamp: 'lr 11/30/2008 13:24'! addPostload: aPackage | package | package := self source addPackage: aPackage. (package isNil or: [ postloads includes: package ]) ifFalse: [ postloads := postloads copyWith: package. package addDependency: self ]. ^ package! ! !PBPackage methodsFor: 'adding' stamp: 'lr 12/18/2008 21:21'! addToSource: aSource ^ aSource packageNamed: self name ifAbsent: [ | working repository package | working := MCWorkingCopy allManagers detect: [ :each | self title = each packageName ] ifNone: [ self error: 'Working copy for ' , self title , ' not found.' ]. working modified ifTrue: [ self error: 'Working copy for ' , self title , ' is modified.' ]. repository := PBSource findRepository: working repositoryGroup repositories withVersion: working currentVersionInfo name. self name: working currentVersionInfo name. self location: repository locationWithTrailingSlash. self uuid: working currentVersionInfo id asString. aSource packages add: (self setSource: aSource) ]! ! !PBPackage methodsFor: 'querying' stamp: 'lr 11/30/2008 13:06'! allDependencies "Answer an ordered collection of dependencies for the receiving package." ^ self addDependenciesTo: OrderedCollection new! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 3/2/2009 12:33'! comment "The package description." ^ comment! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 10/4/2008 22:06'! comment: aString comment := aString! ! !PBPackage methodsFor: 'accessing-readonly' stamp: 'lr 10/4/2008 21:07'! dependencies "Answer the direct dependencies." ^ dependencies! ! !PBPackage methodsFor: 'querying' stamp: 'lr 12/13/2008 13:17'! fileName ^ self name , '.mcz'! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 12/18/2008 16:06'! group "The group name." ^ group! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 11/29/2008 16:57'! group: aString group := aString! ! !PBPackage methodsFor: 'querying' stamp: 'lr 10/18/2008 12:44'! id ^ name copyUpToLast: $-! ! !PBPackage methodsFor: 'initialization' stamp: 'lr 11/30/2008 13:50'! initialize super initialize. dependencies := #(). postloads := #()! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 12/18/2008 16:05'! location "The repository URL." ^ location! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 11/29/2008 16:46'! location: aString location := (aString beginsWith: 'http://') ifFalse: [ 'http://' , aString ] ifTrue: [ aString ]! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 12/18/2008 16:05'! name "The full version name." ^ name! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 10/4/2008 21:11'! name: aString name := aString! ! !PBPackage methodsFor: 'querying' stamp: 'lr 10/18/2008 18:54'! packageName ^ self name copyUpToLast: $-! ! !PBPackage methodsFor: 'accessing-readonly' stamp: 'lr 11/30/2008 13:23'! postloads "Answer the postload packages." ^ postloads! ! !PBPackage methodsFor: 'printing' stamp: 'lr 11/30/2008 12:43'! printOn: aStream super printOn: aStream. aStream nextPut: $(; print: self title; nextPut: $)! ! !PBPackage methodsFor: 'initialization' stamp: 'lr 11/30/2008 13:04'! setSource: aSource source := aSource! ! !PBPackage methodsFor: 'accessing-readonly' stamp: 'lr 11/30/2008 13:04'! source ^ source! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 12/18/2008 16:05'! title "The package name." ^ title! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 10/4/2008 21:45'! title: aString title := aString! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 12/18/2008 16:06'! uuid "The version identifier." ^ uuid! ! !PBPackage methodsFor: 'accessing' stamp: 'lr 10/18/2008 18:36'! uuid: aString uuid := aString! ! !PBPackage methodsFor: 'querying' stamp: 'lr 2/10/2009 18:30'! version ^ (MCHttpRepository location: self location user: '' password: '') versionFromFileNamed: self fileName! ! WAPlatformObject subclass: #PBSource instanceVariableNames: 'title version packages groups configs name' classVariableNames: '' poolDictionaries: '' category: 'Package-Builder-Model'! PBSource class instanceVariableNames: 'repositoryCache repositoryCacheValidUntil baseDirectory baseUrl'! PBSource class instanceVariableNames: 'repositoryCache repositoryCacheValidUntil baseDirectory baseUrl'! !PBSource class methodsFor: 'accessing' stamp: 'lr 2/10/2009 19:07'! baseDirectory ^ baseDirectory ifNil: [ FileDirectory default directoryNamed: 'distributions' ]! ! !PBSource class methodsFor: 'accessing' stamp: 'lr 2/10/2009 19:08'! baseDirectory: aStringOrDirectory "Defines the base-directory where the files are stored. If this value is set to nil, it default to a subdirectory of of the current image-location." baseDirectory := aStringOrDirectory isString ifTrue: [ FileDirectory on: aStringOrDirectory ] ifFalse: [ aStringOrDirectory ]! ! !PBSource class methodsFor: 'accessing' stamp: 'lr 2/10/2009 19:08'! baseUrl ^ baseUrl! ! !PBSource class methodsFor: 'accessing' stamp: 'lr 2/10/2009 19:37'! baseUrl: aString "Defines the base-URL where the files are served from, when using an external web server." baseUrl := aString isNil ifFalse: [ aString last = $/ ifFalse: [ aString ] ifTrue: [ aString copyUpToLast: $/ ] ]! ! !PBSource class methodsFor: 'accessing' stamp: 'lr 2/10/2009 19:20'! filename ^ 'Manifest.obj'! ! !PBSource class methodsFor: 'querying' stamp: 'lr 3/2/2009 12:33'! findRepository: aCollection withVersion: aString (repositoryCache isNil or: [ repositoryCacheValidUntil isNil or: [ repositoryCacheValidUntil < DateAndTime now ] ]) ifTrue: [ repositoryCacheValidUntil := TimeStamp now + 1 hour. repositoryCache := Dictionary new ]. aCollection do: [ :repository | (repository isKindOf: MCHttpRepository) ifTrue: [ ((repositoryCache at: repository ifAbsentPut: [ repository allFileNames ]) anySatisfy: [ :each | each beginsWith: aString ]) ifTrue: [ ^ repository ] ] ]. self error: 'HTTP repository for ' , aString , ' not found.'! ! !PBSource class methodsFor: 'instance-creation' stamp: 'lr 2/10/2009 19:18'! load "Load all the distributions form the default directory." | distributions distribution | distributions := OrderedCollection new. self baseDirectory directoryNames sort do: [ :each | distribution := self load: each. distribution isNil ifFalse: [ distributions addLast: distribution ] ]. ^ distributions asArray! ! !PBSource class methodsFor: 'instance-creation' stamp: 'lr 2/21/2009 11:46'! load: aString "Load the distribution aString form the default directory." | directory stream model | directory := self baseDirectory directoryNamed: aString. (directory exists and: [ directory fileExists: self filename ]) ifFalse: [ ^ nil ]. stream := ReferenceStream on: (directory oldFileNamed: self filename) binary. model := [ [ stream next ] ensure: [ stream close ] ] ifError: [ :err | ^ nil ]. (model isKindOf: self) ifFalse: [ ^ nil ]. ^ model name: aString! ! !PBSource class methodsFor: 'distributions' stamp: 'lr 3/14/2009 10:21'! seaside "self seaside verify; save: '002-Seaside2.9.0-a3'" | model | model := self new. model title: 'Seaside'; version: '2.9.0-alpha3'. " packages " model addPackages: WAPackage packages. " groups " model addGroup: 'Core Library' select: [ :each | (each name beginsWith: 'Seaside-') ]. model addGroup: 'Server Adaptors' select: [ :each | (each name includesSubString: 'Adaptors') ]. model addGroup: 'Web 2.0' select: [ :each | (each name beginsWith: 'Javascript') or: [ (each name beginsWith: 'Scriptaculous') or: [ (each name beginsWith: 'JQuery') or: [ (each name beginsWith: 'Comet') or: [ (each name beginsWith: 'RSS') or: [ (each name beginsWith: 'HTML5') ] ] ] ] ] ]. model addGroup: 'Development' select: [ :each | (each name includesSubString: 'Development') or: [ (each name includesSubString: 'OmniBrowser') ] ]. model addGroup: 'Examples' select: [ :each | (each name includesSubString: 'Examples') ]. model addGroup: 'Tests' select: [ :each | (each name includesSubString: 'Tests') ]. " special dependencies " (((model packageNamed: 'Seaside-Adaptors-Comanche') addDependency: 'KomHttpServer') addDependency: 'KomServices') addDependency: 'DynamicBindings'. ((model packageNamed: 'Seaside-Swazoo') group: nil; addDependency: 'Swazoo') addDependency: 'Sport'. ((model packageNamed: 'Seaside-Slime') group: 'Development'; addDependency: 'Refactoring-Core') addDependency: 'AST'. " special post load " model packages do: [ :each | (each name includesSubString: '-Squeak') ifTrue: [ (model packageNamed: (each title copyReplaceAll: '-Squeak' with: '') ifAbsent: [ model packageNamed: 'Seaside-Platform' ]) addPostload: each title. each group: nil ] ]. ^ model! ! !PBSource methodsFor: 'adding' stamp: 'lr 11/29/2008 16:59'! addGroup: aString "Adds a group named aString." (groups includes: aString) ifFalse: [ groups add: aString ]! ! !PBSource methodsFor: 'adding' stamp: 'lr 11/29/2008 16:59'! addGroup: aString reject: aBlock "Adds a group named aString containing those packages for which aBlock evaluates to false." self addGroup: aString reject: [ :each | (aBlock value: each) not ]! ! !PBSource methodsFor: 'adding' stamp: 'lr 11/29/2008 16:59'! addGroup: aString select: aBlock "Adds a group named aString containing those packages for which aBlock evaluates to true." self addGroup: aString. self packages do: [ :each | (aBlock value: each) ifTrue: [ each group: aString ] ]! ! !PBSource methodsFor: 'adding' stamp: 'lr 11/29/2008 16:54'! addPackage: aPackage "Add a single package to the receiver. The package can be represented as a String, a PackageInfo, a WAPackage, or as a PBPackage. Answer an existing or newly added package." ^ aPackage addToSource: self! ! !PBSource methodsFor: 'adding' stamp: 'lr 11/29/2008 16:55'! addPackages: aCollection "Add a collection of packages to the receiver." ^ aCollection do: [ :each | self addPackage: each ]! ! !PBSource methodsFor: 'querying' stamp: 'lr 12/14/2008 17:46'! analizer | analizerClass | analizerClass := Smalltalk at: #PDPackageAnalyzer ifAbsent: [ self error: 'PDPackageAnalyzer not found' ]. ^ analizerClass onPackagesNamed: (self packages collect: [ :each | each title ])! ! !PBSource methodsFor: 'enumerating' stamp: 'lr 2/10/2009 19:30'! groupsDo: aBlock groups do: [ :group | aBlock value: group value: (self packagesSorted: (self packages select: [ :package | package group = group ])) ]! ! !PBSource methodsFor: 'initialization' stamp: 'lr 2/21/2009 11:24'! initialize super initialize. packages := Set new. groups := OrderedCollection new! ! !PBSource methodsFor: 'accessing' stamp: 'lr 2/10/2009 19:30'! name ^ name! ! !PBSource methodsFor: 'accessing' stamp: 'lr 2/10/2009 19:30'! name: aString name := aString! ! !PBSource methodsFor: 'querying' stamp: 'lr 11/30/2008 12:52'! packageNamed: aString ^ self packageNamed: aString ifAbsent: [ nil ]! ! !PBSource methodsFor: 'querying' stamp: 'lr 12/18/2008 16:14'! packageNamed: aString ifAbsent: aBlock ^ self packages detect: [ :each | each title beginsWith: aString ] ifNone: aBlock! ! !PBSource methodsFor: 'querying' stamp: 'lr 10/4/2008 22:19'! packages ^ packages! ! !PBSource methodsFor: 'querying' stamp: 'lr 11/29/2008 17:20'! packagesSorted: aCollection ^ aCollection asArray sort: [ :a :b | a title < b title ]! ! !PBSource methodsFor: 'printing' stamp: 'lr 10/4/2008 21:52'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' ('; print: self title; nextPutAll: ')'! ! !PBSource methodsFor: 'actions' stamp: 'lr 2/10/2009 21:34'! save self save: self name! ! !PBSource methodsFor: 'actions' stamp: 'lr 2/10/2009 21:35'! save: aString | target stream repository | packages := self packagesSorted: packages. [ target := (self class baseDirectory directoryNamed: aString) assureExistence. stream := ReferenceStream on: (target forceNewFileNamed: self class filename). [ stream nextPut: self ] ensure: [ stream close ] ] ensure: [ packages := packages asSet ]. repository := MCDirectoryRepository new directory: target. packages do: [ :each | repository storeVersion: each version ] displayingProgress: 'Storing ' , self titleAndVersion! ! !PBSource methodsFor: 'accessing' stamp: 'lr 10/4/2008 21:52'! title ^ title! ! !PBSource methodsFor: 'accessing' stamp: 'lr 10/4/2008 21:52'! title: aString title := aString! ! !PBSource methodsFor: 'querying' stamp: 'lr 12/18/2008 16:14'! titleAndVersion ^ self title , ' ' , self version! ! !PBSource methodsFor: 'actions' stamp: 'lr 12/18/2008 16:43'! verify self verify: self analizer! ! !PBSource methodsFor: 'actions' stamp: 'lr 12/14/2008 19:19'! verify: anAnalizer "Verify the receiving source model with the static code analysis." | relation other dependency | relation := anAnalizer relation. self packages do: [ :package | other := relation packages detect: [ :each | each packageName = package title ] ifNone: [ nil ]. other isNil ifFalse: [ other dependentPackages do: [ :depend | dependency := self packages detect: [ :each | each title = depend packageName ] ifNone: [ nil ]. dependency isNil ifFalse: [ (package allDependencies includes: dependency) ifFalse: [ package addDependency: dependency. Transcript show: package title; show: ' is missing '; show: dependency title; show: ' ('; show: (other dependencies detect: [ :each | each target = depend ]) reason; show: ')'; cr ] ] ] ] ]! ! !PBSource methodsFor: 'accessing' stamp: 'lr 10/4/2008 20:35'! version ^ version! ! !PBSource methodsFor: 'accessing' stamp: 'lr 12/18/2008 16:02'! version: aString version := aString! ! PBBuilderComponent initialize!