CVSSourceCodeManager.st
changeset 4157 3eb587af122a
parent 4144 f06214e8e084
child 4164 640b3d01efb9
child 4166 66a7a47f9253
--- a/CVSSourceCodeManager.st	Fri Nov 18 16:17:58 2016 +0100
+++ b/CVSSourceCodeManager.st	Fri Nov 18 18:03:48 2016 +0100
@@ -24,7 +24,7 @@
 !
 
 VersionInfo subclass:#CVSVersionInfo
-	instanceVariableNames:'repositoryPathName timeZone'
+	instanceVariableNames:'repositoryPathName timeZone changedLinesInfo'
 	classVariableNames:''
 	poolDictionaries:''
 	privateIn:CVSSourceCodeManager
@@ -1322,7 +1322,7 @@
     "read and parse a single revision info-entry from the cvs log output.
      Return nil on end.
 
-     The returned information is a structure (IdentityDictionary)
+     The returned information is a CVSVersionInfo object (used to be an IdentityDictionary)
      filled with:
               #revision              -> the revision string
               #author                -> who checked that revision into the repository
@@ -1346,7 +1346,7 @@
     ].
     revLine2 := inStream nextLine.
     (revLine1 notNil and:[revLine2 notNil]) ifTrue:[
-        record := IdentityDictionary new.
+        record := CVSVersionInfo "IdentityDictionary" new.
         record at:#revision put:(revLine1 asCollectionOfWords at:2).
         "/ decompose date/author/state etc.
         (revLine2 asCollectionOfSubstringsSeparatedBy:$;) do:[:info |
@@ -1365,8 +1365,8 @@
             ].
         ].
 
-        "first revision does not hav a 'lines:' entry"
-        (record includesKey:#numberOfChangedLines) ifFalse:[
+        "first revision does not have a 'lines:' entry"
+        (record at:#numberOfChangedLines ifAbsent:[nil]) isNil ifTrue:[
             record at:#numberOfChangedLines put:''
         ].
 
@@ -3139,104 +3139,6 @@
 
 !CVSSourceCodeManager class methodsFor:'source code administration'!
 
-annotationsFor:clsOrNil fileName:classFileName directory:packageDir module:moduleDir
-    "return info about who changed what and when.
-     Return nil on failure.
-
-     The returned information is a structure entry for each line
-            #revision           -> version of last change
-            #author             -> author 
-            #date               -> change date 
-        "
-
-    |tempDir fullName modulePath inStream inHeaderInfo line info msg|
-
-    tempDir := self createTempDirectory:nil forModule:nil.
-    tempDir isNil ifTrue:[
-        ('CVSSourceCodeManager [error]: no tempDir - cannot extract log') errorPrintCR.
-        ^ nil.
-    ].
-
-    [
-        |cmd revArg|
-
-        modulePath :=  moduleDir , '/' , packageDir. 
-        fullName :=  modulePath , '/' , classFileName.
-
-        self createEntryFor:fullName 
-             module:moduleDir
-             in:(tempDir construct:modulePath) 
-             revision:'1.1' 
-             date:'dummy' 
-             special:''
-             overwrite:false.
-
-        msg := 'Fetching annotation log '.
-        clsOrNil isNil ifTrue:[
-            msg := msg , 'in ' , fullName.
-        ] ifFalse:[
-            msg := msg , 'of ', clsOrNil name.
-        ].
-        self activityNotification:msg,'...'.
-
-        inStream := self 
-                        executeCVSCommand:('annotate ' , fullName) 
-                        module:moduleDir 
-                        inDirectory:tempDir 
-                        log:true 
-                        pipe:true.
-
-        inStream isNil ifTrue:[
-            ('CVSSourceCodeManager [error]: cannot open pipe to cvs annotate ', fullName) errorPrintCR.
-            ^ nil
-        ].
-
-        "/
-        "/ read the commands pipe output and extract the info
-        "/
-        info := IdentityDictionary new.
-        inHeaderInfo := true.
-        [inHeaderInfo and:[inStream atEnd not]] whileTrue:[
-            line:= inStream nextLine.
-            ((line ? '') startsWith:'*******') ifTrue:[
-                inHeaderInfo := false.
-            ]
-        ].
-
-        "/
-        "/ continue to read the commands pipe output 
-        "/ and extract change info records
-        "/
-        [inStream atEnd] whileFalse:[
-            line := inStream nextLine.
-Transcript showCR:line.
-        ].
-    ] ensure:[
-        inStream notNil ifTrue:[inStream close].
-
-        tempDir notNil ifTrue:[
-            OperatingSystem accessDeniedErrorSignal handle:[:ex |
-                ('CVSSourceCodeManager [warning]: could not remove tempDir ', tempDir pathName) infoPrintCR.
-            ] do:[
-                tempDir recursiveRemove
-            ].
-        ].
-        self activityNotification:nil.
-    ].
-    ^ info
-
-    "
-     SourceCodeManager 
-        annotationsFor:Array 
-        fileName:'Array.st' directory:'libbasic' module:'stx'
-    "
-    "
-     SourceCodeManager 
-        annotationsFor:MenuPanel 
-        fileName:'MenuPanel.st' directory:'libwidg2' module:'stx'
-    "
-!
-
 checkForExistingContainer:fileName inModule:moduleDir directory:packageDir
     "check for a container to exist"
 
@@ -4004,108 +3906,6 @@
     "
 !
 
-diffListFor:clsOrNil fileName:classFileName directory:packageDir module:moduleDir revision1:rev1 revision2:rev2
-    "return diff info. This is supposed to return a standard diff-like
-     list of lines, representing the diffs between two revisions.
-     experimental (for ownershipGraph)"
-
-    ^  self
-        diffListFor:clsOrNil fileName:classFileName directory:packageDir module:moduleDir revision1:rev1 revision2:rev2 
-        cache:true
-!
-
-diffListFor:clsOrNil fileName:classFileNameArg directory:packageDir module:moduleDir revision1:rev1 revision2:rev2 cache:cacheIt
-    "return diff info. This is supposed to return a standard diff-like
-     list of lines, representing the diffs between two revisions.
-     experimental (for ownershipGraph)"
-
-    |tempDir fullName modulePath inStream list msg cacheDir cachedFile classFileName|
-
-    clsOrNil notNil ifTrue:[
-        modulePath :=  clsOrNil package copyReplaceAll:$: with:$/.
-        fullName :=  modulePath , '/' , (classFileName := clsOrNil getClassFilename).
-    ] ifFalse:[
-        modulePath :=  moduleDir , '/' , packageDir. 
-        fullName :=  modulePath , '/' , (classFileName := classFileNameArg).
-    ].
-
-   (cacheIt) ifTrue:[
-        (cacheDir := self sourceCacheDirectory) isNil ifTrue:[
-            ('CVSSourceCodeManager [warning]: no source cache directory') infoPrintCR.
-        ] ifFalse:[
-            (cacheDir / modulePath / '.diffs') exists ifFalse:[
-                (cacheDir / modulePath / '.diffs') makeDirectory.
-            ].
-            cachedFile := cacheDir / modulePath / '.diffs' / (classFileName,'_',rev1,'_',rev2).
-            cachedFile exists ifTrue:[
-                ^ cachedFile contents
-            ].
-        ].
-    ].
-
-    tempDir := self createTempDirectory:nil forModule:nil.
-    tempDir isNil ifTrue:[
-        ('CVSSourceCodeManager [error]: no tempDir - cannot extract status') errorPrintCR.
-        ^ nil.
-    ].
-
-    [
-        self createEntryFor:fullName 
-             module:moduleDir
-             in:(tempDir construct:modulePath) 
-             revision:'1.1' 
-             date:'dummy' 
-             special:''
-             overwrite:false.
-
-        msg := 'CVS: Fetching diff list of '.
-        clsOrNil isNil ifTrue:[
-            msg := msg , fullName.
-        ] ifFalse:[
-            msg := msg , clsOrNil name.
-        ].
-        msg := msg , ' ' , rev1 , ' vs. ' , rev2.
-        self activityNotification:msg.
-
-        inStream := self 
-                        executeCVSCommand:('diff -w -r%1 -r%2 %3' bindWith:rev1 with:rev2 with:fullName) 
-                        module:moduleDir 
-                        inDirectory:tempDir 
-                        log:true 
-                        pipe:true.
-
-        inStream isNil ifTrue:[
-            ('CVSSourceCodeManager [error]: cannot open pipe to cvs diff ', fullName) errorPrintCR.
-            ^ nil
-        ].
-
-        "/
-        "/ read the commands pipe output and extract the container info
-        "/
-        [ inStream nextLine startsWith:'diff -'] whileFalse.
-
-        list := inStream contents.
-    ] ensure:[
-        inStream notNil ifTrue:[inStream close].
-        tempDir recursiveRemove
-    ].
-    list := list reject:[:line | line startsWith:'\ '].
-
-    cachedFile notNil ifTrue:[
-        cachedFile contents:list.
-    ].
-    ^ list
-
-    "
-     SourceCodeManager statusOf:Array 
-     SourceCodeManager statusOf:Array fileName:'Array.st' directory:'libbasic' module:'stx'  
-     SourceCodeManager statusOf:Filename fileName:'Filename.st' directory:'libbasic' module:'stx'  
-     SourceCodeManager statusOf:NewSystemBrowser fileName:'NewSystemBrowser.st' directory:'libtool' module:'stx'  
-    "
-
-    "Modified: / 29-08-2006 / 13:18:00 / cg"
-!
-
 getExistingContainersInModule:aModule directory:aPackage
     "return a list of existing containers."
 
@@ -4144,27 +3944,6 @@
     "
 !
 
-initialRevisionStringFor:aClass inModule:moduleDir directory:packageDir container:fileName
-    "return a string usable as initial revision string"
-
-    |cvsRoot fullName|
-
-    cvsRoot := self getCVSROOTForModule:moduleDir.
-    cvsRoot := self repositoryTopDirectoryFromCVSRoot:cvsRoot.
-    packageDir isEmptyOrNil ifTrue:[
-        fullName := (cvsRoot , '/' , moduleDir)
-    ] ifFalse:[
-        fullName := (cvsRoot , '/' , moduleDir , '/' , packageDir)
-    ].        
-    ^ self
-        initialRCSRevisionStringFor:aClass 
-        in:fullName
-        container:fileName
-
-    "Modified: / 16-01-1998 / 17:34:13 / stefan"
-    "Created: / 23-08-2006 / 14:05:46 / cg"
-!
-
 listDirectories:cvsPath
     "return a list of all directories in cvsPath.
      cvsPath is the path relative to the cvs root"
@@ -4819,7 +4598,7 @@
 
      The returned information is a structure (IdentityDictionary)
      filled with:
-            #container          -> the RCS/CVS container file name 
+            #container          -> the CVS container file name 
             #cvsRoot            -> the CVS root (repository) 
             #filename           -> the actual source file name
             #newestRevision     -> the revisionString of the newest revision
@@ -4841,7 +4620,7 @@
               #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
+              #numberOfChangedLines  -> the number of changed lines w.r.t the previous (as string with +n -n)
               #logMessage            -> the checkIn log message
 
             revisions are ordered newest first 
@@ -5047,7 +4826,7 @@
     "
      The returned information is a list of structures (IdentityDictionary)
      each filled with:
-            #container          -> the RCS/CVS container file name 
+            #container          -> the CVS container file name 
             #cvsRoot            -> the CVS root (repository) 
             #filename           -> the actual source file name
             #newestRevision     -> the revisionString of the newest revision
@@ -5069,7 +4848,7 @@
               #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
+              #numberOfChangedLines  -> the number of changed lines w.r.t the previous (as string with +n -n)
               #logMessage            -> the checkIn log message
 
             revisions are ordered newest first 
@@ -5719,6 +5498,255 @@
     "Modified: / 29-08-2006 / 13:18:00 / cg"
 ! !
 
+!CVSSourceCodeManager class methodsFor:'source code utilities'!
+
+annotationsFor:clsOrNil fileName:classFileName directory:packageDir module:moduleDir
+    "return info about who changed what and when.
+     Return nil on failure.
+
+     The returned information is a structure entry for each line
+            #revision           -> version of last change
+            #author             -> author 
+            #date               -> change date 
+        "
+
+    |tempDir fullName modulePath inStream inHeaderInfo line info msg|
+
+    tempDir := self createTempDirectory:nil forModule:nil.
+    tempDir isNil ifTrue:[
+        ('CVSSourceCodeManager [error]: no tempDir - cannot extract log') errorPrintCR.
+        ^ nil.
+    ].
+
+    [
+        |cmd revArg|
+
+        modulePath :=  moduleDir , '/' , packageDir. 
+        fullName :=  modulePath , '/' , classFileName.
+
+        self createEntryFor:fullName 
+             module:moduleDir
+             in:(tempDir construct:modulePath) 
+             revision:'1.1' 
+             date:'dummy' 
+             special:''
+             overwrite:false.
+
+        msg := 'Fetching annotation log '.
+        clsOrNil isNil ifTrue:[
+            msg := msg , 'in ' , fullName.
+        ] ifFalse:[
+            msg := msg , 'of ', clsOrNil name.
+        ].
+        self activityNotification:msg,'...'.
+
+        inStream := self 
+                        executeCVSCommand:('annotate ' , fullName) 
+                        module:moduleDir 
+                        inDirectory:tempDir 
+                        log:true 
+                        pipe:true.
+
+        inStream isNil ifTrue:[
+            ('CVSSourceCodeManager [error]: cannot open pipe to cvs annotate ', fullName) errorPrintCR.
+            ^ nil
+        ].
+
+        "/
+        "/ read the commands pipe output and extract the info
+        "/
+        info := IdentityDictionary new.
+        inHeaderInfo := true.
+        [inHeaderInfo and:[inStream atEnd not]] whileTrue:[
+            line:= inStream nextLine.
+            ((line ? '') startsWith:'*******') ifTrue:[
+                inHeaderInfo := false.
+            ]
+        ].
+
+        "/
+        "/ continue to read the commands pipe output 
+        "/ and extract change info records
+        "/
+        [inStream atEnd] whileFalse:[
+            line := inStream nextLine.
+Transcript showCR:line.
+        ].
+    ] ensure:[
+        inStream notNil ifTrue:[inStream close].
+
+        tempDir notNil ifTrue:[
+            OperatingSystem accessDeniedErrorSignal handle:[:ex |
+                ('CVSSourceCodeManager [warning]: could not remove tempDir ', tempDir pathName) infoPrintCR.
+            ] do:[
+                tempDir recursiveRemove
+            ].
+        ].
+        self activityNotification:nil.
+    ].
+    ^ info
+
+    "
+     SourceCodeManager 
+        annotationsFor:Array 
+        fileName:'Array.st' directory:'libbasic' module:'stx'
+    "
+    "
+     SourceCodeManager 
+        annotationsFor:MenuPanel 
+        fileName:'MenuPanel.st' directory:'libwidg2' module:'stx'
+    "
+!
+
+diffListFor:clsOrNil fileName:classFileNameArg directory:packageDir module:moduleDir revision1:rev1 revision2:rev2 cache:cacheIt
+    "return diff info. This is supposed to return a standard diff-like
+     list of lines, representing the diffs between two revisions.
+     experimental (for ownershipGraph).
+     Here we ask cvs to give us the diff list"
+
+    |tempDir fullName modulePath inStream list msg cacheDir cachedFile classFileName diffDir|
+
+    clsOrNil notNil ifTrue:[
+        modulePath :=  clsOrNil package copyReplaceAll:$: with:$/.
+        fullName :=  modulePath , '/' , (classFileName := clsOrNil getClassFilename).
+    ] ifFalse:[
+        modulePath :=  moduleDir , '/' , packageDir. 
+        fullName :=  modulePath , '/' , (classFileName := classFileNameArg).
+    ].
+
+   (cacheIt) ifTrue:[
+        (cacheDir := self sourceCacheDirectory) isNil ifTrue:[
+            ('CVSSourceCodeManager [warning]: no source cache directory') infoPrintCR.
+        ] ifFalse:[
+            diffDir := (cacheDir / modulePath / '.diffs').
+            diffDir exists ifFalse:[
+                diffDir makeDirectory.
+            ].
+            cachedFile := diffDir / (classFileName,'_',rev1,'_',rev2).
+            cachedFile exists ifTrue:[
+                ^ cachedFile contents
+            ].
+        ].
+    ].
+
+    tempDir := self createTempDirectory:nil forModule:nil.
+    tempDir isNil ifTrue:[
+        ('CVSSourceCodeManager [error]: no tempDir - cannot extract status') errorPrintCR.
+        ^ nil.
+    ].
+
+    [
+        self createEntryFor:fullName 
+             module:moduleDir
+             in:(tempDir construct:modulePath) 
+             revision:'1.1' 
+             date:'dummy' 
+             special:''
+             overwrite:false.
+
+        msg := 'CVS: Fetching diff list of '.
+        clsOrNil isNil ifTrue:[
+            msg := msg , fullName.
+        ] ifFalse:[
+            msg := msg , clsOrNil name.
+        ].
+        msg := msg , ' ' , rev1 , ' vs. ' , rev2.
+        self activityNotification:msg.
+
+        inStream := self 
+                        executeCVSCommand:('diff -w -r%1 -r%2 %3' bindWith:rev1 with:rev2 with:fullName) 
+                        module:moduleDir 
+                        inDirectory:tempDir 
+                        log:true 
+                        pipe:true.
+
+        inStream isNil ifTrue:[
+            ('CVSSourceCodeManager [error]: cannot open pipe to cvs diff ', fullName) errorPrintCR.
+            ^ nil
+        ].
+
+        "/
+        "/ read the command's pipe output, skipping some administrative info
+        "/
+        [ inStream nextLine startsWith:'diff -'] whileFalse.
+
+        list := inStream contents.
+    ] ensure:[
+        inStream notNil ifTrue:[inStream close].
+        tempDir recursiveRemove
+    ].
+    list := list reject:[:line | line startsWith:'\ '].
+
+    cachedFile notNil ifTrue:[
+        cachedFile contents:list.
+    ].
+    ^ list
+
+    "
+     SourceCodeManager statusOf:Array 
+     SourceCodeManager statusOf:Array fileName:'Array.st' directory:'libbasic' module:'stx'  
+     SourceCodeManager statusOf:Filename fileName:'Filename.st' directory:'libbasic' module:'stx'  
+     SourceCodeManager statusOf:NewSystemBrowser fileName:'NewSystemBrowser.st' directory:'libtool' module:'stx'  
+    "
+
+    "Modified: / 29-08-2006 / 13:18:00 / cg"
+!
+
+initialRCSRevisionStringFor:aClass in:dir container:fileName
+    "return a string usable as initial revision string"
+
+    "/ do not make the string below into one string;
+    "/ RCS would expand it into a wrong rev-string
+
+    |nm oldRev idx special|
+
+    nm := fileName.
+    (nm endsWith:',v') ifTrue:[
+        nm := nm copyButLast:2
+    ].
+    (nm endsWith:'.st') ifFalse:[
+        nm := nm , '.st'
+    ].
+
+    oldRev := aClass revisionString.
+    special := ''.
+
+    oldRev notNil ifTrue:[
+        idx := oldRev lastIndexOf:$[.
+        idx ~~ 0 ifTrue:[
+            idx := oldRev indexOf:$[ startingAt:idx+1.
+            idx ~~ 0 ifTrue:[
+                special := ' ' , (oldRev copyFrom:idx).
+            ]
+        ]
+    ].
+
+
+    ^ '$' , 'Header: ' , dir , '/' , fileName , ',v $'
+      , special
+
+    "Modified: 17.9.1996 / 15:57:15 / cg"
+    "Created: 14.2.1997 / 20:59:28 / cg"
+!
+
+initialRevisionStringFor:aClass inModule:moduleDir directory:packageDir container:fileName
+    "return a string usable as initial revision string"
+
+    |cvsRoot fullName|
+
+    cvsRoot := self getCVSROOTForModule:moduleDir.
+    cvsRoot := self repositoryTopDirectoryFromCVSRoot:cvsRoot.
+    packageDir isEmptyOrNil ifTrue:[
+        fullName := (cvsRoot , '/' , moduleDir)
+    ] ifFalse:[
+        fullName := (cvsRoot , '/' , moduleDir , '/' , packageDir)
+    ].        
+    ^ self initialRCSRevisionStringFor:aClass in:fullName container:fileName
+
+    "Modified: / 16-01-1998 / 17:34:13 / stefan"
+    "Created: / 23-08-2006 / 14:05:46 / cg"
+! !
+
 !CVSSourceCodeManager class methodsFor:'testing'!
 
 isCVS
@@ -5864,6 +5892,14 @@
 
 !CVSSourceCodeManager::CVSVersionInfo methodsFor:'accessing'!
 
+changedLinesInfo
+    ^ changedLinesInfo
+!
+
+changedLinesInfo:aString
+    changedLinesInfo := aString.
+!
+
 repositoryPathName
     ^ repositoryPathName
 !