Frank Shearar uploaded a new version of UpdateStream to project The Trunk:
http://source.squeak.org/trunk/UpdateStream-fbs.3.mcz ==================== Summary ==================== Name: UpdateStream-fbs.3 Author: fbs Time: 6 December 2013, 8:56:59.9 pm UUID: 2d0c0933-b30f-da40-a681-f45f01308218 Ancestors: UpdateStream-nice.2 FilePackage has a bunch of logic around handling update streams' changesets. This logic now belongs in UpdateStream. =============== Diff against UpdateStream-nice.2 =============== Item was added: + ----- Method: FilePackage class>>conflictsWithUpdatedMethods: (in category '*UpdateStream-instance creation') ----- + conflictsWithUpdatedMethods: fullName + | conflicts changeList | + conflicts := (self fromFileNamed: fullName) conflictsWithUpdatedMethods. + conflicts isEmpty ifTrue: [^ self]. + changeList := ChangeList new. + changeList + changes: conflicts + file: (FileDirectory default readOnlyFileNamed: fullName) close. + ChangeList + open: changeList + name: 'Conflicts for ', (FileDirectory localNameFor: fullName) + multiSelect: true.! Item was added: + ----- Method: FilePackage class>>fileReaderServicesForFile:suffix: (in category '*UpdateStream-reader service') ----- + fileReaderServicesForFile: fullName suffix: suffix + + ^(suffix = 'st') | (suffix = 'cs') | (suffix = '*') + ifTrue: [self services] + ifFalse: [#()]! Item was added: + ----- Method: FilePackage class>>serviceConflictsWithUpdatedMethods (in category '*UpdateStream-reader service') ----- + serviceConflictsWithUpdatedMethods + ^ SimpleServiceEntry + provider: self + label: 'conflicts with updated methods' + selector: #conflictsWithUpdatedMethods: + description: 'check for conflicts with more recently updated methods in the image, showing the conflicts in a transcript window' + buttonLabel: 'conflicts'! Item was added: + ----- Method: FilePackage class>>services (in category '*UpdateStream-reader service') ----- + services + ^ Array with: self serviceConflictsWithUpdatedMethods! Item was added: + ----- Method: FilePackage>>checkForMoreRecentUpdateThanChangeSet:pseudoClass:selector: (in category '*UpdateStream-conflict checker') ----- + checkForMoreRecentUpdateThanChangeSet: updateNumberChangeSet pseudoClass: pseudoClass selector: selector + "Returns the source code for a conflict if a conflict is found, otherwise returns nil." + + | classOrMeta allChangeSets moreRecentChangeSets conflictingChangeSets changeRecordSource classAndMethodPrintString | + + classAndMethodPrintString := pseudoClass name, (pseudoClass hasMetaclass ifTrue: [' class'] ifFalse: ['']), '>>', selector asString. + + changeRecordSource := pseudoClass sourceCode at: selector. + changeRecordSource isText + ifTrue: [changeRecordSource := Text + fromString: 'method: ', classAndMethodPrintString, ' was removed'] + ifFalse: [changeRecordSource stamp isEmptyOrNil ifTrue: + [self notify: 'Warning: ', classAndMethodPrintString, ' in ', self packageName, ' has no timestamp/initials!!']]. + + pseudoClass exists ifFalse: + [(self classes at: pseudoClass name) hasDefinition + ifTrue: [^ nil "a method was added for a newly defined class; not a conflict"] + ifFalse: [self class logCr; log: 'CONFLICT found for ', classAndMethodPrintString, '... class ', pseudoClass name asString, ' does not exist in the image and is not defined in the file'. + ^ changeRecordSource]]. + + classOrMeta := pseudoClass realClass. + + "Only printout the replacing methods here, but we still check for removed methods too in the rest of this method." + (self class verboseConflicts and: [classOrMeta includesSelector: selector]) + ifTrue: [self class logCr; log: '...checking ', classOrMeta asString, '>>', selector asString]. + + allChangeSets := ChangesOrganizer allChangeSets. + moreRecentChangeSets := allChangeSets + copyFrom: (allChangeSets indexOf: updateNumberChangeSet) + to: (allChangeSets size). + conflictingChangeSets := (moreRecentChangeSets select: + [:cs | (cs atSelector: selector class: classOrMeta) ~~ #none]). + conflictingChangeSets isEmpty ifTrue: [^ nil]. + + self class logCr; log: 'CONFLICT found for ', classAndMethodPrintString, + (' with newer changeset' asPluralBasedOn: conflictingChangeSets). + conflictingChangeSets do: [:cs | self class log: ' ', cs name]. + ^ changeRecordSource + ! Item was added: + ----- Method: FilePackage>>conflictsWithUpdatedMethods (in category '*UpdateStream-conflict checker') ----- + conflictsWithUpdatedMethods + "Check this package for conflicts with methods in the image which are in newer updates." + + | localFileName stream updateNumberString updateNumber imageUpdateNumber updateNumberChangeSet conflicts fileStream | + + localFileName := FileDirectory localNameFor: fullName. + stream := ReadStream on: sourceSystem. + stream upToAll: 'latest update: #'. + updateNumberString := stream upTo: $]. + stream close. + + fileStream := FileStream readOnlyFileNamed: fullName. + (fileStream contentsOfEntireFile includes: Character linefeed) + ifTrue: [self notifyWithLabel: 'The changeset file ', localFileName, ' contains linefeeds. Proceed if... + you know that this is okay (e.g. the file contains raw binary data).']. + fileStream close. + + updateNumberString isEmpty ifFalse: "remove prepended junk, if any" + [updateNumberString := (updateNumberString findTokens: Character space) last]. + updateNumberString asInteger ifNil: + [(self confirm: 'Error: ', localFileName, ' has no valid Latest Update number in its header. + Do you want to enter an update number for this file?') + ifFalse: [^ self] + ifTrue: [updateNumberString := UIManager default + request: 'Please enter the estimated update number (e.g. 4332).']]. + updateNumberString asInteger ifNil: [self inform: 'Conflict check cancelled.'. ^ self]. + updateNumber := updateNumberString asInteger. + + imageUpdateNumber := SystemVersion current highestUpdate. + updateNumber > imageUpdateNumber ifTrue: + [(self confirm: 'Warning: The update number for this file (#', updateNumberString, ') + is greater than the highest update number for this image (#', imageUpdateNumber asString, '). + This probably means you need to update your image. + Should we proceed anyway as if the file update number is #', imageUpdateNumber asString, '?') + ifTrue: + [updateNumber := imageUpdateNumber. + updateNumberString := imageUpdateNumber asString] + ifFalse: [^ self]]. + + updateNumberChangeSet := self findUpdateChangeSetMatching: updateNumber. + updateNumberChangeSet ifNil: [^ self]. + + Smalltalk isMorphic ifTrue: [self currentWorld findATranscript: self currentEvent]. + self class logCr; logCr; log: 'Checking ', localFileName, ' (#', updateNumberString, ') for method conflicts with changesets after ', updateNumberChangeSet name, ' ...'. + + conflicts := OrderedCollection new. + self classes do: [:pseudoClass | + (Array with: pseudoClass with: pseudoClass metaClass) do: [:classOrMeta | + classOrMeta selectorsDo: [:selector | | conflict | + conflict := self + checkForMoreRecentUpdateThanChangeSet: updateNumberChangeSet + pseudoClass: classOrMeta + selector: selector. + conflict ifNotNil: [conflicts add: conflict]. + ]. + ]. + ]. + self class logCr; log: conflicts size asString, (' conflict' asPluralBasedOn: conflicts), ' found.'; logCr. + self class closeLog. + ^ conflicts! Item was added: + ----- Method: FilePackage>>findUpdateChangeSetMatching: (in category '*UpdateStream-conflict checker') ----- + findUpdateChangeSetMatching: updateNumber + "Find update-changeset beginning with updateNumber, or reasonably close." + "This is to account for the fact that many changeset files are output from final releases, but may be tested for conflicts in a following alpha image, which will often not include that particular update-changeset from the final release but will contain ones near it. For example, if the file updateNumber is 5180 (from 3.5 final), but the image has no update-changeset beginning with 5180 because it's a 3.6alpha image (which starts at 5181), it will try up to 5190 and down to 5170 for a close match." + | updateNumberChangeSet updateNumberToTry | + + updateNumberToTry := updateNumber. + updateNumberChangeSet := nil. + [updateNumberChangeSet isNil and: [updateNumberToTry notNil]] whileTrue: + [updateNumberChangeSet := ChangesOrganizer allChangeSets + detect: [:cs | (cs name beginsWith: updateNumberToTry asString) + and: [(cs name at: (updateNumberToTry asString size + 1)) isDigit not]] + ifNone: [nil]. + updateNumberToTry >= updateNumber ifTrue: + [updateNumberToTry < (updateNumber + 10) + ifTrue: [updateNumberToTry := updateNumberToTry + 1] + ifFalse: [updateNumberToTry := updateNumber]]. + updateNumberToTry <= updateNumber ifTrue: + [updateNumberToTry > (updateNumber - 10) + ifTrue: [updateNumberToTry := updateNumberToTry - 1] + ifFalse: [updateNumberToTry := nil "we're done trying"]]. + ]. + + updateNumberChangeSet ifNil: + [(self confirm: 'Warning: No changeset beginning with ', + updateNumber asString, ' (within +/- 10) was found in the image. + You must have changesets going back this far in your image + in order to accurately check for conflicts. + Proceed anyway?') + ifTrue: [updateNumberChangeSet := ChangesOrganizer allChangeSets first]]. + + ^ updateNumberChangeSet! |
Free forum by Nabble | Edit this page |