'From Squeak3.7alpha of ''11 September 2003'' [latest update: #5566] on 8 December 2003 at 4:58:11 pm'! "Change Set: CompareArbitraryVersions-nk Date: 5 December 2003 Author: Ned Konz Squeak Version: 3.7a (uses #translated) Adds a 'compare to selected version' feature to the VersionsBrowser, letting you compare any method version with any other version. Compares the changeset timestamps to determine which is the 'from' version. 5 Dec.: removed automatic re-ordering by timestamps. Also adds a couple of utility methods: ChangeRecord>>timeStamp returns a TimeStamp (MenuMorph,CustomMenu)>>addTranslatedList: sends #translate to its strings "! !VersionsBrowser commentStamp: 'nk 11/25/2003 10:04' prior: 0! VersionsBrowser shows all the versions of a particular method, and lets you compare them, revert to selected versions, and so on.! !ChangeRecord methodsFor: 'access' stamp: 'nk 11/25/2003 09:44'! timeStamp "Answer a TimeStamp that corresponds to my (text) stamp" | tokens date time | tokens := self stamp findTokens: Character separators. ^ tokens size > 2 ifTrue: [[date := Date fromString: (tokens at: tokens size - 1). time := Time fromString: tokens last. TimeStamp date: date time: time] on: Error do: [:ex | ex return: (TimeStamp fromSeconds: 0)]] ifFalse: [TimeStamp fromSeconds: 0]! ! !CustomMenu methodsFor: 'construction' stamp: 'nk 11/25/2003 10:00'! addTranslatedList: listOfTuplesAndDashes "Add a menu item to the receiver for each tuple in the given list of the form ( ). Add a line for each dash (-) in the list. The tuples may have an optional third element, providing balloon help for the item, but such an element is ignored in mvc. The first element will be translated." listOfTuplesAndDashes do: [:aTuple | aTuple == #- ifTrue: [self addLine] ifFalse: [self add: aTuple first translated action: aTuple second]] "CustomMenu new addTranslatedList: #( ('apples' buyApples) ('oranges' buyOranges) - ('milk' buyMilk)); startUp" ! ! !MenuMorph methodsFor: 'construction' stamp: 'nk 11/25/2003 09:59'! addTranslatedList: aList "Add the given items to this menu, where each item is a pair ( ).. If an element of the list is simply the symobl $-, add a line to the receiver. The optional third element of each entry, if present, provides balloon help. The first and third items will be translated." aList do: [:tuple | (tuple == #-) ifTrue: [self addLine] ifFalse: [self add: tuple first translated action: tuple second. tuple size > 2 ifTrue: [self balloonTextForLastItem: tuple third translated ]]]! ! !VersionsBrowser methodsFor: 'menu' stamp: 'nk 12/8/2003 16:47'! compareToOtherVersion "Prompt the user for a reference version, then spawn a window showing the diffs between the older and the newer of the current version and the reference version as text." | change1 change2 s1 s2 | change1 := changeList at: listIndex ifAbsent: [ ^self ]. change2 := ((SelectionMenu labels: (list copyWithoutIndex: listIndex) selections: (changeList copyWithoutIndex: listIndex)) startUp) ifNil: [ ^self ]. "compare earlier -> later" "change1 timeStamp < change2 timeStamp ifFalse: [ | temp | temp _ change1. change1 _ change2. change2 _ temp ]." s1 := change1 string. s2 := change2 string. s1 = s2 ifTrue: [^ self inform: 'Exact Match' translated]. (StringHolder new textContents: (TextDiffBuilder buildDisplayPatchFrom: s1 to: s2 inClass: classOfMethod prettyDiffs: self showingPrettyDiffs)) openLabel: (('Comparison from {1} to {2}' translated) format: { change1 stamp. change2 stamp })! ! !VersionsBrowser methodsFor: 'menu' stamp: 'nk 11/25/2003 10:19'! versionsHelpString ^ 'Each entry in the list pane represents a version of the source code for the same method; the topmost entry is the current version, the next entry is the next most recent, etc. To revert to an earlier version, select it (in the list pane) and then do any of the following: * Choose "revert to this version" from the list pane menu. * Hit the "revert" button, * Type ENTER in the code pane * Type cmd-s (alt-s) in the code pane. The code pane shows the source for the selected version. If "diffing" is in effect, then differences betwen the selected version and the version before it are pointed out in the pane. Turn diffing on and off by choosing "toggle diffing" from the list pane menu, or hitting the "diffs" button, or hitting cmd-D when the cursor is over the list pane. To get a comparison between the selected version and the current version, choose "compare to current" from the list pane menu or hit the "compare to current" button. (This is meaningless if the current version is selected, and is unnecessary if you''re interested in diffs from between the current version and the next-most-recent version, since the standard in-pane "diff" feature will give you that.) You can also compare the selected version with any other version using the "compare to version..." menu choice. If further versions of the method in question have been submitted elsewhere since you launched a particular Versions Browser, it will still stay nicely up-to-date if you''re in Morphic and have asked that smart updating be maintained; if you''re in mvc or in morphic but with smart-updating turned off, a versions browser is only brought up to date when you activate its window (and when you issue "revert" from within it, of course,) and you can also use the "update list" command to make certain the versions list is up to date. Hit the "remove from changes" button, or choose the corresponding command in the list pane menu, to have the method in question deleted from the current change set. This is useful if you''ve put debugging code into a method, and now want to strip it out and cleanse your current change set of all memory of the excursion. Note: the annotation pane in versions browsers shows information about the *current* version of the method in the image, not about the selected version.'! ! !VersionsBrowser methodsFor: 'menu' stamp: 'nk 11/25/2003 10:18'! versionsMenu: aMenu "Fill aMenu with menu items appropriate to the receiver" Smalltalk isMorphic ifTrue: [aMenu title: 'Versions' translated. aMenu addStayUpItemSpecial]. (list size > 1 and: [ listIndex > 0 ]) ifTrue: [ aMenu addTranslatedList: #( ('compare to current' compareToCurrentVersion 'compare selected version to the current version') ('compare to version...' compareToOtherVersion 'compare selected version to another selected version') ('revert to selected version' fileInSelections 'resubmit the selected version, so that it becomes the current version') )]. aMenu addTranslatedList: #( ('remove from changes' removeMethodFromChanges 'remove this method from the current change set, if present') ('edit current method (O)' openSingleMessageBrowser 'open a single-message browser on the current version of this method') ('find original change set' findOriginalChangeSet 'locate the changeset which originally contained this version') - ('toggle diffing (D)' toggleDiffing 'toggle whether or not diffs should be shown here') ('update list' reformulateList 'reformulate the list of versions, in case it somehow got out of synch with reality') - ('senders (n)' browseSenders 'browse all senders of this selector') ('implementors (m)' browseImplementors 'browse all implementors of this selector') - ('help...' offerVersionsHelp 'provide an explanation of the use of this tool')). ^aMenu! !