CVSSourceCodeManager.st
changeset 1989 d4e5428a3b58
parent 1963 98901fb28bea
child 1990 69b3fcc2f7f6
--- a/CVSSourceCodeManager.st	Mon Feb 04 13:22:47 2008 +0100
+++ b/CVSSourceCodeManager.st	Mon Feb 04 18:08:53 2008 +0100
@@ -4033,6 +4033,7 @@
 
             revisions are ordered newest first 
             (i.e. the last entry is for the initial revision; the first for the most recent one)
+            Attention: if state = 'dead' that revision is no longer valid.
         "
 
     |tempDir fullName modulePath inStream inHeaderInfo atEnd line idx
@@ -4219,6 +4220,200 @@
         module:moduleDir
 !
 
+revisionLogOfPackageInDirectory:packageDir module:moduleDir
+    "
+     The returned information is a list of structures (IdentityDictionary)
+     each filled with:
+            #container          -> the RCS/CVS container file name 
+            #cvsRoot            -> the CVS root (repository) 
+            #filename           -> the actual source file name
+            #newestRevision     -> the revisionString of the newest revision
+            #numberOfRevisions  -> the number of revisions in the container (nil for all)
+            #revisions          -> collection of per-revision info (see below)
+
+            firstRev / lastRef specify from which revisions a logEntry is wanted:
+             -If firstRev is nil, the first revision is the initial revision
+              otherwise, the log starts with that revision.
+             -If lastRef is nil, the last revision is the newest revision
+              otherwise, the log ends with that revision.
+
+             -If both are nil, all logEntries are extracted.
+             -If both are 0 (not 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
+              #logMessage            -> the checkIn log message
+
+            revisions are ordered newest first 
+            (i.e. the last entry is for the initial revision; the first for the most recent one)
+            Attention: if state = 'dead' that revision is no longer valid.
+        "
+
+    |tempDir modulePath inStream inHeaderInfo atEnd line idx
+     info record revisionRecords s headerOnly msg infoCollection
+     fn container|
+
+    self use_rlog ifFalse:[
+        tempDir := self createTempDirectory:nil forModule:nil.
+    ].
+
+    [
+        |cmd revArg|
+
+        modulePath :=  moduleDir , '/' , packageDir. 
+
+        self use_rlog ifFalse:[
+self halt.
+^ self.
+"/            self createEntryFor:fullName 
+"/                 module:moduleDir
+"/                 in:(tempDir construct:modulePath) 
+"/                 revision:'1.1' 
+"/                 date:'dummy' 
+"/                 special:''
+"/                 overwrite:false.
+        ].
+
+        revArg := ''.
+        headerOnly := false.
+
+        headerOnly ifTrue:[
+            msg := 'fetching revision info '
+        ] ifFalse:[
+            msg := 'reading revision log '
+        ].
+        msg := msg , 'in package ' , modulePath.
+        self activityNotification:msg,'...'.
+
+        self use_rlog ifTrue:[
+            cmd := ('rlog ' , revArg , ' ' , modulePath).
+        ] ifFalse:[
+            cmd := ('log ' , revArg , ' ' , modulePath).
+        ].
+
+        inStream := self 
+                        executeCVSCommand:cmd 
+                        module:moduleDir 
+                        inDirectory:tempDir 
+                        log:true 
+                        pipe:true.
+
+        inStream isNil ifTrue:[
+            ('CVSSourceCodeManager [error]: cannot open pipe to cvs log ', modulePath) errorPrintCR.
+            ^ nil
+        ].
+
+        infoCollection := Dictionary new.
+        [inStream atEnd not] whileTrue:[
+            "/
+            "/ read the commands pipe output and extract the container info
+            "/
+            info := IdentityDictionary new.
+            inHeaderInfo := true.
+            [inHeaderInfo and:[inStream atEnd not]] whileTrue:[
+                line:= inStream nextLine.
+                line notEmptyOrNil ifTrue:[
+                    |gotIt|
+
+                    gotIt := false.
+                    #('RCS file:'        #container
+                      'Working file:'    #filename
+                      'head:'            #newestRevision
+                      'total revisions:' #numberOfRevisions
+                     ) pairWiseDo:[:word :key |
+                        gotIt ifFalse:[
+                            s := line restAfter:word withoutSeparators:true.
+                            s notNil ifTrue:[info at:key put:s. gotIt := true].                        
+                        ]
+                    ].
+                    gotIt ifFalse:[
+                        (line startsWith:'symbolic names:') ifTrue:[
+                            |tags tokens|
+
+                            tags := Dictionary new.
+                            line:= inStream nextLine.
+                            [line notNil 
+                             and:[(line startsWith:Character space) or:[line startsWith:Character tab]]] whileTrue:[
+                                tokens := line asCollectionOfSubstringsSeparatedBy:$:.
+                                tags at:(tokens first withoutSeparators) put:(tokens second withoutSeparators).
+                                line:= inStream nextLine.
+                            ].
+                            info at:#symbolicNames put:tags.
+                        ].
+                        (line startsWith:'description:') ifTrue:[inHeaderInfo := false].
+                    ]
+                ]
+            ].
+            inStream nextLine. "/ skip separating line after description.
+
+            info isEmpty ifTrue:[
+                ('CVSSourceCodeManager [warning]: no log for ', modulePath) errorPrintCR.
+            ] ifFalse:[
+
+                "/ strip selected revisions from the total-revisions entry
+                s := info at:#numberOfRevisions.
+                (idx := s indexOf:$;) ~~ 0 ifTrue:[
+                    info at:#numberOfRevisions put:(Integer readFrom:(s copyTo:idx - 1))
+                ] ifFalse:[
+                    info at:#numberOfRevisions put:(Integer readFrom:s onError:[1])
+                ].
+                headerOnly ifFalse:[
+                    |numRevisions|
+
+                    "/
+                    "/ continue to read the commands pipe output 
+                    "/ and extract revision info records
+                    "/
+                    numRevisions := info at:#numberOfRevisions.
+                    revisionRecords := OrderedCollection new:numRevisions.
+                    info at:#revisions put:revisionRecords.
+
+                    atEnd := false.
+                    [atEnd or:[inStream atEnd]] whileFalse:[
+                        record := self readRevisionLogEntryFromStream:inStream.
+                        record isNil ifTrue:[
+                            atEnd := true.
+                        ] ifFalse:[
+                            revisionRecords add:record.
+                        ].
+                        (numRevisions notNil and:[revisionRecords size >= numRevisions]) ifTrue:[
+                            atEnd := true
+                        ]
+                    ].
+                ].
+            ].
+            fn := info at:#filename ifAbsent:nil.
+            fn isNil ifTrue:[
+                container := info at:#container ifAbsent:nil.
+                fn := container asFilename baseName copyWithoutLast:2.   "/ remove ',v' suffix
+                info at:#filename put:fn.
+            ].
+            infoCollection at:(info at:#filename) put:info.    
+        ].
+    ] 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.
+    ].
+    ^ infoCollection
+
+    "
+     CVSSourceCodeManager revisionLogOfPackageInDirectory:'libbasic3' module:'stx'  
+    "
+!
+
 setSymbolicName:symbolicName revision:rev overWrite:overWriteBool class:aClass
     "set a symbolicName for revision rev.
      If rev is nil, set it for the head (most recent) revision.
@@ -4512,7 +4707,7 @@
 !CVSSourceCodeManager class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic3/CVSSourceCodeManager.st,v 1.349 2007-03-28 16:44:09 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic3/CVSSourceCodeManager.st,v 1.350 2008-02-04 17:08:53 cg Exp $'
 ! !
 
 CVSSourceCodeManager initialize!