More SourceCodeManager API.
authorJan Vrany <jan.vrany@fit.cvut.cz>
Tue, 04 Dec 2012 10:14:28 +0000
changeset 126 952efea00dd2
parent 125 4d1414d5f1ba
child 127 4135913495fc
More SourceCodeManager API. Added #streamForClass:fileName:revision:directory:module:cache:
mercurial/HGChangesetFile.st
mercurial/HGCommand.st
mercurial/HGSourceCodeManager.st
mercurial/HGStXTests.st
mercurial/mercurial.rc
--- a/mercurial/HGChangesetFile.st	Tue Dec 04 01:36:59 2012 +0000
+++ b/mercurial/HGChangesetFile.st	Tue Dec 04 10:14:28 2012 +0000
@@ -189,6 +189,21 @@
     "Created: / 16-11-2012 / 23:41:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!HGChangesetFile methodsFor:'operations'!
+
+copyTo: aStringOrFilename
+    "Writes contents of the receiver to given file"
+
+    HGCommand cat
+        workingDirectory: self repository pathName;
+        path: self pathName;
+        revision: changeset id revno;
+        destination: aStringOrFilename;
+        execute.
+
+    "Created: / 04-12-2012 / 01:58:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !HGChangesetFile methodsFor:'printing & storing'!
 
 printOn:aStream
--- a/mercurial/HGCommand.st	Tue Dec 04 01:36:59 2012 +0000
+++ b/mercurial/HGCommand.st	Tue Dec 04 10:14:28 2012 +0000
@@ -22,7 +22,7 @@
 !
 
 HGCommand subclass:#cat
-	instanceVariableNames:'path revision'
+	instanceVariableNames:'path revision destination'
 	classVariableNames:''
 	poolDictionaries:''
 	privateIn:HGCommand
@@ -602,6 +602,14 @@
 
 !HGCommand::cat methodsFor:'accessing'!
 
+destination
+    ^ destination
+!
+
+destination:aStringOrFilename
+    destination := aStringOrFilename.
+!
+
 path
     ^ path
 !
@@ -627,7 +635,7 @@
     
     "
 
-    | pipe output pid environment sema args |
+    | pipe output pid environment sema args sout exec |
 
     pipe := NonPositionableExternalStream makePipe.
     output := pipe first.
@@ -648,22 +656,43 @@
         ]
     ].
 
+    sout := destination notNil 
+                ifTrue:[destination asFilename writeStream]
+                ifFalse:[pipe second].
     sema := Semaphore new name: 'Waiting for hg command to finish'.
-    pid := OperatingSystem exec:(self executable) withArguments:args
-            environment:environment
-            fileDescriptors:{0 . pipe second fileDescriptor . pipe second fileDescriptor}
-            fork:true 
-            newPgrp:false 
-            inDirectory:self workingDirectory.
+    exec := [
+        pid := OperatingSystem exec:(self executable) withArguments:args
+                environment:environment
+                fileDescriptors:{0 . sout fileDescriptor . pipe second fileDescriptor}
+                fork:true 
+                newPgrp:false 
+                inDirectory:self workingDirectory.
+    ].
+
+    destination notNil ifTrue:[
+        Processor 
+            monitor:exec
+            action:[:stat |
+                sema signal.
+            ].
+    ] ifFalse:[
+        exec value
+    ].
+
+
     pipe second close.
+    sout close.
     pid isNil ifTrue:[
         HGCommandError raiseErrorString: 'cannot execute hg command'.
         output close.
         ^ self.
     ].
-    ^output
+    ^destination notNil 
+        ifTrue:[sema wait. nil]
+        ifFalse:[output].
 
     "Created: / 17-11-2012 / 00:13:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 04-12-2012 / 10:10:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !HGCommand::cat methodsFor:'private'!
--- a/mercurial/HGSourceCodeManager.st	Tue Dec 04 01:36:59 2012 +0000
+++ b/mercurial/HGSourceCodeManager.st	Tue Dec 04 10:14:28 2012 +0000
@@ -62,7 +62,38 @@
      The classes source code is extracted using the revision and the sourceCodeInfo,
      which itself is extracted from the classes packageString."
 
-    ^ self shouldImplement
+    | pkg repo file |
+
+    pkg := HGPackageModel named: (moduleDir , ':' , packageDir).
+    repo := pkg repository.
+    file := (repo @ revision) / pkg repositoryRoot / classFileName.
+
+    doCache ifTrue:[
+        ^SourceCodeCache default
+            streamForClass:aClass 
+            fileName:classFileName 
+            revision:revision 
+            repository: 'svn' "TODO: Use repository ID here" 
+            module:moduleDir 
+            directory:packageDir 
+            ifAbsent: [:destination|
+                ActivityNotification notify: ('Checking out ', classFileName , '@' , revision  , '...').
+                [
+                    file copyTo: destination.    
+                    destination exists ifTrue:[
+                        destination readStream
+                    ] ifFalse:[
+                        nil
+                    ]
+                ] on: SVN::SVNError do:[
+                    nil                    
+                ]
+            ]            
+    ] ifFalse:[
+        ^file readStream.
+    ]
+
+    "Modified: / 04-12-2012 / 02:04:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !HGSourceCodeManager class methodsFor:'basic administration'!
@@ -148,12 +179,12 @@
             Attention: if state = 'dead' that revision is no longer valid.
     "
 
-    | pkg repo path info newest |
+    | pkg repo path info newest rev limit stop log |
 
     info := IdentityDictionary new.
-    pkg := HGPackageModelRegistry packageNamed: (moduleDir , ':' , packageDir).
+    pkg := HGPackageModel named: (moduleDir , ':' , packageDir).
     repo := pkg repository.
-    path := repo repositoryRoot.
+    path := pkg repositoryRoot.
 
     newest := repo workingCopy heads first.
     [   
@@ -169,13 +200,41 @@
     info at:#filename           put: classFileName.         "/ -> the actual source file name
     info at:#newestRevision     put: newest id printString. "/-> the revisionString of the newest revision
 
-    (rev1OrNil == 0 and:[rev2OrNil == 0]) ifTrue:[ ^ info ].
+    (rev1OrNil == 0 and:[rev2OrNil == 0]) ifTrue:[
+        limit := 1
+    ] ifFalse:[
+        limit := limitOrNil 
+    ].
+    log := OrderedCollection new.
+    rev := rev1OrNil isNil ifTrue:[newest] ifFalse:[repo @ rev1OrNil].
+
+    stop := false.
+    [ stop ] whileFalse:[
+        | entry |
 
-    self breakPoint: #jv.
+        entry :=  IdentityDictionary new.
+        entry at:#revision              put: rev id printString."/ -> the revision string
+        entry at:#author                put: rev author."/ -> who checked that revision into the repository
+        entry at:#date                  put: rev timestamp printString."/ -> when was it checked in
+        entry at:#state                 put: 'Exp'. "/ -> the RCS state
+        entry at:#numberOfChangedLines  put: 'N/A'. "/ -> the number of changed line w.r.t the previous
+        entry at:#logMessage            put: rev message."/ -> the checkIn log message.
+        log add: entry.
+
+        limit notNil ifTrue:[limit := limit - 1].
+        stop :=
+            rev isNil 
+                or:[limit == 0
+                or:[(rev2OrNil notNil and:[rev2OrNil = rev id printString])
+                or:[([ rev / path / classFileName . false ] on: HGError do:[:ex | true ])]]].
+        rev := rev parent1.
+        
+    ].
+    info at: #revisions put: log.
 
     ^info
 
-    "Modified: / 01-12-2012 / 02:24:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 04-12-2012 / 01:34:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !HGSourceCodeManager class methodsFor:'queries'!
@@ -346,5 +405,5 @@
 !
 
 version_SVN
-    ^ 'Id::                                                                                                                        '
+    ^ '§Id::                                                                                                                        §'
 ! !
--- a/mercurial/HGStXTests.st	Tue Dec 04 01:36:59 2012 +0000
+++ b/mercurial/HGStXTests.st	Tue Dec 04 10:14:28 2012 +0000
@@ -60,8 +60,16 @@
     ].
 "/    Delay waitForSeconds: 1.
 
+    "/ Also, wipe out cached sources...
+    [ 
+        (AbstractSourceCodeManager cacheDirectoryName asFilename / 'mocks') recursiveRemove
+    ] on: Error do:[:ex|
+        Delay waitForSeconds: 1.
+        (AbstractSourceCodeManager cacheDirectoryName asFilename / 'mocks') recursiveRemove.
+    ]
+
     "Created: / 16-11-2012 / 19:00:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 21-11-2012 / 17:53:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 04-12-2012 / 02:14:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 test_infrastructure
@@ -583,6 +591,110 @@
     self assert: ((log at: #revisions) first at:#revision) = '0:99acfa83a3bf'.
 
     "Created: / 04-12-2012 / 01:33:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_stream_01a
+
+    | stream repo contents |
+
+
+    repo := self repositoryNamed: 'mocks/hg/p1'.
+    self assert: (Smalltalk loadPackage:'mocks:hg/p1').
+
+    stream := HGSourceCodeManager 
+                streamForClass:MockHGP1Bar 
+                fileName:'MockHGP1Bar.st'
+                revision: '0:99acfa83a3bf'
+                directory: 'hg/p1'
+                module:'mocks'
+                cache: false.
+    contents := stream contents.
+
+    self assert: contents first = '"{ Package: ''mocks/hg/p1'' }"'
+
+    "Created: / 04-12-2012 / 02:04:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_stream_01b
+
+    | stream repo contents |
+
+
+    repo := self repositoryNamed: 'mocks/hg/p1'.
+    self assert: (Smalltalk loadPackage:'mocks:hg/p1').
+
+    stream := HGSourceCodeManager 
+                streamForClass:MockHGP1Bar 
+                fileName:'MockHGP1Bar.st'
+                revision: '1:e0bec585af86'
+                directory: 'hg/p1'
+                module:'mocks'
+                cache: false.
+    contents := stream contents.
+
+    self assert: contents first = '"{ Package: ''mocks:hg/p1'' }"'
+
+    "Created: / 04-12-2012 / 02:05:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_stream_02a
+
+    | stream repo contents |
+
+
+    repo := self repositoryNamed: 'mocks/hg/p1'.
+    self assert: (Smalltalk loadPackage:'mocks:hg/p1').
+
+    stream := HGSourceCodeManager 
+                streamForClass:MockHGP1Bar 
+                fileName:'MockHGP1Bar.st'
+                revision: '0:99acfa83a3bf'
+                directory: 'hg/p1'
+                module:'mocks'
+                cache: true.
+
+    contents := stream contents.
+
+    self assert: contents first = '"{ Package: ''mocks/hg/p1'' }"'.
+    self assert: stream isFileStream.
+
+    stream := HGSourceCodeManager 
+                streamForClass:MockHGP1Bar 
+                fileName:'MockHGP1Bar.st'
+                revision: '0:99acfa83a3bf'
+                directory: 'hg/p1'
+                module:'mocks'
+                cache: true.
+
+    contents := stream contents.
+
+    self assert: contents first = '"{ Package: ''mocks/hg/p1'' }"'.
+    self assert: stream isFileStream.
+
+    "Created: / 04-12-2012 / 02:08:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 04-12-2012 / 10:12:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_stream_02b
+
+    | stream repo contents |
+
+
+    repo := self repositoryNamed: 'mocks/hg/p1'.
+    self assert: (Smalltalk loadPackage:'mocks:hg/p1').
+
+    stream := HGSourceCodeManager 
+                streamForClass:MockHGP1Bar 
+                fileName:'MockHGP1Bar.st'
+                revision: '1:e0bec585af86'
+                directory: 'hg/p1'
+                module:'mocks'
+                cache: true.
+    contents := stream contents.
+
+    self assert: contents first = '"{ Package: ''mocks:hg/p1'' }"'
+
+    "Created: / 04-12-2012 / 10:11:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !HGStXTests methodsFor:'tests - misc'!
--- a/mercurial/mercurial.rc	Tue Dec 04 01:36:59 2012 +0000
+++ b/mercurial/mercurial.rc	Tue Dec 04 10:14:28 2012 +0000
@@ -25,7 +25,7 @@
       VALUE "LegalCopyright", "Copyright Jan Vrany 2012\0"
       VALUE "ProductName", "Smalltalk/X Mercurial Integration\0"
       VALUE "ProductVersion", "6.2.3.0\0"
-      VALUE "ProductDate", "Mon, 03 Dec 2012 16:17:54 GMT\0"
+      VALUE "ProductDate", "Tue, 04 Dec 2012 10:13:16 GMT\0"
     END
 
   END