[Pkg] Squeak3.11 Contributions: MethodAuthorship-mtf.1.mcz

squeak-dev-noreply at lists.squeakfoundation.org squeak-dev-noreply at lists.squeakfoundation.org
Sat Feb 7 21:46:42 UTC 2009


A new version of MethodAuthorship was added to project Squeak3.11 Contributions:
http://www.squeaksource.com/311/MethodAuthorship-mtf.1.mcz

==================== Summary ====================

Name: MethodAuthorship-mtf.1
Author: mtf
Time: 7 February 2009, 4:46:38 pm
UUID: 7cd55eb9-f7a6-4944-93cb-e1f8089dcd51
Ancestors: 

This is what is in the image and works

==================== Snapshot ====================

SystemOrganization addCategory: #MethodAuthorship!

Browser subclass: #MethodHistoryBrowser
	instanceVariableNames: 'database'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'MethodAuthorship'!

----- Method: MethodHistoryBrowser class>>example1 (in category 'as yet unclassified') -----
example1

	| m sV1 c11 c113 c117 c118 c119 c12 c122 c123 c131 sV2 c20 c21 c22 c23 c24 c25 c26 c27 c28 sV3 c30 c31 c32 c34 c35 c36 c37 c38 sq e23 ev3 e3l b |
	m := MethodHistoryDatabase new.
	sV1 := m processChangesFile: 'SqueakV1.sources' encoding: 'mac-roman'.
	c11 := m processChangesFile: 'Squeak1.1.changes' encoding: 'mac-roman'.
	c113 := m processChangesFile: 'Squeak1.13u.changes' encoding: 'mac-roman'.
	"1.16 is proper prefix of 1.17."
	c117 := m processChangesFile: 'Squeak1.17u.changes' encoding: 'mac-roman'.
	c118 := m processChangesFile: 'Squeak1.18.changes' encoding: 'mac-roman'.
	c119 := m processChangesFile: 'Squeak1.19d.changes' encoding: 'mac-roman'.
	c12 := m processChangesFile: 'Squeak1.2.changes' encoding: 'mac-roman'.
	c122 := m processChangesFile: 'Squeak1.22.changes' encoding: 'mac-roman'.
	c123 := m processChangesFile: 'Squeak1.23up.changes' encoding: 'mac-roman'.
	c131 := m processChangesFile: 'Squeak1.31.changes' encoding: 'mac-roman'.
	sV2 := m processChangesFile: 'SqueakV2.sources' encoding: 'mac-roman'.
	c20 := m processChangesFile: 'Squeak2.0.changes' encoding: 'mac-roman'.
	c21 := m processChangesFile: 'Squeak2.1.changes' encoding: 'mac-roman'.
	c22 := m processChangesFile: 'Squeak2.2.changes' encoding: 'mac-roman'.
	c23 := m processChangesFile: 'Squeak2.3.changes' encoding: 'mac-roman'.
	c24 := m processChangesFile: 'Squeak2.4b.changes' encoding: 'mac-roman'.
	c25 := m processChangesFile: 'Squeak2.5.changes' encoding: 'mac-roman'.
	c26 := m processChangesFile: 'Squeak2.6.changes' encoding: 'mac-roman'.
	c27 := m processChangesFile: 'Squeak2.7.changes' encoding: 'mac-roman'.
	c28 := m processChangesFile: 'Squeak2.8.changes' encoding: 'mac-roman'.
	sV3 := m processChangesFile: 'SqueakV3.sources' encoding: 'mac-roman'.
	c30 := m processChangesFile: 'Squeak3.0.changes' encoding: 'mac-roman'.
	c31 := m processChangesFile: 'Squeak3.1beta-4411.changes' encoding: 'mac-roman'.
	c32 := m processChangesFile: 'Squeak3.2-4956.changes' encoding: 'mac-roman'.
	c34 := m processChangesFile: 'Squeak3.4.changes' encoding: 'mac-roman'.
	c35 := m processChangesFile: 'Squeak3.5-5180.changes' encoding: 'mac-roman'.
	c36 := m processChangesFile: 'Squeak3.6-5429-full.changes' encoding: 'mac-roman'.
	c37 := m processChangesFile: 'Squeak3.7-5989-full.changes' encoding: 'mac-roman'.
	c38 := m processChangesFile: 'Squeak3.8-6665full.changes' encoding: 'utf-8'.
	sq := m processChangesFile: 'SqueakPlugin-dev.changes' encoding: 'utf-8'.
	e23 := m processChangesFile: 'etoys-dev-2.3-2.changes' encoding: 'utf-8'.
	ev3 := m processChangesFile: 'EtoysV3.sources' encoding: 'utf-8'.
	e3l := m processChangesFile: 'etoys-dev-3.0-2-2079.changes' encoding: 'utf-8'.

	m processChangesList: sV1.
	m processChangesList: c11.
	m processChangesList: c113.
	m processChangesList: c117.
	m processChangesList: c118.
	m processChangesList: c119.
	m processChangesList: c12.
	m processChangesList: c122.
	m processChangesList: c123.
	m processChangesList: c131.
	m processChangesList: sV2.
	m processChangesList: c20.
	m processChangesList: c21.
	m processChangesList: c22.
	m processChangesList: c23.
	m processChangesList: c24.
	m processChangesList: c25.
	m processChangesList: c26.
	m processChangesList: c27.
	m processChangesList: c28.
	m processChangesList: sV3.
	m processChangesList: c30.
	m processChangesList: c31.
	m processChangesList: c32.
	m processChangesList: c34.
	m processChangesList: c35.
	m processChangesList: c36.
	m processChangesList: c37.
	m processChangesList: c38.

	m processChangesList: sq.
	m processChangesList: e23.
	m processChangesList: ev3.
	m processChangesList: e3l.

	b := MethodHistoryBrowser new.
	b database: m.
	MethodHistoryBrowser openBrowserView: (b openEditString: nil) label: 'foo'.!

----- Method: MethodHistoryBrowser class>>example2 (in category 'as yet unclassified') -----
example2

	| m d b |
	MethodHistoryChangeList ignoreNonExsiting: true.
	m := MethodHistoryDatabase new.

	m readFile: 'SqueakV1.sources' encodingName: 'mac-roman'.
	d := FileDirectory default directoryNamed: 'history-updates'.
	#('PreBeta' 'Sqk20Beta') do: [:v |
		m readFilesIn: d updateFile: 'updates.list' versionName: v.].

	m readFile: 'SqueakV2.sources' encodingName: 'mac-roman'.
	#('Squeak2.0' 'Squeak2.1' 'Squeak2.2beta' 'Squeak2.2' 'Squeak2.3' 'Squeak2.4' 'Squeak2.5test' 'Squeak2.5' 'Squeak2.6alpha' 'Squeak2.6' 'Squeak2.7alpha' 'Squeak2.7' 'Squeak2.8alpha' 'Squeak2.8' 'Squeak2.9alpha') do: [:v |
		m readFilesIn: d updateFile: 'updates.list' versionName: v.].

	m readFile: 'SqueakV3.sources' encodingName: 'mac-roman'.
	#('Squeak3.0' 'Squeak3.1alpha' 'Squeak3.1beta' 'Squeak3.2alpha' 'Squeak3.2gamma' 'Squeak3.2' 'Squeak3.2.1' 'Squeak3.4alpha' 'Squeak3.4beta' 'Squeak3.4gamma' 'Squeak3.5alpha' 'Squeak3.5beta' 'Squeak3.5gamma' 'Squeak3.6alpha' 'Squeak3.6beta' 'Squeak3.6gamma' 'Squeak3.6') do: [:v |
		m readFilesIn: d updateFile: 'updates.list' versionName: v.].

	d := FileDirectory default directoryNamed: 'squeak.org-updates'.
	#('Squeak3.7alpha' 'Squeak3.7beta' 'Squeak3.7gamma' 'Squeak3.7' 'Squeak3.8alpha' 'Squeak3.8beta' 'Squeak3.8gamma') do: [:v |
		m readFilesIn: d updateFile: 'SqCupdates.list' versionName: v.].

	d := FileDirectory default directoryNamed: 'squeakland.org-updates'.
	#('Squeakland 3.1.3905' 'Squeakland 3.1.4295' 'Squeakland 3.2.4913' 'Squeakland 3.8.5976' 'Squeakland05' 'Squeakland 3.8-05') do: [:v |
		m readFilesIn: d updateFile: 'updates.list' versionName: v.].

	d := FileDirectory default directoryNamed: 'olpc-updates'.
	#('OLPC1.0' 'OLPC2.0') do: [:v |
		m readFilesIn: d updateFile: 'updates.list' versionName: v.].

	d := FileDirectory default directoryNamed: 'etoys-updates'.
	#('etoys2.1' 'etoys2.2' 'etoys2.3') do: [:v |
		m readFilesIn: d updateFile: 'updates.list' versionName: v.].

	m readFile: 'EtoysV3.sources' encodingName: 'utf-8'.
	#('etoys3.0') do: [:v |
		m readFilesIn: d updateFile: 'updates.list' versionName: v.].

	b := MethodHistoryBrowser new.
	b database: m.
	MethodHistoryBrowser openBrowserView: (b openEditString: nil) label: 'foo'.!

----- Method: MethodHistoryBrowser>>browseVersions (in category 'all') -----
browseVersions
	"Create and schedule a Versions Browser, showing all versions of the 
	currently selected message. Answer the browser or nil."
	| selector class | 
	self classCommentIndicated
		ifTrue: [ ClassCommentVersionsBrowser browseCommentOf: self selectedClass.
			^nil ].

	(selector _ self selectedMessageName)
		ifNil:[ self inform: 'Sorry, only actual methods have retrievable versions.'. ^nil ]
		ifNotNil: [
			class _ self selectedClassOrMetaClass.
			^MethodHistoryVersionBrowser
				browseVersionsOf: (class compiledMethodAt: selector)
				class: self selectedClass
				meta: class isMeta
				category: (class organization categoryOfElement: selector)
				selector: selector
				database: database]!

----- Method: MethodHistoryBrowser>>database: (in category 'all') -----
database: d

	database := d.
!

----- Method: MethodHistoryBrowser>>selectedMessage (in category 'all') -----
selectedMessage
	"Answer a copy of the source code for the selected message."

	| class selector |
	contents == nil ifFalse: [^ contents copy].

	self showingDecompile ifTrue:
		[^ self decompiledSourceIntoContentsWithTempNames: Sensor leftShiftDown not ].

	class _ self selectedClassOrMetaClass.
	selector _ self selectedMessageName.
	^ (database sourceCodeAt: class name asSymbol at: selector).
!

OrderedCollection subclass: #MethodCollection
	instanceVariableNames: 'title'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'MethodAuthorship'!

----- Method: MethodCollection class>>titled: (in category 'as yet unclassified') -----
titled: aName
	^self new title: aName!

----- Method: MethodCollection>>printOn: (in category 'accessing') -----
printOn: aStream 
	aStream nextPutAll: 'methods by ';
		 nextPutAll: title;
		 cr.
	self do: [:each | aStream tab. each shortPrintOn: aStream. aStream cr]!

----- Method: MethodCollection>>title (in category 'accessing') -----
title
	^ title!

----- Method: MethodCollection>>title: (in category 'accessing') -----
title: aName 
	title := aName!

ChangeList subclass: #MethodHistoryChangeList
	instanceVariableNames: ''
	classVariableNames: 'IgnoreNonExsiting'
	poolDictionaries: ''
	category: 'MethodAuthorship'!

----- Method: MethodHistoryChangeList class>>ignoreNonExsiting: (in category 'as yet unclassified') -----
ignoreNonExsiting: aBoolean

	IgnoreNonExsiting _ aBoolean.
!

----- Method: MethodHistoryChangeList>>annotation (in category 'all') -----
annotation

	^ '------'
!

----- Method: MethodHistoryChangeList>>contentsDiffedFromCurrent (in category 'all') -----
contentsDiffedFromCurrent
	"Answer the contents diffed forward from current (in-memory) method version"

	| aChange aClass |
	listIndex = 0
		ifTrue: [^ ''].
	aChange _ changeList at: listIndex.
	^ (aChange type == #method and: [(aClass _ aChange methodClass) notNil])
		ifTrue:
			 [(changeList size >= (listIndex + 1)) ifTrue: [
				 TextDiffBuilder
					buildDisplayPatchFrom: (changeList at: listIndex + 1) text
					to: aChange text
					inClass: aClass
					prettyDiffs: self showingPrettyDiffs] ifFalse: [(changeList at: listIndex) text]]
		ifFalse:
			[(changeList at: listIndex) text]!

----- Method: MethodHistoryChangeList>>ignoreNonExisting (in category 'all') -----
ignoreNonExisting

	^ IgnoreNonExsiting ifNil: [^ true].
!

----- Method: MethodHistoryChangeList>>initializeForDatabase (in category 'all') -----
initializeForDatabase

	listSelections := Array new: list size withAll: false.
!

----- Method: MethodHistoryChangeList>>scanCategory (in category 'all') -----
scanCategory  
	"Scan anything that involves more than one chunk; method name is historical only"

	| item tokens stamp isComment anIndex |
	item _ file nextChunk.

	isComment _ (item includesSubString: 'commentStamp:').
	(isComment or: [item includesSubString: 'methodsFor:']) ifFalse:
		[^ self].

	tokens _ Scanner new scanTokens: item.
	tokens size >= 3 ifTrue:
		[stamp _ ''.
		anIndex _ tokens indexOf: #stamp: ifAbsent: [nil].
		anIndex ifNotNil: [stamp _ tokens at: (anIndex + 1)].

		tokens second == #methodsFor:
			ifTrue: [^ self scanCategory: tokens third class: tokens first
							meta: false stamp: stamp].
		tokens third == #methodsFor:
			ifTrue: [^ self scanCategory: tokens fourth class: tokens first
							meta: true stamp: stamp]].

		tokens second == #commentStamp:
			ifTrue:
				[stamp _ tokens third.
				"self addItem:
						(ChangeRecord new file: file position: file position type: #classComment
										class: tokens first category: nil meta: false stamp: stamp)
						text: 'class comment for ' , tokens first, 
							  (stamp isEmpty ifTrue: [''] ifFalse: ['; ' , stamp])."
				file nextChunk.
				^ file skipStyleChunk]!

----- Method: MethodHistoryChangeList>>scanCategory:class:meta:stamp: (in category 'all') -----
scanCategory: category class: class meta: meta stamp: stamp
	| method sel |
	self ignoreNonExisting ifTrue: [Smalltalk at: class ifAbsent: [^ self]].
	[
	method _ file nextChunk.
	file skipStyleChunk.
	method size > 0]						"done when double terminators"
		whileTrue:
		[sel _ Parser new parseSelector: method.
		self addItem: (MethodHistoryChangeRecord new class: (class, (meta ifTrue: [' class'] ifFalse: [''])) asSymbol selector: sel stamp: stamp text: method asString sourceFile: file localName)
			text: 'method: ' , class , (meta ifTrue: [' class '] ifFalse: [' '])
				, sel
				, (stamp isEmpty ifTrue: [''] ifFalse: ['; ' , stamp])]!

----- Method: MethodHistoryChangeList>>scanFile:from:to: (in category 'all') -----
scanFile: aFile from: startPosition to: stopPosition
	| itemPosition item prevChar |
	file _ aFile.
	changeList _ OrderedCollection new.
	list _ OrderedCollection new.
	listIndex _ 0.
	file position: startPosition.
'Scanning ', aFile localName, '...'
	displayProgressAt: Sensor cursorPoint
	from: startPosition to: stopPosition
	during: [:bar |
	[file position < stopPosition]
		whileTrue:
		[bar value: file position.
		[file atEnd not and: [file peek isSeparator]]
				whileTrue: [prevChar _ file next].
		(file peekFor: $!!)
		ifTrue:
			[(prevChar = Character cr or: [prevChar = Character lf])
				ifTrue: [self scanCategory]]
		ifFalse:
			[itemPosition _ file position.
			item _ file nextChunk.
			file skipStyleChunk.
			]]].
	listSelections _ Array new: list size withAll: false!

Object subclass: #Authorship
	instanceVariableNames: 'missingDictionary authorDictionary notAccounted database historicalMissingDictionary historicalAuthorDictionary historicalNotAccounted'
	classVariableNames: 'AllMethods'
	poolDictionaries: ''
	category: 'MethodAuthorship'!

!Authorship commentStamp: 'yo 9/19/2008 13:03' prior: 0!
To use this class along with the MethodHistoryDatabase, get the necessary files and put them some directories under the image directory, and evaluate the following in a workspace:

m := MethodHistoryDatabase new.
MethodHistoryChangeList ignoreNonExsiting: false.
m readFile: 'SqueakV1.sources' encodingName: 'mac-roman'.
d := FileDirectory default directoryNamed: 'history-updates'.
#('PreBeta' 'Sqk20Beta') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

m readFile: 'SqueakV2.sources' encodingName: 'mac-roman'.
#('Squeak2.0' 'Squeak2.1' 'Squeak2.2beta' 'Squeak2.2' 'Squeak2.3' 'Squeak2.4' 'Squeak2.5test' 'Squeak2.5' 'Squeak2.6alpha' 'Squeak2.6' 'Squeak2.7alpha' 'Squeak2.7' 'Squeak2.8alpha' 'Squeak2.8' 'Squeak2.9alpha') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

m readFile: 'SqueakV3.sources' encodingName: 'mac-roman'.
#('Squeak3.0' 'Squeak3.1alpha' 'Squeak3.1beta' 'Squeak3.2alpha' 'Squeak3.2gamma' 'Squeak3.2' 'Squeak3.2.1' 'Squeak3.4alpha' 'Squeak3.4beta' 'Squeak3.4gamma' 'Squeak3.5alpha' 'Squeak3.5beta' 'Squeak3.5gamma' 'Squeak3.6alpha' 'Squeak3.6beta' 'Squeak3.6gamma' 'Squeak3.6') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

d := FileDirectory default directoryNamed: 'squeak.org-updates'.
#('Squeak3.7alpha' 'Squeak3.7beta' 'Squeak3.7gamma' 'Squeak3.7' 'Squeak3.8alpha' 'Squeak3.8beta' 'Squeak3.8gamma') do: [:v |
	m readFilesIn: d updateFile: 'SqCupdates.list' versionName: v.].

d := FileDirectory default directoryNamed: 'squeakland.org-updates'.
#('Squeakland 3.1.3905' 'Squeakland 3.1.4295' 'Squeakland 3.2.4913' 'Squeakland 3.8.5976' 'Squeakland05' 'Squeakland 3.8-05') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

d := FileDirectory default directoryNamed: 'olpc-updates'.
#('OLPC1.0' 'OLPC2.0') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

d := FileDirectory default directoryNamed: 'etoys-updates'.
#('etoys2.1' 'etoys2.2' 'etoys2.3') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

m readFile: 'EtoysV3.sources' encodingName: 'utf-8'.
#('etoys3.0') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

b := MethodHistoryBrowser new.
b database: m.
MethodHistoryBrowser openBrowserView: (b openEditString: nil) label: 'foo'.

Authorship initialize.
authors := Authorship new.
authors database: m.
missing := authors missingAuthorsWithMethods.
returned := authors returnedAuthorsWithMethods.
notAccounted := authors notAccounted.
historicalMissing := authors historicalMissingAuthorsWithMethods.
historicalNotAccounted := authors historicalNotAccounted.

f _ FileStream newFileNamed: 'currentMissing.html'.
m writeDictWithVersion: missing toHTMLFileNameOn: f title: 'Agreement Missing in Etoys 3.0' explanationFileName: 'missingExplanation.txt'.
f close.

Or for the mainstream image, create appropriate .changes files by doing updates and then:

m := MethodHistoryDatabase new.
MethodHistoryChangeList ignoreNonExsiting: false.
m readFile: 'SqueakV1.sources' encodingName: 'mac-roman'.
d := FileDirectory default directoryNamed: 'history-updates'.
#('PreBeta' 'Sqk20Beta') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

m readFile: 'SqueakV2.sources' encodingName: 'mac-roman'.
#('Squeak2.0' 'Squeak2.1' 'Squeak2.2beta' 'Squeak2.2' 'Squeak2.3' 'Squeak2.4' 'Squeak2.5test' 'Squeak2.5' 'Squeak2.6alpha' 'Squeak2.6' 'Squeak2.7alpha' 'Squeak2.7' 'Squeak2.8alpha' 'Squeak2.8' 'Squeak2.9alpha') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

m readFile: 'SqueakV3.sources' encodingName: 'mac-roman'.
#('Squeak3.0' 'Squeak3.1alpha' 'Squeak3.1beta' 'Squeak3.2alpha' 'Squeak3.2gamma' 'Squeak3.2' 'Squeak3.2.1' 'Squeak3.4alpha' 'Squeak3.4beta' 'Squeak3.4gamma' 'Squeak3.5alpha' 'Squeak3.5beta' 'Squeak3.5gamma' 'Squeak3.6alpha' 'Squeak3.6beta' 'Squeak3.6gamma' 'Squeak3.6') do: [:v |
	m readFilesIn: d updateFile: 'updates.list' versionName: v.].

d := FileDirectory default directoryNamed: 'squeak.org-updates'.
#('Squeak3.7alpha' 'Squeak3.7beta' 'Squeak3.7gamma' 'Squeak3.7' 'Squeak3.8alpha' 'Squeak3.8beta' 'Squeak3.8gamma') do: [:v |
	m readFilesIn: d updateFile: 'SqCupdates.list' versionName: v.].

m readFile: 'Squeak3.9b-7053.changes' encodingName: 'utf-8'.
m readFile: 'SqueakV39.sources' encodingName: 'utf-8'.
m readFile: 'Squeak39g-7056+3102-7179.changes' encodingName: 'utf-8'.

b := MethodHistoryBrowser new.
b database: m.
MethodHistoryBrowser openBrowserView: (b openEditString: nil) label: 'foo'.

Authorship initialize.
authors := Authorship new.
authors database: m.
missing := authors missingAuthorsWithMethods.
returned := authors returnedAuthorsWithMethods.
notAccounted := authors notAccounted.
historicalMissing := authors historicalMissingAuthorsWithMethods.
historicalNotAccounted := authors historicalNotAccounted.


f _ FileStream newFileNamed: 'currentMissing.html'.
m writeDictWithVersion: missing toHTMLFileNameOn: f title: 'Agreement Missing in Etoys 3.0' explanationFileName: 'missingExplanation.txt'.
f close.

m writeDict: missing toFileName: 'missing.txt'.!

----- Method: Authorship class>>example1 (in category 'as yet unclassified') -----
example1

	| authors missing returned notAccounted |
	Authorship initialize.
	authors := Authorship new.
	missing := authors missingAuthorsWithMethods.
	returned := authors returnedAuthorsWithMethods.
	notAccounted := authors notAccounted.
	^ authors.
!

----- Method: Authorship class>>initialize (in category 'as yet unclassified') -----
initialize
	| n i eachClass |
	super initialize.
	n := Metaclass allInstances size.
	AllMethods := OrderedCollection new.
	i _ 0.
	'Collecting method information...' displayProgressAt: Sensor cursorPoint from: 1 to: n during: [:bar |
		Metaclass allInstancesDo: [:mc |
			bar value: (i := i + 1).
			(eachClass := mc)  selectors
				do: [:eachSelector |
					(#(DoIt DoItIn:) includes: eachSelector) ifFalse: [
						AllMethods
							add: (MethodHistoryChangeRecord new  class: eachClass name selector: eachSelector stamp:  (eachClass compiledMethodAt: eachSelector) timeStamp text: '' sourceFile: '(current)')]].
			(eachClass := mc theNonMetaClass) selectors
				do: [:eachSelector |
					(#(DoIt DoItIn:) includes: eachSelector) ifFalse: [
						AllMethods
							add: (MethodHistoryChangeRecord new  class: eachClass name selector: eachSelector stamp:  (eachClass compiledMethodAt: eachSelector) timeStamp text: '' sourceFile: '(current)')]]]].
!

----- Method: Authorship>>addToHistoricalListIfAuthorHasReturnedSignatory: (in category 'private') -----
addToHistoricalListIfAuthorHasReturnedSignatory: each 

	(historicalAuthorDictionary at: each author ifAbsent: [^nil]) addLast: each!

----- Method: Authorship>>addToHistoricalListIfAuthorIsMissingSignatory: (in category 'private') -----
addToHistoricalListIfAuthorIsMissingSignatory: each 
	(historicalMissingDictionary at: each author ifAbsent: [^nil]) addLast: each!

----- Method: Authorship>>addToListIfAuthorHasReturnedSignatory: (in category 'private') -----
addToListIfAuthorHasReturnedSignatory: each 

	(authorDictionary at: each author ifAbsent: [^nil]) addLast: each!

----- Method: Authorship>>addToListIfAuthorIsMissingSignatory: (in category 'private') -----
addToListIfAuthorIsMissingSignatory: each 
	"author dictionary's value at key k is an OrderedCollection containing the methods 
	written by k"
	(missingDictionary at: each author ifAbsent: [^nil]) addLast: each!

----- Method: Authorship>>agreedContributors (in category 'data') -----
agreedContributors

"This is a list of all Squeak contributors whom Yoshiki Ohshima contacted and get the favorable words, but have not returned a signed distribution agreement yet.

---

initials         name"
^ #(
'jla'              'Jerry Archibald'
'pad'		'Pierre-Andre Dreyfuss'
'r++'              'Gerardo Richarte'
)!

----- Method: Authorship>>database: (in category 'initialize-release') -----
database: db

	| count eachClass ret1 ret2 |
	database _ db.

	self missingSignatories
		pairsDo: [:initials :name |
			historicalMissingDictionary
				at: initials
				put: (MethodCollection titled: name)].
	self returnedSignatories, self newContributors, self agreedContributors
		pairsDo: [:initials :name |
			historicalAuthorDictionary
				at: initials
				put: (MethodCollection titled: name)].

	count _ 0.
	'collecting information (historical)...' displayProgressAt: Sensor cursorPoint from: 1 to: database size // 100 during: [:bar |
		database keys do: [:k |
			count := count + 1.
			count \\ 100 = 0 ifTrue: [bar value: count//100].
			eachClass := database at: k.
			eachClass do: [:recs |
				recs do: [:rec |
					ret1 := self addToHistoricalListIfAuthorIsMissingSignatory: rec.
					ret2 := self addToHistoricalListIfAuthorHasReturnedSignatory: rec.
				(ret1 == nil and: [ret2 == nil and: [rec author isEmpty not]]) ifTrue: [historicalNotAccounted add: rec]]]]].!

----- Method: Authorship>>historicalMissingAuthorsWithMethods (in category 'filtering') -----
historicalMissingAuthorsWithMethods
	^ historicalMissingDictionary select: [ :eachAssoc | eachAssoc value notEmpty ]!

----- Method: Authorship>>historicalNotAccounted (in category 'filtering') -----
historicalNotAccounted

	^ historicalNotAccounted
!

----- Method: Authorship>>initialize (in category 'initialize-release') -----
initialize
	
	| ret1 ret2 each |
	missingDictionary := Dictionary new.
	authorDictionary := Dictionary new.
	notAccounted := OrderedCollection new.
	historicalMissingDictionary := Dictionary new.
	historicalAuthorDictionary := Dictionary new.
	historicalNotAccounted := OrderedCollection new.
	self missingSignatories
		pairsDo: [:initials :name |
			missingDictionary
				at: initials
				put: (MethodCollection titled: name)].
	self returnedSignatories, self newContributors, self agreedContributors
		pairsDo: [:initials :name |
			authorDictionary
				at: initials
				put: (MethodCollection titled: name)].
	'collecting information...' displayProgressAt: Sensor cursorPoint from: 1 to: AllMethods size // 100 during: [:bar |
		1 to: AllMethods size do: [:i |
			i \\ 100 = 0 ifTrue: [bar value: i//100].
			each := AllMethods at: i.
			"each methodSymbol = #testTwoArgumentEvent ifTrue: [self halt]."
			ret1 := self addToListIfAuthorIsMissingSignatory: each.
			ret2 := self addToListIfAuthorHasReturnedSignatory: each.
			(ret1 == nil and: [ret2 == nil and: [each author isEmpty not]]) ifTrue: [notAccounted add: each]]].
!

----- Method: Authorship>>missingAuthorsWithMethods (in category 'filtering') -----
missingAuthorsWithMethods
	^ missingDictionary select: [ :eachAssoc | eachAssoc value notEmpty ]!

----- Method: Authorship>>missingSignatories (in category 'data') -----
missingSignatories
"This is a list of all Squeak contributors who have not returned a signed distribution agreement.

Aug 21st  2008

---

initials         name"
^ #(
'abc'              '?'
'afr'              'Alejandro Reimondo'
'ag'               'Andreas Gerdes'
'AK'               'Anoulak Kictiraz'
'ak'               'Anoulak Kictiraz'
'AM'               'Aibek Musaev'
'am'               'Aibek Musaev'
'ASF'              'Adam Franco'
'bmk'              'Brian Keefer'
'cE'               'Christian Eitner'
'cm'               'Cesare Marilungo?'
'dik'		'Denis Kudriashov'
'djm'              'Douglas McPherson'
'dls'              'Darryl Smith'
'dns'              'David N. Smith'
'drs'              'Dean Swan'
'dwh'              'Dwight Hughes'
'edt'              '?'
'eldeh'            'Lars Dornheim'
'EP'               '?'
'EW'               'Etan Wexler'
'ff'               'Felix Franz'
'gg'               'Giovanni Giorgi'
'GL'               'Greg Lewin?'
'GVG'              'Greg Gritton'
'gwc'              'Geoff Corey'
'H.Hachisuka'      'Hitoshi Hachisuka'
'hg'               'Henrik Gedenryd'
'hh'               'Helge Horch'
'HJH'              'Hannes Hirzel'
'hk'		'Harald Kopp'
'IT'               'Ian Trudel'
'jbc'              'Jay Casler'
'JDD'              'John David Duncan'
'jdl'              'Jose Laiolo'
'jet'              'John Tobler'
'jj'               '?'
'JLM'              'Jason McVay'
'jlm'              'Jason McVay'
'JO'               'Jonas Oehrn'
'jwh'              'Jim Heyne'
'JZH'              'John (Zhijiang) Han'
'Kafka'            'Pablo Malavolta'
'kph'		'Keith Hodges'
'los'              'Lothar Schenk'
'mkd'              'Michael Donegan'
'MM'               'Maarten Maartensz'
'mm'               '?'
'mmo'               'Marica Odagaki'
'msk'              'Michael Klein'
'mtf'		'Matthew Fulmer'
'mx'               'Maximialiano Taborda'
'NDCC'             '?'
'mn'               'Mats Nygren'
'nm'		'Nicolas Melin'
'PH'               'Phil Hudson'
'pmm'              'Philippe Marschall?'
'RAH'              'Richard A. Harmon'
'RB'               'Roland Bertuli'
'RCS'              'Russell Swan'
'rej'		'Ralph Johnson'
'RJ'               'Ranjan Bagchi'
'rjf'              'Ricardo J. Ferreira'
'rlf'              'Ricardo J. Ferreira'
'rmf'              'Robert Fure'
'RMF'              'Robert Fure'
'rop'              'Russell Penney'
'rp'              '?'
'rpj'              'Robert P. Jarvis'
'RvL'              'Reinier van Loon'
'sac'              'Scott Crosby'
'SIM'              'Stewart MacLean'
'sjc'              'Sean Charles'
'sk'               'Stefan Kersten'
'slr'              'Steve Rees'
'squeak'           'Henrik Gedenryd'
'TBP'              'Brian Payne'
'Tbp'              'Brian Payne'
'TEM'              'Tom Morgan'
'tm'               '?'
'tonyg'		'Tony Garnock-Jones'
'to'               '?'
'tp'               '?'
'umur'             'Umur Ozkul'
'UO'             'Umur Ozkul'
'wb'               'Wayne Braun'
'wbk'		'Bryce Kampjes'
'wdc'              'Bill Cattey'
'YE'               '?'
'zL'               'Lantz Rowland'
'mvl'		'Martin v. Lowis'
'pf'		'Petr Fischer'
'JPF'		'?'
'ktt'		'?'
'ndCollectionsTests-Unordered'		'?'
'kb'		'Ken Bryant'
'ge'		'?'
)!

----- Method: Authorship>>newContributors (in category 'data') -----
newContributors

"This is a list of all Squeak contributors who started after the relicensing effort was started and therefore know that the license is under MIT.

---

initials         name"
^ #(
'aw'               'Alessandro Warth'
'be'			'Bernd Eckardt'
'cjs'			'(from trac)'
'jf'			'Jan Fietz'
'lg'               'Luke Gorrie'
'jl'			'Jens Linke'
'JSM'	   'John S Mcintosh'
'thf'			'an Impara employee'
'sjg'			'Simon Guest'
'kks'            'kks'
'meta-auto'	'generated code'
'programmatic'     'generated code'
)!

----- Method: Authorship>>notAccounted (in category 'filtering') -----
notAccounted

	^ notAccounted
!

----- Method: Authorship>>overlap (in category 'filtering') -----
overlap

	| returned missing |
	returned := OrderedCollection new: 100.
	(self returnedSignatories, self newContributors, self agreedContributors) pairsDo: [:initials :name |
		returned add: initials.
	].
	missing := OrderedCollection new: 100.
	self missingSignatories pairsDo: [:initials :name |
		missing add: initials.
	].
	^ missing asSet intersection: returned asSet!

----- Method: Authorship>>returnedAuthorsWithMethods (in category 'filtering') -----
returnedAuthorsWithMethods
	^ authorDictionary select: [ :eachAssoc | eachAssoc value notEmpty ]!

----- Method: Authorship>>returnedSignatories (in category 'data') -----
returnedSignatories

"This is a list of all Squeak contributors who have returned a signed distribution agreement.

Aug 21st  2008

---

initials         name"
^ #(
'AB'               'Alexandre Bergel'
'ab'               'Avi Bryant or Alexandre Bergel'
'ac'               'Andrew Catton'
'ACG'              'Andrew C. Greenberg'
'acg'              'Andrew C. Greenberg'
'ack'              'Alan Kay'
'ads'              'Adam Spitz'
'AFi'              'Alain Fischer'
'ajh'              'Anthony Hannan'
'aka'              'Mark Guzdial'
'al'               'Adrian Lienhard or Alexander Lazarevic'
'aoy'              'Andres Otaduy'
'apb'              'Andrew P. Black'
'apl'              'Alain Plantec'
'ar'               'Andreas Raab'
'???'               'Andreas Raab'
'asm'              'Alejandro Magistrello'
'avi'              'Avi Bryant'
'ba'			'Bob Arning'
'bf'               'Bert Freudenberg'
'BEO'              'Bruce O''Neel '
'BG'               'Boris Gaertner'
'bg'               'Boris Gaertner'
'bh'               'Bob Hartwig'
'BJP'              'Bijan Parsia'
'BJP
9/9/1998'              'Bijan Parsia'
'bk'              'Bolot Kerimbaev'
'bkv'              'Brent Vukmer'
'bob'			'Bob Arning'
'bolot'            'Bolot Kerimbaev'
'bootstrap'        'Pavel Krivanek'
'BP'               'Brent Pinkney'
'bp'               'Brent Pinkney or Bernhard Pieber'
'brp'              'Brent Pinkney'
'brp`'              'Brent Pinkney'
'btr'              'Brian Rice'
'bvs'              'Ben Schroeder'
'cbc'              'Chris Cunningham'
'ccn'              'Chris Norton'
'ccn+ceg'          'Chris Norton and Carl Gundel'
'ceg'       'Carl Gundel'
'CdG'              'Cees de Groot'
'cds'              'C. David Shaffer'
'chronograph'               'Tetsuya Hayashi'
'cmm'              'Chris Muller'
'crl'              'Craig Latta'
'cwp'              'Colin Putney'
'daf'              'Dave Faught'
'dao'              'danil osipchuk'
'das'              'David A Smith'
'DAS'              'David A Smith'
'dc'               'Damien Cassou'
'dd'               'Dominique Dutoit'
'de'               'Scott Wallace'
'dew'              'Doug Way'
'DF'               'Diego Fernandez'
'dgd'              'Diego Gomez Deck'
'dhhi'             'Dan Ingalls'
'di'               'Dan Ingalls'
'di
'               'Dan Ingalls'
'6/5/97'               'Dan Ingalls'
'6/6/97'               'Dan Ingalls'
'6/7/97'               'Dan Ingalls'
'6/8/97'               'Dan Ingalls'
'6/9/97'               'Dan Ingalls'
'6/10/97'               'Dan Ingalls'
'6/11/97'               'Dan Ingalls'
'6/13/97'               'Dan Ingalls'
'6/18/97'               'Dan Ingalls'
'djp'              'David J. Pennell'
'DM'               'Duane Maxwell'
'dm'               'Duane Maxwell/EntryPoint'
'DSM'              'Duane Maxwell'
'DSM
10/15/1999'              'Duane Maxwell'
'drm'              'Delbert Murphy'
'dtl'              'Dave Lewis'
'dv'              'Daniel Vainsencher'
'dvf'              'Daniel Vainsencher'
'dvf
6/10/2000'              'Daniel Vainsencher'
'eat'              'Eric Arseneau Tremblay'
'edc'              'Edgar DeCleene or Marcus Denker'
'efc'              'Eddie Cottongim'
'efo'              'Emilio Oca'
'em'               'Ernest Micklei?'
'emm'              'Ernest Micklei'
'es'               'Enrico Spinielli'
'fbs'              'Frank Shearar'
'FBS'              'Frank Shearar'
'fbs'              'Frank Shearar'
'fc'               'Frank Caggiano'
'fcs'              'Frank Sergeant'
'fm'               'Florin Mateoc'
'gh'               'Goran Krampe (nee Hultgren)'
'gk'               'Goran Krampe (nee Hultgren)'
'gm'               'German Morales'
'go'               'Georg Gollmann'
'gsa'              'German Arduino'
'HEG'              'Henrik Ekenberg'
'HilaireFernandes' 'Hilaire Fernandes'
'hk'               'Herbert Konig'
'hmm'              'Hans-Martin Mosner'
'hpt'              'Hernan Tylim'
'huma'             'Lyndon Tremblay'
'ich.'             'Yuji Ichikawa'
'ikp'              'Ian Piumarta'
'jaf'              'Jan Fietz'
'jam'              'Javier Musa'
'jb'              'Jim Benson'
'jcg'              'Joshua Gargus'
'jdf'              'David Farber'
'jdr'              'Javier Diaz-Reinoso'
'je'               'Joern Eyrich'
'je77'             'Jochen Rick'
'JF'               'Julian Fitzell'
'jf'               'Julian Fitzell'
'jhm'              'John Maloney'
'jm'              'John Maloney'
'jm
'              'John Maloney'
'jlb'              'Jim Benson'
'jmb'              'Hans Baveco'
'JMM'              'John McIntosh'
'JMV'              'Juan Manuel Vuletich'
'jmv'              'Juan Manuel Vuletich'
'jon'              'Jon Hylands'
'JP'               'Joseph Pelrine'
'jp'               'Joseph Pelrine'
'jrm'              'John-Reed Maffeo'
'jrp'              'John Pierce'
'jsp'              'Jeff Pierce'
'JW'               'Jesse Welton'
'jws'			'John Sarkela'
'JWS'		'John Sarkela'
'ka'               'Kazuhiro Abe'
'kfr'              'Karl Ramberg'
'KLC'              'Ken Causey'
'klc'              'Ken Causey'
'KR'               'korakurider'
'KTT'              'Kurt Thams'
'kwl'              'Klaus D. Witzel'
'ky'               'Koji Yokokawa'
'laza'             'Alexander Lazarevic'
'LB'               'Leo Burd'
'LC'               'Leandro Caniglia'
'lc'               'Leandro Caniglia'
'LEG'              'Gerald Leeb'
'len'              'Luciano Esteban Notarfrancesco'
'lr'               'Lukas Renggli'
'lrs'              'Lorenzo Schiavina'
'ls'               'Lex Spoon'
'LS'               'Lex Spoon'
'm3r'              'Maurice Rabb'
'MAL'              'Michael Latta'
'mas'              'Mark Schwenk'
'm'                'Marcus Denker'
'MD'               'Marcus Denker'
'md'               'Marcus Denker'
'md\'              'Marcus Denker'
'mdr'              'Mike Rutenberg'
'mga'              'Markus Galli'
'miki'             'Mikael Kindborg'
'mikki'            'Mikael Kindborg'
'mir'              'Michael Rueger'
'mist'             'Michal Starke'
'MJG'              'Mark Guzdial'
'mjg'              'Mark Guzdial'
'mjg
8/31/1998'              'Mark Guzdial'
'mjg
9/9/1998'              'Mark Guzdial'
'mjg
9/23/1998'              'Mark Guzdial'
'mjr'              'Mike Roberts'
'mjt'              'Mike Thomas'
'mk'               'Matej Kosik'
'mlr'              'Michael Rueger'
'MPW'              'Marcel Weiher'
'mpw'              'Marcel Weiher'
'mrm'              'Martin McClure'
'MPH'              'Michael Hewner'
'ms'               'math'
'MU'               'Masashi Umezawa'
'mu'               'Masashi Umezawa'
'mw'               'Martin Wirblat'
'nb'               'Naala Brewer'
'nice'             'Nicolas Cellier'
'nk'               'Ned Konz'
'nop'              'Jay Carlson'
'Noury'            'Noury Bouraqadi'
'NS'               'Nathanael Schaerli'
'panda'            'Michael Rueger'
'PHK'              'Peter Keeler'
'pk'               'Pavel Krivanek'
'pm'               'Patrick Mauritz'
'pnm'              'Paul McDonough'
'pnm
8/23/2000'              'Paul McDonough'
'RAA'              'Bob Arning'
'RAA
3/28/2000'              'Bob Arning'
'raa'              'Bob Arning'
'raok'             'Richard A. O''Keefe'
'rbb'              'Brian Brown'
'rca'              'Russell Allen'
'reThink'          'Paul McDonough'
'rew'              'Roger Whitney'
'rhi'              'Robert Hirschfeld'
'rh'              'Robert Hirschfeld'
'Rik'              'Rik Fischer SmOOdy'
'rk'               'Ram Krishnan'
'rkris'               'Ram Krishnan'
'RJT'              'Ron Teitelbaum'
'RM'			'Rick McGeer'
'rr'               'Romain Robbes'
'rw'               'Roel Wuyts'
'rw'              'Robert Withers'
'rww'              'Robert Withers'
'sbw'              'Stephan B. Wessels'
'SD'               'Stephane Ducasse'
'sd'               'Stephane Ducasse'
'stephaneducassse'               'Stephane Ducasse'
'sge'              'Steve Elkins'
'shrink'           'Pavel Krivanek'
'slg'              'Steve Gilbert'
'sm'               'Simon Michael'
'sma'              'Stefan Matthias Aust'
'sn'               'Suslov Nikolay'
'spfa'             'Stephane Rollandin'
'sps'              'Steven Swerling'
'sqr'              'Andres Valloud'
'SqR'              'Andres Valloud'
'SqR!!!!'            'Andres Valloud'
'SqR!!!!!!!!'         'Andres Valloud'
'sr'               'Stephan Rudlof'
'ssa'              'Sam S. Adams'
'Sames'            'Samuel S. Shuster'
'SSS'              'Samuel S. Shuster'
'st'               'Samuel Tardieu'
'stephaneducasse'  'Stephane Ducasse'
'stp'              'Stephen Travis Pope'
'sumim'            'Masato Sumi'
'svp'              'Stephen Vincent Pair'
'sw'               'Scott Wallace'
'sws'              'Scott Wallace'
'T2'               'Toshiyuki Takeda'
'tak'              'Takashi Yamamiya'
'tao'              'Tim Olson'
'tb'               'Todd Blanchard or Torsten Bergman'
'TBn'              'Torsten Bergmann'
'tbn'              'Torsten Bergmann'
'tetha'            'Tetsuya Hayashi'
'tfei'             'The Fourth Estate, Inc.'
'th'               'Torge Husfeldt'
'ti'               'Tobias Isenberg'
'TJ'               'TJ Leone'
'tk'               'Ted Kaehler'
'tk
9/13/97'               'Ted Kaehler'
'tk
12/6/2004'               'Ted Kaehler'
'tk
11/29/2004'               'Ted Kaehler'
'tk
11/26/2004'               'Ted Kaehler'
'tk'               'Thomas Kowark'
'tlk'              'Tom Koenig'
'TN'               'korakurider'
'TPR'              'Tim Rowledge'
'tpr'              'Tim Rowledge'
'TAG'              'Travis Griggs'
'TRee'             'Trygve Reenskaug'
'ts'          'Shortsleeved'
'Tsutomu'          'Tsutomu Hiroshima'
'tween'            'Andy Tween'
'vb'               'Vassili Bykov'
'vbdew'               'Vassili Bykov and Doug Way'
'vj'               'Vladimir Janousek'
'wiz'              'Jerome Peace'
'wod'              'Bill Dargel'
'ykoubo'           'Koji Yokokawa'
'yo'               'Yoshiki Ohshima'
'ward'             'Ward Cunningham'
'zz'               'Serge Stinckwich'
)!

Object subclass: #MethodHistoryDatabase
	instanceVariableNames: 'dictionary'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'MethodAuthorship'!

----- Method: MethodHistoryDatabase>>at: (in category 'all') -----
at: className

	^ dictionary at: className ifAbsent: [^ Dictionary new].
!

----- Method: MethodHistoryDatabase>>at:at: (in category 'all') -----
at: className at: sel

	dictionary at: className ifPresent: [:dict | dict at: sel ifPresent: [:col | ^ col]].
	^ Array new.
!

----- Method: MethodHistoryDatabase>>initialize (in category 'all') -----
initialize

	super initialize.
	dictionary := IdentityDictionary new.
!

----- Method: MethodHistoryDatabase>>keys (in category 'all') -----
keys

	^ dictionary keys
!

----- Method: MethodHistoryDatabase>>processChangesFile:encoding: (in category 'all') -----
processChangesFile: aFilename encoding: encodingString

	| aStream c |
	aStream := FileStream readOnlyFileNamed: aFilename.
	aStream converter: (TextConverter newForEncoding: encodingString).
	c := MethodHistoryChangeList new.
	c scanFile: aStream from: 0 to: aStream size.
	c removeDoIts.
	aStream close.
	^ c.
!

----- Method: MethodHistoryDatabase>>processChangesList: (in category 'all') -----
processChangesList: aCollection
"
	'Processing...' displayProgressAt: Display center from: 1 to: aCollection changeList size during: [:bar |
		aCollection changeList withIndexDo: [:record :ind |
			bar value: ind.
			self processRecord: record.
		].
	]."

	aCollection changeList do: [:record |
		self processRecord: record]
!

----- Method: MethodHistoryDatabase>>processRecord: (in category 'all') -----
processRecord: rec

	| col clsName sel cls |
	cls := rec methodClass.
	cls ifNil: [^ self].
	clsName := cls asSymbol.
	sel := rec methodSelector.
	sel ifNil: [^ self].
		dictionary at: clsName ifAbsent: [
dictionary at: clsName put: IdentityDictionary new].
	(dictionary at: clsName) at: sel ifAbsent: [(dictionary at: clsName) at: sel put: OrderedCollection new].

	col := (dictionary at: clsName) at: sel.
	col detect: [:old | old equals: rec] ifNone: [
		col addFirst: rec
	].
!

----- Method: MethodHistoryDatabase>>readFile:encodingName: (in category 'all') -----
readFile: aFilename encodingName: encodingName

	| c |
	Transcript show: 'reading... ', aFilename; cr.
	c := self processChangesFile: aFilename encoding: encodingName.
	self processChangesList: c.
!

----- Method: MethodHistoryDatabase>>readFilesIn:updateFile:versionName: (in category 'all') -----
readFilesIn: dir updateFile: updateFileName versionName: versionName

	| updates more line file encoding |
	updates := dir readOnlyFileNamed: updateFileName.
	more := true.
	[more] whileTrue: [
		updates atEnd ifTrue: [updates close. ^ self].
		line := updates upTo: Character cr.
		line ifNil: [updates close. ^ self].
		line size > 0 ifTrue: [
			line first = $# ifTrue: [
				(line copyFrom: 2 to: line size) = versionName ifTrue: [more := false]].
		].
	].
	more := true.
	[more] whileTrue: [
		updates atEnd ifTrue: [updates close. ^ self].
		line := updates upTo: Character cr.
		line ifNil: [^ self].
		(line first = $#) ifTrue: [^ self].
		file := dir readOnlyFileNamed: line.
		file binary.
		encoding := ((file next: 3) = (ByteArray with: 16rEF with: 16rBB with: 16rBF)) ifTrue: ['utf-8'] ifFalse: ['mac-roman'].
		self readFile: file fullName encodingName: encoding.
	].
!

----- Method: MethodHistoryDatabase>>size (in category 'all') -----
size

	^ dictionary size.
!

----- Method: MethodHistoryDatabase>>sourceCodeAt:at: (in category 'all') -----
sourceCodeAt: className at: sel

	dictionary at: className ifPresent: [:dict | dict at: sel ifPresent: [:col | ^ col first text]].
	^ ''
!

----- Method: MethodHistoryDatabase>>writeDict:toFileName: (in category 'all') -----
writeDict: aDict toFileName: aFileName

	| f |
	f := FileStream newFileNamed: aFileName.
	aDict keys asSortedCollection do: [:k |
		f nextPutAll: (aDict at: k) printString; cr.
	].
	f close.
!

----- Method: MethodHistoryDatabase>>writeDictWithVersion:toHTMLFileNameOn:title: (in category 'all') -----
writeDictWithVersion: aDict toHTMLFileNameOn: aStream title: aString

	self writeDictWithVersion: aDict toHTMLFileNameOn: aStream title: aString explanationFileName: nil.
!

----- Method: MethodHistoryDatabase>>writeDictWithVersion:toHTMLFileNameOn:title:explanationFileName: (in category 'all') -----
writeDictWithVersion: aDict toHTMLFileNameOn: aStream title: aString explanationFileName: explanation

	| entries current prev history firstPart secondPart diffString oldStamp newStamp |
	firstPart _ WriteStream on: (String new: 10).
	secondPart _ WriteStream on: (String new: 10).
	aStream nextPutAll: '<html><head>'.
	aStream nextPutAll: '<title>'.
	aStream nextPutAll: aString.
	aStream nextPutAll: '</title></head><body>'.
	aStream cr.
	aStream nextPutAll: '<H2>'.
	aStream nextPutAll: aString.
	aStream nextPutAll: '</H2>'.
	aStream cr.
	explanation ifNotNil: [
		aStream nextPutAll: (FileStream readOnlyFileNamed: explanation) contentsOfEntireFile].

	aDict keys asSortedCollection do: [:k |
		entries _ aDict at: k.
		entries do: [:m |
			history := self at: m methodClass asSymbol at: m methodSelector.
			current _ history size > 0 ifTrue: [history first text] ifFalse: [''].
			prev _ history size > 1 ifTrue: [history second text] ifFalse: [''].
			firstPart nextPutAll: '<A HREF="#'.
			firstPart nextPutAll: m methodClass asString, '-', m methodSelector asString.
			firstPart nextPutAll: '">'.
			firstPart nextPutAll: m methodClass, '>>', m methodSelector.
			firstPart nextPutAll: '</A><BR>'.
			firstPart nextPut: Character cr.
			secondPart nextPutAll: '<A NAME="'.
			secondPart nextPutAll: m methodClass asString, '-', m methodSelector asString.
			secondPart nextPutAll: '">'.
			secondPart nextPutAll: '<table border=1 vspace=5px width=90%>'.
			secondPart nextPutAll: '<tr><td>'.
			secondPart nextPutAll: m methodClass asString, '>>', m methodSelector asString.
			oldStamp := history size > 1 ifTrue: [history second stamp] ifFalse: [''].
			oldStamp ifEmpty: [oldStamp := 'no stamp'].
			newStamp := history size > 0 ifTrue: [history first stamp] ifFalse: [''].
			newStamp ifEmpty: [newStamp := 'no stamp'].
			secondPart nextPutAll: ': ('.
			secondPart nextPutAll: oldStamp.
			secondPart nextPutAll: ' -> '.
			secondPart nextPutAll: newStamp.
			secondPart nextPutAll: ')'.
			secondPart nextPutAll: '<tr><td><pre>'.
			secondPart nextPutAll: (prev ifEmpty: ['no previous history'] ifNotEmpty: [TextDiffBuilder buildHTMLPatchFrom: prev asHtmlNOBR to: prev asHtmlNOBR]).
			secondPart nextPutAll: '</pre></td></tr>'.
			secondPart nextPut: Character cr.
			secondPart nextPutAll: '<tr><td><pre>'.
			secondPart nextPutAll: (current ifEmpty: ['not found'] ifNotEmpty: [TextDiffBuilder buildHTMLPatchFrom: current asHtmlNOBR to: current asHtmlNOBR]).
			secondPart nextPutAll: '</pre></td></tr>'.
			(prev size > 0 and: [current size > 0]) ifTrue: [
				diffString := TextDiffBuilder buildHTMLPatchFrom: prev asHtmlNOBR to: current asHtmlNOBR.
				secondPart nextPutAll: '<tr><td><pre>'.
				secondPart nextPutAll: diffString.
				secondPart nextPutAll: '</pre></td></tr>'.
			].
			secondPart nextPutAll: '</table>'.
			secondPart nextPut: Character cr.
			secondPart cr.
		].
	].
	aStream nextPutAll: firstPart contents.
	aStream cr.
	aStream nextPutAll: secondPart contents.

	aStream nextPutAll: '</body></html>'.
!

VersionsBrowser subclass: #MethodHistoryVersionBrowser
	instanceVariableNames: 'database'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'MethodAuthorship'!

----- Method: MethodHistoryVersionBrowser class>>browseVersionsOf:class:meta:category:selector:database: (in category 'as yet unclassified') -----
browseVersionsOf: method class: class meta: meta category: msgCategory selector: selector database: database
	^ self new class: class meta: meta selector: selector database: database
!

----- Method: MethodHistoryVersionBrowser>>class:meta:selector:database: (in category 'all') -----
class: cls meta: isMeta selector: sel database: db
	| c |
	database := db.
	classOfMethod _ cls.
	selectorOfMethod _ sel.
	list _ database at: (classOfMethod name, (isMeta ifTrue: [' class'] ifFalse: ['']))  asSymbol at: selectorOfMethod.
	c := MethodHistoryChangeList new.
	list do: [:l |
		c addItem: l text: (l stamp ifNotEmpty: [l stamp] ifEmpty: ['no stamp']), ' (', l fileName, ')'].
	c initializeForDatabase.
	MethodHistoryChangeList open: c name: 'Recent versions of ' , sel multiSelect: false.
!

----- Method: MethodHistoryVersionBrowser>>reformulateList (in category 'all') -----
reformulateList
	| col |
	col := database at: classOfMethod asSymbol at: selectorOfMethod.
	col ifEmpty: [^ self].

	list _ col.
	listIndex _ 1.
	self changed: #listIndex.
	self contentsChanged
!

ChangeRecord subclass: #MethodHistoryChangeRecord
	instanceVariableNames: 'text selector sourceFile'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'MethodAuthorship'!

----- Method: MethodHistoryChangeRecord>>author (in category 'all') -----
author

	^ (stamp copyUpTo: $ ) copyWithout: Character lf.
!

----- Method: MethodHistoryChangeRecord>>class:selector:stamp:text:sourceFile: (in category 'all') -----
class: clsName selector: sel stamp: st text: t sourceFile: fileName

	class _ clsName copyUpTo: $ .	"the non-meta part of a class name"
	meta _ clsName endsWith: ' class'.
	selector := sel.
	stamp := st.
	text := t.
	type := #method.
	sourceFile := fileName.
!

----- Method: MethodHistoryChangeRecord>>equals: (in category 'all') -----
equals: another

	"^ self methodClassName = another methodClassName and: [
		self methodSelector = another methodSelector and: [
			self text = another text and: [self stamp = another stamp]]].
"
	^ self text = another text and: [self stamp = another stamp]!

----- Method: MethodHistoryChangeRecord>>fileName (in category 'all') -----
fileName

	^ sourceFile ifNil: ['unknown'].
!

----- Method: MethodHistoryChangeRecord>>methodClass (in category 'all') -----
methodClass

	^ class, (meta ifTrue: [' class'] ifFalse: ['']).
!

----- Method: MethodHistoryChangeRecord>>methodSelector (in category 'all') -----
methodSelector

	^ selector!

----- Method: MethodHistoryChangeRecord>>shortPrintOn: (in category 'all') -----
shortPrintOn: aStream
	"Print the receiver on a stream"

	aStream nextPutAll: ' ', self methodClass name, ' >> ', self methodSelector, ' (', self stamp, ')'!

----- Method: MethodHistoryChangeRecord>>string (in category 'all') -----
string

	^ text
!

----- Method: MethodHistoryChangeRecord>>text (in category 'all') -----
text

	^ text ifNil: [text := super text].
!



More information about the Packages mailing list