now also look at revisionInfo
authorClaus Gittinger <cg@exept.de>
Sat, 25 Nov 1995 19:02:43 +0100
changeset 96 326cccce2fe7
parent 95 aeda58a2343c
child 97 16fca8aec034
now also look at revisionInfo
AbstrSCMgr.st
AbstractSourceCodeManager.st
--- a/AbstrSCMgr.st	Sat Nov 25 16:27:29 1995 +0100
+++ b/AbstrSCMgr.st	Sat Nov 25 19:02:43 1995 +0100
@@ -64,6 +64,100 @@
     ^ CacheDirectoryName
 !
 
+directoryFromContainerPath:containerPath
+    |path idx|
+
+    path := self pathInRepositoryFrom:containerPath.
+    path notNil ifTrue:[
+        idx := path indexOf:(Filename separator).
+        idx ~~ 0 ifTrue:[
+            path := path copyFrom:(idx + 1)
+        ].
+        ^ path asFilename directoryName
+    ].
+    ^ nil
+
+    "
+     SourceCodeManager directoryFromContainerPath:'/files/CVS/stx/libbasic/Array.st'
+    "
+
+    "Created: 25.11.1995 / 18:42:20 / cg"
+    "Modified: 25.11.1995 / 18:48:46 / cg"
+!
+
+filenameFromContainerPath:containerPath
+    |top rest|
+
+    containerPath notNil ifTrue:[
+        top := self repositoryTopDirectory.
+        top notNil ifTrue:[
+            (containerPath startsWith:(top , '/')) ifTrue:[
+                rest := containerPath copyFrom:(top size + 2).
+                ^ rest asFilename baseName
+            ]
+        ]
+    ].
+
+    "Created: 25.11.1995 / 18:42:34 / cg"
+!
+
+moduleFromContainerPath:containerPath
+    |path idx|
+
+    path := self pathInRepositoryFrom:containerPath.
+    path notNil ifTrue:[
+        idx := path indexOf:(Filename separator).
+        idx == 0 ifTrue:[^ path].
+        ^ path copyTo:(idx - 1)
+    ].
+    ^ nil
+
+    "
+     SourceCodeManager moduleFromContainerPath:'/files/CVS/stx/libbasic/Array.st'
+    "
+
+    "Created: 25.11.1995 / 18:42:20 / cg"
+    "Modified: 25.11.1995 / 18:47:27 / cg"
+!
+
+pathInRepositoryFrom:containerPath
+    |top rest lastTop idx|
+
+    containerPath notNil ifTrue:[
+        top := self repositoryTopDirectory.
+        top notNil ifTrue:[
+            (containerPath startsWith:(top , '/')) ifTrue:[
+                ^ containerPath copyFrom:(top size + 2).
+            ].
+            "/ hardcase - the repository-filename in the versionInfo
+            "/ does no match my repository top.
+            "/ check for mangled prefix (happens with symbolic links)
+            lastTop := '/' , top asFilename baseName, '/'.
+            idx := containerPath indexOfSubCollection:lastTop.
+            idx ~~ 0 ifTrue:[
+                ('SOURCEMGR: warning: repository path mismatch: ' , (containerPath copyTo:idx-1) , lastTop , ' vs. ' , top , '/') infoPrintNL.
+                'SOURCEMGR: warning: assuming that mismatch is ok.' infoPrintNL.
+                ^ containerPath copyFrom:(idx + lastTop size).
+            ]
+        ]
+    ].
+    ^ rest
+
+    "
+     SourceCodeManager pathInRepositoryFrom:'/files/CVS/stx/libbasic/Array.st'
+     SourceCodeManager pathInRepositoryFrom:'/phys/ibm/CVS/stx/libbasic/Array.st'
+    "
+
+    "Created: 25.11.1995 / 18:42:20 / cg"
+    "Modified: 25.11.1995 / 18:59:26 / cg"
+!
+
+repositoryTopDirectory
+    ^ nil
+
+    "Created: 25.11.1995 / 18:38:59 / cg"
+!
+
 revisionAfter:aRevisionString
     |idx s|
 
@@ -98,33 +192,78 @@
     ^ dir
 !
 
+sourceInfoOfClass:aClass
+    "helper: return a classes sourceCodeInfo"
+
+    |cls sourceInfo revInfo actualSourceFileName classFileName
+     newInfo revisionInfo container|
+
+    cls := aClass.
+    cls isMeta ifTrue:[
+        cls := cls soleInstance
+    ].
+
+    "/
+    "/ the info given by the classes source ...
+    "/
+    revInfo := aClass revisionInfo.
+
+    "/
+    "/ the info given by the classes binary ...
+    "/ if present, we better trust that one.
+    "/
+    sourceInfo := cls packageSourceCodeInfo.
+    sourceInfo isNil ifTrue:[
+        revInfo isNil ifTrue:[
+            'SOURCEMGR: class has neither source nor compiled-in info' infoPrintNL.
+            ^ nil
+        ].
+
+        container := revInfo at:#repositoryPathName ifAbsent:nil.
+        container notNil ifTrue:[
+            sourceInfo := revInfo.
+            sourceInfo at:#directory put:(self directoryFromContainerPath:container).
+            sourceInfo at:#module put:(self moduleFromContainerPath:container).
+        ]
+    ].
+
+
+    "/
+    "/ the filename I would expect from its name ...
+    "/
+    classFileName := Smalltalk fileNameForClass:aClass.
+
+    newInfo := IdentityDictionary new.
+    sourceInfo keysAndValuesDo:[:key :value |
+        newInfo at:key put:value
+    ].
+
+    "/ check ..
+    revInfo notNil ifTrue:[
+        actualSourceFileName := revInfo at:#fileName ifAbsent:nil.
+        actualSourceFileName notNil ifTrue:[
+            actualSourceFileName ~= (classFileName , '.st') ifTrue:[
+                ('SOURCEMGR: source of class ' , aClass name , ' found in ' , actualSourceFileName , ' (expected: ' , classFileName , '.st); renamed ?') printNL.
+                newInfo at:#expectedFileName put:(classFileName).
+                newInfo at:#renamed put:true.
+                classFileName := actualSourceFileName copyWithoutLast:3
+            ]
+        ]
+    ].
+
+    newInfo at:#classFileName put:classFileName.
+    ^ newInfo
+
+    "Created: 25.11.1995 / 12:40:19 / cg"
+    "Modified: 25.11.1995 / 18:51:16 / cg"
+!
+
 streamForClass:cls fileName:classFileName revision:revision directory:packageDir module:moduleDir cache:cacheIt
     self subclassResponsibility.
     ^ nil
 
     "Created: 4.11.1995 / 19:09:12 / cg"
     "Modified: 4.11.1995 / 19:15:43 / cg"
-!
-
-sourceInfoOfClass:aClass
-    "helper: return a classes sourceCodeInfo"
-
-    |cls sourceInfo|
-
-    cls := aClass.
-    cls isMeta ifTrue:[
-	cls := cls soleInstance
-    ].
-
-    sourceInfo := cls sourceCodeInfo.
-    sourceInfo isNil ifTrue:[
-	'SOURCEMGR: cannot extract classes sourceInfo' infoPrintNL.
-	^ nil
-    ].
-    ^ sourceInfo
-
-    "Created: 25.11.1995 / 12:40:19 / cg"
-    "Modified: 25.11.1995 / 12:40:27 / cg"
 ! !
 
 !AbstractSourceCodeManager class methodsFor:'source code access'!
@@ -140,47 +279,48 @@
 
     packageDir := sourceInfo at:#directory.
     moduleDir := sourceInfo at:#module.  "/ use the modules name as CVS module
-    classFileName := Smalltalk fileNameForClass:aClass.
+    classFileName := sourceInfo at:#classFileName.
+"/    classFileName := Smalltalk fileNameForClass:aClass.
 
     tempDir := (Filename newTemporaryIn:nil) makeDirectory.
     [
-	|aStream|
+        |aStream|
 
-	tempFile := tempDir construct:(classFileName,'.st').
-	aStream := tempFile writeStream.
-	aStream isNil ifTrue:[
-	    'SOURCEMGR: temporary fileout failed' infoPrintNL.
-	    ^ false
-	].
+        tempFile := tempDir construct:(classFileName,'.st').
+        aStream := tempFile writeStream.
+        aStream isNil ifTrue:[
+            'SOURCEMGR: temporary fileout failed' infoPrintNL.
+            ^ false
+        ].
 
-	Class fileOutErrorSignal handle:[:ex |
-	    'SOURCEMGR: fileout failed' infoPrintNL.
-	    aStream close.
-	    ^ false
-	] do:[
-	    aClass fileOutOn:aStream withTimeStamp:false.
-	].
-	aStream close.
+        Class fileOutErrorSignal handle:[:ex |
+            'SOURCEMGR: fileout failed' infoPrintNL.
+            aStream close.
+            ^ false
+        ] do:[
+            aClass fileOutOn:aStream withTimeStamp:false.
+        ].
+        aStream close.
 
-	(tempFile := tempDir construct:(classFileName,'.st')) exists ifFalse:[
-	    'SOURCEMGR: temporary fileout failed' infoPrintNL.
-	    ^ false
-	].
+        (tempFile := tempDir construct:(classFileName,'.st')) exists ifFalse:[
+            'SOURCEMGR: temporary fileout failed' infoPrintNL.
+            ^ false
+        ].
 
-	ok := self 
-	    checkinClass:aClass
-	    fileName:classFileName 
-	    directory:packageDir 
-	    module:moduleDir
-	    source:(tempFile name)
-	    logMessage:logMessage.
+        ok := self 
+            checkinClass:aClass
+            fileName:classFileName 
+            directory:packageDir 
+            module:moduleDir
+            source:(tempFile name)
+            logMessage:logMessage.
 
-	ok ifTrue:[
-	    Class addChangeRecordForClassCheckIn:aClass.
-	].
-	^ ok
+        ok ifTrue:[
+            Class addChangeRecordForClassCheckIn:aClass.
+        ].
+        ^ ok
     ] valueNowOrOnUnwindDo:[
-	tempDir recursiveRemove
+        tempDir recursiveRemove
     ].
     ^ false
 
@@ -189,7 +329,7 @@
     "
 
     "Created: 6.11.1995 / 18:56:00 / cg"
-    "Modified: 18.11.1995 / 17:06:05 / cg"
+    "Modified: 25.11.1995 / 17:05:02 / cg"
 !
 
 mostRecentSourceStreamForClassNamed:aClassOrClassName
@@ -226,16 +366,17 @@
      The classes source code is extracted using the revision and the sourceCodeInfo,
      which itself is extracted from the classes packageString."
 
-    |classFileName revision packageDir moduleDir sourceInfo|
+    |classFileName revision 
+     packageDir moduleDir sourceInfo revInfo|
 
     aRevisionStringOrNil isNil ifTrue:[
-	revision := aClass revision.
-	revision isNil ifTrue:[ 
-	    'SOURCEMGR: class ' , aClass name , ' has no revision string' infoPrintNL.
-	    ^ nil.
-	]
+        revision := aClass revision.
+        revision isNil ifTrue:[ 
+            'SOURCEMGR: class ' , aClass name , ' has no revision string' infoPrintNL.
+            ^ nil.
+        ]
     ] ifFalse:[
-	revision := aRevisionStringOrNil
+        revision := aRevisionStringOrNil
     ].
 
     sourceInfo := self sourceInfoOfClass:aClass.
@@ -243,17 +384,18 @@
 
     packageDir := sourceInfo at:#directory.
     moduleDir := sourceInfo at:#module.  "/ use the modules name as CVS module
-    classFileName := Smalltalk fileNameForClass:aClass.
+    classFileName := sourceInfo at:#classFileName.
+
 
     ^ self 
-	streamForClass:aClass
-	fileName:classFileName 
-	revision:revision 
-	directory:packageDir 
-	module:moduleDir
-	cache:true
+        streamForClass:aClass
+        fileName:classFileName 
+        revision:revision 
+        directory:packageDir 
+        module:moduleDir
+        cache:true
 
-    "Modified: 9.11.1995 / 14:34:10 / cg"
+    "Modified: 25.11.1995 / 17:04:38 / cg"
 ! !
 
 !AbstractSourceCodeManager class methodsFor:'source code administration'!
@@ -300,54 +442,72 @@
 
      The returned information is a structure (IdentityDictionary)
      filled with:
-	    #container          -> the RCS container file name 
-	    #filename           -> the actual source file name
-	    #newestRevision     -> the revisionString of the newest revision
-	    #numberOfRevisions  -> the number of revisions in the container
-	    #revisions          -> collection of per-revision info (see below)
+            #container          -> the RCS container file name 
+            #filename           -> the actual source file name
+            #newestRevision     -> the revisionString of the newest revision
+            #numberOfRevisions  -> the number of revisions in the container
+            #revisions          -> collection of per-revision info (see below)
 
-	    rev1 / rev2 specify from which revisions a logEntry is wanted:
-	      If rev1 is nil, the first revision is the initial revision
-	      otherwise, the log starts with that revision.
-	      If rev2 is nil, the last revision is the newest revision
-	      otherwise, the log ends with that revision.
-	      If both are nil, no logEntries are extracted (i.e. only the header).
+         for some classes, additional info is returned:
+
+            #renamed            -> true if the class has been renamed or copied
+                                   and the sourceInfo is from the previous one
+            #expectedFileName   -> the filename we would expect (i.e. for the new class)
 
-	    per revision info consists of one record per revision:
+            rev1 / rev2 specify from which revisions a logEntry is wanted:
+              If rev1 is nil, the first revision is the initial revision
+              otherwise, the log starts with that revision.
+              If rev2 is nil, the last revision is the newest revision
+              otherwise, the log ends with that revision.
+              If both are nil, no logEntries are extracted (i.e. only the header).
+
+            per revision info consists of one record per revision:
 
-	      #revision              -> the revision string
-	      #author                -> who checked that revision into the repository
-	      #date                  -> when was it checked in
-	      #state                 -> the RCS state
-	      #numberOfChangedLines  -> the number of changed line w.r.t the previous
+              #revision              -> the revision string
+              #author                -> who checked that revision into the repository
+              #date                  -> when was it checked in
+              #state                 -> the RCS state
+              #numberOfChangedLines  -> the number of changed line w.r.t the previous
 
-	    revisions are ordered newest first 
-	    (i.e. the last entry is for the initial revision; the first for the most recent one)
-	"
+            revisions are ordered newest first 
+            (i.e. the last entry is for the initial revision; the first for the most recent one)
+        "
 
-    |cls sourceInfo packageDir moduleDir classFileName|
+    |cls sourceInfo packageDir moduleDir classFileName info|
 
     sourceInfo := self sourceInfoOfClass:aClass.
     sourceInfo isNil ifTrue:[^ nil].
 
     packageDir := sourceInfo at:#directory.
     moduleDir := sourceInfo at:#module.  "/ use the modules name as CVS module
-    classFileName := Smalltalk fileNameForClass:aClass.
+"/    classFileName := Smalltalk fileNameForClass:aClass.
+    classFileName := sourceInfo at:#classFileName.
 
-    ^ self 
-	revisionLogOf:aClass
-	fromRevision:rev1 
-	toRevision:rev2
-	fileName:classFileName 
-	directory:packageDir 
-	module:moduleDir
+    info := self 
+        revisionLogOf:aClass
+        fromRevision:rev1 
+        toRevision:rev2
+        fileName:classFileName 
+        directory:packageDir 
+        module:moduleDir.
+
+    info notNil ifTrue:[
+        (sourceInfo includesKey:#renamed) ifTrue:[
+            info at:#renamed put:(sourceInfo at:#renamed)
+        ].
+        (sourceInfo includesKey:#expectedFileName) ifTrue:[
+            info at:#expectedFileName put:(sourceInfo at:#expectedFileName)
+        ]
+    ].
+    ^ info
 
     "
      SourceCodeManager revisionLogOf:Array fromRevision:'1.40' toRevision:'1.43' 
+     SourceCodeManager revisionLogOf:XtBoxNew 
     "
 
     "Created: 6.11.1995 / 18:56:00 / cg"
-    "Modified: 25.11.1995 / 12:43:12 / cg"
+    "Modified: 25.11.1995 / 17:25:29 / cg"
 !
 
 revisionLogOf:cls fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir 
@@ -359,31 +519,48 @@
     "Modified: 25.11.1995 / 11:56:38 / cg"
 !
 
-writeRevisionLogOf:cls fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir to:aStream
-    "send (part of) the revisionlog to aStream"
+writeRevisionLogMessagesFrom:log to:aStream
+    "helper; send the revisionlog to aStream"
 
-    |log |
-
-    log := self revisionLogOf:cls fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir.
-    log isNil ifTrue:[^ false].
+    (log at:#renamed ifAbsent:false) ifTrue:[
+        aStream nextPutAll:'  Class was renamed; revision info is from original class.'.
+        aStream cr; nextPutAll:'  You have to create a new container for it.'.
+        aStream cr; cr.
+    ].
 
     aStream nextPutAll:'  Total revisions: '; nextPutAll:(log at:#numberOfRevisions) printString; cr.
     aStream nextPutAll:'  Newest revision: '; nextPutAll:(log at:#newestRevision) printString; cr.
 
     (log at:#revisions) do:[:entry |
-	aStream cr.
-	aStream nextPutAll:'  revision '; nextPutAll:(entry at:#revision); tab.
-	aStream nextPutAll:' date: '; nextPutAll:(entry at:#date); tab.
-	aStream nextPutAll:' author: '; nextPutAll:(entry at:#author); tab.
-	aStream cr.
+        |logMsg|
+
+        aStream cr.
+        aStream nextPutAll:'  revision '; nextPutAll:(entry at:#revision); tab.
+        aStream nextPutAll:' date: '; nextPutAll:(entry at:#date); tab.
+        aStream nextPutAll:' author: '; nextPutAll:(entry at:#author); tab.
+        aStream cr.
 
-	log := entry at:#logMessage.
-	(log isEmpty or:[log isBlank or:[log withoutSeparators = '.']]) ifTrue:[
-	    log := '*** empty log message ***'
-	].
-	aStream tab; nextPutAll:log.
-	aStream cr.
+        logMsg := entry at:#logMessage.
+        (logMsg isEmpty or:[logMsg isBlank or:[logMsg withoutSeparators = '.']]) ifTrue:[
+            logMsg := '*** empty log message ***'
+        ].
+        aStream tab; nextPutAll:logMsg.
+        aStream cr.
     ].
+
+    "Created: 16.11.1995 / 13:25:30 / cg"
+    "Modified: 25.11.1995 / 17:27:31 / cg"
+!
+
+writeRevisionLogOf:aClass fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir to:aStream
+    "send (part of) the revisionlog to aStream"
+
+    |log |
+
+    log := self revisionLogOf:aClass fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir.
+    log isNil ifTrue:[^ false].
+
+    self writeRevisionLogMessagesFrom:log to:aStream.
     ^ true
 
     "
@@ -394,36 +571,26 @@
     "
 
     "Created: 16.11.1995 / 13:25:30 / cg"
-    "Modified: 25.11.1995 / 12:02:53 / cg"
+    "Modified: 25.11.1995 / 17:25:04 / cg"
 !
 
 writeRevisionLogOf:aClass fromRevision:rev1 toRevision:rev2 to:aStream
     "extract a classes log and append it to aStream."
 
-    |sourceInfo packageDir moduleDir classFileName|
-
-    sourceInfo := self sourceInfoOfClass:aClass.
-    sourceInfo isNil ifTrue:[^ nil].
-
-    packageDir := sourceInfo at:#directory.
-    moduleDir := sourceInfo at:#module.  "/ use the modules name as CVS module
-    classFileName := Smalltalk fileNameForClass:aClass.
+    |log |
 
-    ^ self 
-	writeRevisionLogOf:aClass 
-	fromRevision:rev1 
-	toRevision:rev2
-	fileName:classFileName 
-	directory:packageDir 
-	module:moduleDir
-	to:aStream
+    log := self revisionLogOf:aClass fromRevision:rev1 toRevision:rev2.
+    log isNil ifTrue:[^ false].
+
+    self writeRevisionLogMessagesFrom:log to:aStream.
+    ^ true
 
     "
      SourceCodeManager writeRevisionLogOf:Array fromRevision:'1.40' toRevision:'1.43' to:Transcript 
     "
 
     "Created: 6.11.1995 / 18:56:00 / cg"
-    "Modified: 25.11.1995 / 12:42:59 / cg"
+    "Modified: 25.11.1995 / 17:24:55 / cg"
 !
 
 writeRevisionLogOf:aClass to:aStream
@@ -440,4 +607,4 @@
 !AbstractSourceCodeManager class methodsFor:'documentation'!
 
 version
-^ '$Header: /cvs/stx/stx/libbasic3/Attic/AbstrSCMgr.st,v 1.23 1995-11-25 15:27:25 cg Exp $'! !
+^ '$Header: /cvs/stx/stx/libbasic3/Attic/AbstrSCMgr.st,v 1.24 1995-11-25 18:02:43 cg Exp $'! !
--- a/AbstractSourceCodeManager.st	Sat Nov 25 16:27:29 1995 +0100
+++ b/AbstractSourceCodeManager.st	Sat Nov 25 19:02:43 1995 +0100
@@ -64,6 +64,100 @@
     ^ CacheDirectoryName
 !
 
+directoryFromContainerPath:containerPath
+    |path idx|
+
+    path := self pathInRepositoryFrom:containerPath.
+    path notNil ifTrue:[
+        idx := path indexOf:(Filename separator).
+        idx ~~ 0 ifTrue:[
+            path := path copyFrom:(idx + 1)
+        ].
+        ^ path asFilename directoryName
+    ].
+    ^ nil
+
+    "
+     SourceCodeManager directoryFromContainerPath:'/files/CVS/stx/libbasic/Array.st'
+    "
+
+    "Created: 25.11.1995 / 18:42:20 / cg"
+    "Modified: 25.11.1995 / 18:48:46 / cg"
+!
+
+filenameFromContainerPath:containerPath
+    |top rest|
+
+    containerPath notNil ifTrue:[
+        top := self repositoryTopDirectory.
+        top notNil ifTrue:[
+            (containerPath startsWith:(top , '/')) ifTrue:[
+                rest := containerPath copyFrom:(top size + 2).
+                ^ rest asFilename baseName
+            ]
+        ]
+    ].
+
+    "Created: 25.11.1995 / 18:42:34 / cg"
+!
+
+moduleFromContainerPath:containerPath
+    |path idx|
+
+    path := self pathInRepositoryFrom:containerPath.
+    path notNil ifTrue:[
+        idx := path indexOf:(Filename separator).
+        idx == 0 ifTrue:[^ path].
+        ^ path copyTo:(idx - 1)
+    ].
+    ^ nil
+
+    "
+     SourceCodeManager moduleFromContainerPath:'/files/CVS/stx/libbasic/Array.st'
+    "
+
+    "Created: 25.11.1995 / 18:42:20 / cg"
+    "Modified: 25.11.1995 / 18:47:27 / cg"
+!
+
+pathInRepositoryFrom:containerPath
+    |top rest lastTop idx|
+
+    containerPath notNil ifTrue:[
+        top := self repositoryTopDirectory.
+        top notNil ifTrue:[
+            (containerPath startsWith:(top , '/')) ifTrue:[
+                ^ containerPath copyFrom:(top size + 2).
+            ].
+            "/ hardcase - the repository-filename in the versionInfo
+            "/ does no match my repository top.
+            "/ check for mangled prefix (happens with symbolic links)
+            lastTop := '/' , top asFilename baseName, '/'.
+            idx := containerPath indexOfSubCollection:lastTop.
+            idx ~~ 0 ifTrue:[
+                ('SOURCEMGR: warning: repository path mismatch: ' , (containerPath copyTo:idx-1) , lastTop , ' vs. ' , top , '/') infoPrintNL.
+                'SOURCEMGR: warning: assuming that mismatch is ok.' infoPrintNL.
+                ^ containerPath copyFrom:(idx + lastTop size).
+            ]
+        ]
+    ].
+    ^ rest
+
+    "
+     SourceCodeManager pathInRepositoryFrom:'/files/CVS/stx/libbasic/Array.st'
+     SourceCodeManager pathInRepositoryFrom:'/phys/ibm/CVS/stx/libbasic/Array.st'
+    "
+
+    "Created: 25.11.1995 / 18:42:20 / cg"
+    "Modified: 25.11.1995 / 18:59:26 / cg"
+!
+
+repositoryTopDirectory
+    ^ nil
+
+    "Created: 25.11.1995 / 18:38:59 / cg"
+!
+
 revisionAfter:aRevisionString
     |idx s|
 
@@ -98,33 +192,78 @@
     ^ dir
 !
 
+sourceInfoOfClass:aClass
+    "helper: return a classes sourceCodeInfo"
+
+    |cls sourceInfo revInfo actualSourceFileName classFileName
+     newInfo revisionInfo container|
+
+    cls := aClass.
+    cls isMeta ifTrue:[
+        cls := cls soleInstance
+    ].
+
+    "/
+    "/ the info given by the classes source ...
+    "/
+    revInfo := aClass revisionInfo.
+
+    "/
+    "/ the info given by the classes binary ...
+    "/ if present, we better trust that one.
+    "/
+    sourceInfo := cls packageSourceCodeInfo.
+    sourceInfo isNil ifTrue:[
+        revInfo isNil ifTrue:[
+            'SOURCEMGR: class has neither source nor compiled-in info' infoPrintNL.
+            ^ nil
+        ].
+
+        container := revInfo at:#repositoryPathName ifAbsent:nil.
+        container notNil ifTrue:[
+            sourceInfo := revInfo.
+            sourceInfo at:#directory put:(self directoryFromContainerPath:container).
+            sourceInfo at:#module put:(self moduleFromContainerPath:container).
+        ]
+    ].
+
+
+    "/
+    "/ the filename I would expect from its name ...
+    "/
+    classFileName := Smalltalk fileNameForClass:aClass.
+
+    newInfo := IdentityDictionary new.
+    sourceInfo keysAndValuesDo:[:key :value |
+        newInfo at:key put:value
+    ].
+
+    "/ check ..
+    revInfo notNil ifTrue:[
+        actualSourceFileName := revInfo at:#fileName ifAbsent:nil.
+        actualSourceFileName notNil ifTrue:[
+            actualSourceFileName ~= (classFileName , '.st') ifTrue:[
+                ('SOURCEMGR: source of class ' , aClass name , ' found in ' , actualSourceFileName , ' (expected: ' , classFileName , '.st); renamed ?') printNL.
+                newInfo at:#expectedFileName put:(classFileName).
+                newInfo at:#renamed put:true.
+                classFileName := actualSourceFileName copyWithoutLast:3
+            ]
+        ]
+    ].
+
+    newInfo at:#classFileName put:classFileName.
+    ^ newInfo
+
+    "Created: 25.11.1995 / 12:40:19 / cg"
+    "Modified: 25.11.1995 / 18:51:16 / cg"
+!
+
 streamForClass:cls fileName:classFileName revision:revision directory:packageDir module:moduleDir cache:cacheIt
     self subclassResponsibility.
     ^ nil
 
     "Created: 4.11.1995 / 19:09:12 / cg"
     "Modified: 4.11.1995 / 19:15:43 / cg"
-!
-
-sourceInfoOfClass:aClass
-    "helper: return a classes sourceCodeInfo"
-
-    |cls sourceInfo|
-
-    cls := aClass.
-    cls isMeta ifTrue:[
-	cls := cls soleInstance
-    ].
-
-    sourceInfo := cls sourceCodeInfo.
-    sourceInfo isNil ifTrue:[
-	'SOURCEMGR: cannot extract classes sourceInfo' infoPrintNL.
-	^ nil
-    ].
-    ^ sourceInfo
-
-    "Created: 25.11.1995 / 12:40:19 / cg"
-    "Modified: 25.11.1995 / 12:40:27 / cg"
 ! !
 
 !AbstractSourceCodeManager class methodsFor:'source code access'!
@@ -140,47 +279,48 @@
 
     packageDir := sourceInfo at:#directory.
     moduleDir := sourceInfo at:#module.  "/ use the modules name as CVS module
-    classFileName := Smalltalk fileNameForClass:aClass.
+    classFileName := sourceInfo at:#classFileName.
+"/    classFileName := Smalltalk fileNameForClass:aClass.
 
     tempDir := (Filename newTemporaryIn:nil) makeDirectory.
     [
-	|aStream|
+        |aStream|
 
-	tempFile := tempDir construct:(classFileName,'.st').
-	aStream := tempFile writeStream.
-	aStream isNil ifTrue:[
-	    'SOURCEMGR: temporary fileout failed' infoPrintNL.
-	    ^ false
-	].
+        tempFile := tempDir construct:(classFileName,'.st').
+        aStream := tempFile writeStream.
+        aStream isNil ifTrue:[
+            'SOURCEMGR: temporary fileout failed' infoPrintNL.
+            ^ false
+        ].
 
-	Class fileOutErrorSignal handle:[:ex |
-	    'SOURCEMGR: fileout failed' infoPrintNL.
-	    aStream close.
-	    ^ false
-	] do:[
-	    aClass fileOutOn:aStream withTimeStamp:false.
-	].
-	aStream close.
+        Class fileOutErrorSignal handle:[:ex |
+            'SOURCEMGR: fileout failed' infoPrintNL.
+            aStream close.
+            ^ false
+        ] do:[
+            aClass fileOutOn:aStream withTimeStamp:false.
+        ].
+        aStream close.
 
-	(tempFile := tempDir construct:(classFileName,'.st')) exists ifFalse:[
-	    'SOURCEMGR: temporary fileout failed' infoPrintNL.
-	    ^ false
-	].
+        (tempFile := tempDir construct:(classFileName,'.st')) exists ifFalse:[
+            'SOURCEMGR: temporary fileout failed' infoPrintNL.
+            ^ false
+        ].
 
-	ok := self 
-	    checkinClass:aClass
-	    fileName:classFileName 
-	    directory:packageDir 
-	    module:moduleDir
-	    source:(tempFile name)
-	    logMessage:logMessage.
+        ok := self 
+            checkinClass:aClass
+            fileName:classFileName 
+            directory:packageDir 
+            module:moduleDir
+            source:(tempFile name)
+            logMessage:logMessage.
 
-	ok ifTrue:[
-	    Class addChangeRecordForClassCheckIn:aClass.
-	].
-	^ ok
+        ok ifTrue:[
+            Class addChangeRecordForClassCheckIn:aClass.
+        ].
+        ^ ok
     ] valueNowOrOnUnwindDo:[
-	tempDir recursiveRemove
+        tempDir recursiveRemove
     ].
     ^ false
 
@@ -189,7 +329,7 @@
     "
 
     "Created: 6.11.1995 / 18:56:00 / cg"
-    "Modified: 18.11.1995 / 17:06:05 / cg"
+    "Modified: 25.11.1995 / 17:05:02 / cg"
 !
 
 mostRecentSourceStreamForClassNamed:aClassOrClassName
@@ -226,16 +366,17 @@
      The classes source code is extracted using the revision and the sourceCodeInfo,
      which itself is extracted from the classes packageString."
 
-    |classFileName revision packageDir moduleDir sourceInfo|
+    |classFileName revision 
+     packageDir moduleDir sourceInfo revInfo|
 
     aRevisionStringOrNil isNil ifTrue:[
-	revision := aClass revision.
-	revision isNil ifTrue:[ 
-	    'SOURCEMGR: class ' , aClass name , ' has no revision string' infoPrintNL.
-	    ^ nil.
-	]
+        revision := aClass revision.
+        revision isNil ifTrue:[ 
+            'SOURCEMGR: class ' , aClass name , ' has no revision string' infoPrintNL.
+            ^ nil.
+        ]
     ] ifFalse:[
-	revision := aRevisionStringOrNil
+        revision := aRevisionStringOrNil
     ].
 
     sourceInfo := self sourceInfoOfClass:aClass.
@@ -243,17 +384,18 @@
 
     packageDir := sourceInfo at:#directory.
     moduleDir := sourceInfo at:#module.  "/ use the modules name as CVS module
-    classFileName := Smalltalk fileNameForClass:aClass.
+    classFileName := sourceInfo at:#classFileName.
+
 
     ^ self 
-	streamForClass:aClass
-	fileName:classFileName 
-	revision:revision 
-	directory:packageDir 
-	module:moduleDir
-	cache:true
+        streamForClass:aClass
+        fileName:classFileName 
+        revision:revision 
+        directory:packageDir 
+        module:moduleDir
+        cache:true
 
-    "Modified: 9.11.1995 / 14:34:10 / cg"
+    "Modified: 25.11.1995 / 17:04:38 / cg"
 ! !
 
 !AbstractSourceCodeManager class methodsFor:'source code administration'!
@@ -300,54 +442,72 @@
 
      The returned information is a structure (IdentityDictionary)
      filled with:
-	    #container          -> the RCS container file name 
-	    #filename           -> the actual source file name
-	    #newestRevision     -> the revisionString of the newest revision
-	    #numberOfRevisions  -> the number of revisions in the container
-	    #revisions          -> collection of per-revision info (see below)
+            #container          -> the RCS container file name 
+            #filename           -> the actual source file name
+            #newestRevision     -> the revisionString of the newest revision
+            #numberOfRevisions  -> the number of revisions in the container
+            #revisions          -> collection of per-revision info (see below)
 
-	    rev1 / rev2 specify from which revisions a logEntry is wanted:
-	      If rev1 is nil, the first revision is the initial revision
-	      otherwise, the log starts with that revision.
-	      If rev2 is nil, the last revision is the newest revision
-	      otherwise, the log ends with that revision.
-	      If both are nil, no logEntries are extracted (i.e. only the header).
+         for some classes, additional info is returned:
+
+            #renamed            -> true if the class has been renamed or copied
+                                   and the sourceInfo is from the previous one
+            #expectedFileName   -> the filename we would expect (i.e. for the new class)
 
-	    per revision info consists of one record per revision:
+            rev1 / rev2 specify from which revisions a logEntry is wanted:
+              If rev1 is nil, the first revision is the initial revision
+              otherwise, the log starts with that revision.
+              If rev2 is nil, the last revision is the newest revision
+              otherwise, the log ends with that revision.
+              If both are nil, no logEntries are extracted (i.e. only the header).
+
+            per revision info consists of one record per revision:
 
-	      #revision              -> the revision string
-	      #author                -> who checked that revision into the repository
-	      #date                  -> when was it checked in
-	      #state                 -> the RCS state
-	      #numberOfChangedLines  -> the number of changed line w.r.t the previous
+              #revision              -> the revision string
+              #author                -> who checked that revision into the repository
+              #date                  -> when was it checked in
+              #state                 -> the RCS state
+              #numberOfChangedLines  -> the number of changed line w.r.t the previous
 
-	    revisions are ordered newest first 
-	    (i.e. the last entry is for the initial revision; the first for the most recent one)
-	"
+            revisions are ordered newest first 
+            (i.e. the last entry is for the initial revision; the first for the most recent one)
+        "
 
-    |cls sourceInfo packageDir moduleDir classFileName|
+    |cls sourceInfo packageDir moduleDir classFileName info|
 
     sourceInfo := self sourceInfoOfClass:aClass.
     sourceInfo isNil ifTrue:[^ nil].
 
     packageDir := sourceInfo at:#directory.
     moduleDir := sourceInfo at:#module.  "/ use the modules name as CVS module
-    classFileName := Smalltalk fileNameForClass:aClass.
+"/    classFileName := Smalltalk fileNameForClass:aClass.
+    classFileName := sourceInfo at:#classFileName.
 
-    ^ self 
-	revisionLogOf:aClass
-	fromRevision:rev1 
-	toRevision:rev2
-	fileName:classFileName 
-	directory:packageDir 
-	module:moduleDir
+    info := self 
+        revisionLogOf:aClass
+        fromRevision:rev1 
+        toRevision:rev2
+        fileName:classFileName 
+        directory:packageDir 
+        module:moduleDir.
+
+    info notNil ifTrue:[
+        (sourceInfo includesKey:#renamed) ifTrue:[
+            info at:#renamed put:(sourceInfo at:#renamed)
+        ].
+        (sourceInfo includesKey:#expectedFileName) ifTrue:[
+            info at:#expectedFileName put:(sourceInfo at:#expectedFileName)
+        ]
+    ].
+    ^ info
 
     "
      SourceCodeManager revisionLogOf:Array fromRevision:'1.40' toRevision:'1.43' 
+     SourceCodeManager revisionLogOf:XtBoxNew 
     "
 
     "Created: 6.11.1995 / 18:56:00 / cg"
-    "Modified: 25.11.1995 / 12:43:12 / cg"
+    "Modified: 25.11.1995 / 17:25:29 / cg"
 !
 
 revisionLogOf:cls fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir 
@@ -359,31 +519,48 @@
     "Modified: 25.11.1995 / 11:56:38 / cg"
 !
 
-writeRevisionLogOf:cls fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir to:aStream
-    "send (part of) the revisionlog to aStream"
+writeRevisionLogMessagesFrom:log to:aStream
+    "helper; send the revisionlog to aStream"
 
-    |log |
-
-    log := self revisionLogOf:cls fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir.
-    log isNil ifTrue:[^ false].
+    (log at:#renamed ifAbsent:false) ifTrue:[
+        aStream nextPutAll:'  Class was renamed; revision info is from original class.'.
+        aStream cr; nextPutAll:'  You have to create a new container for it.'.
+        aStream cr; cr.
+    ].
 
     aStream nextPutAll:'  Total revisions: '; nextPutAll:(log at:#numberOfRevisions) printString; cr.
     aStream nextPutAll:'  Newest revision: '; nextPutAll:(log at:#newestRevision) printString; cr.
 
     (log at:#revisions) do:[:entry |
-	aStream cr.
-	aStream nextPutAll:'  revision '; nextPutAll:(entry at:#revision); tab.
-	aStream nextPutAll:' date: '; nextPutAll:(entry at:#date); tab.
-	aStream nextPutAll:' author: '; nextPutAll:(entry at:#author); tab.
-	aStream cr.
+        |logMsg|
+
+        aStream cr.
+        aStream nextPutAll:'  revision '; nextPutAll:(entry at:#revision); tab.
+        aStream nextPutAll:' date: '; nextPutAll:(entry at:#date); tab.
+        aStream nextPutAll:' author: '; nextPutAll:(entry at:#author); tab.
+        aStream cr.
 
-	log := entry at:#logMessage.
-	(log isEmpty or:[log isBlank or:[log withoutSeparators = '.']]) ifTrue:[
-	    log := '*** empty log message ***'
-	].
-	aStream tab; nextPutAll:log.
-	aStream cr.
+        logMsg := entry at:#logMessage.
+        (logMsg isEmpty or:[logMsg isBlank or:[logMsg withoutSeparators = '.']]) ifTrue:[
+            logMsg := '*** empty log message ***'
+        ].
+        aStream tab; nextPutAll:logMsg.
+        aStream cr.
     ].
+
+    "Created: 16.11.1995 / 13:25:30 / cg"
+    "Modified: 25.11.1995 / 17:27:31 / cg"
+!
+
+writeRevisionLogOf:aClass fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir to:aStream
+    "send (part of) the revisionlog to aStream"
+
+    |log |
+
+    log := self revisionLogOf:aClass fromRevision:rev1 toRevision:rev2 fileName:classFileName directory:packageDir module:moduleDir.
+    log isNil ifTrue:[^ false].
+
+    self writeRevisionLogMessagesFrom:log to:aStream.
     ^ true
 
     "
@@ -394,36 +571,26 @@
     "
 
     "Created: 16.11.1995 / 13:25:30 / cg"
-    "Modified: 25.11.1995 / 12:02:53 / cg"
+    "Modified: 25.11.1995 / 17:25:04 / cg"
 !
 
 writeRevisionLogOf:aClass fromRevision:rev1 toRevision:rev2 to:aStream
     "extract a classes log and append it to aStream."
 
-    |sourceInfo packageDir moduleDir classFileName|
-
-    sourceInfo := self sourceInfoOfClass:aClass.
-    sourceInfo isNil ifTrue:[^ nil].
-
-    packageDir := sourceInfo at:#directory.
-    moduleDir := sourceInfo at:#module.  "/ use the modules name as CVS module
-    classFileName := Smalltalk fileNameForClass:aClass.
+    |log |
 
-    ^ self 
-	writeRevisionLogOf:aClass 
-	fromRevision:rev1 
-	toRevision:rev2
-	fileName:classFileName 
-	directory:packageDir 
-	module:moduleDir
-	to:aStream
+    log := self revisionLogOf:aClass fromRevision:rev1 toRevision:rev2.
+    log isNil ifTrue:[^ false].
+
+    self writeRevisionLogMessagesFrom:log to:aStream.
+    ^ true
 
     "
      SourceCodeManager writeRevisionLogOf:Array fromRevision:'1.40' toRevision:'1.43' to:Transcript 
     "
 
     "Created: 6.11.1995 / 18:56:00 / cg"
-    "Modified: 25.11.1995 / 12:42:59 / cg"
+    "Modified: 25.11.1995 / 17:24:55 / cg"
 !
 
 writeRevisionLogOf:aClass to:aStream
@@ -440,4 +607,4 @@
 !AbstractSourceCodeManager class methodsFor:'documentation'!
 
 version
-^ '$Header: /cvs/stx/stx/libbasic3/AbstractSourceCodeManager.st,v 1.23 1995-11-25 15:27:25 cg Exp $'! !
+^ '$Header: /cvs/stx/stx/libbasic3/AbstractSourceCodeManager.st,v 1.24 1995-11-25 18:02:43 cg Exp $'! !