DataBaseSourceCodeManager.st
changeset 2674 7612087d1a82
child 2684 4fed20db7ecb
equal deleted inserted replaced
2673:06f4f56d7818 2674:7612087d1a82
       
     1 "
       
     2  COPYRIGHT (c) 2011 by Claus Gittinger
       
     3               All Rights Reserved
       
     4 
       
     5  This software is furnished under a license and may be used
       
     6  only in accordance with the terms of that license and with the
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 "{ Package: 'stx:libbasic3' }"
       
    13 
       
    14 AbstractSourceCodeManager subclass:#DataBaseSourceCodeManager
       
    15 	instanceVariableNames:''
       
    16 	classVariableNames:'Verbose RepositoryPath ModulePathes'
       
    17 	poolDictionaries:''
       
    18 	category:'System-SourceCodeManagement'
       
    19 !
       
    20 
       
    21 !DataBaseSourceCodeManager class methodsFor:'documentation'!
       
    22 
       
    23 copyright
       
    24 "
       
    25  COPYRIGHT (c) 2011 by Claus Gittinger
       
    26               All Rights Reserved
       
    27 
       
    28  This software is furnished under a license and may be used
       
    29  only in accordance with the terms of that license and with the
       
    30  inclusion of the above copyright notice.   This software may not
       
    31  be provided or otherwise made available to, or used by, any
       
    32  other person.  No title to or ownership of the software is
       
    33  hereby transferred.
       
    34 "
       
    35 !
       
    36 
       
    37 documentation
       
    38 "
       
    39     A simple file based sourceCodeManager, which saves versions in a local directory.
       
    40     Versions will be stored as filename.st.vNr (i.e. Foo.st.1, Foo.st.2, etc.)
       
    41 
       
    42     This is more an example of the protocol which needs to be implemented,
       
    43     than a real manager (although it may be useful for tiny private projects or classroom examples)
       
    44 
       
    45     [author:]
       
    46         Claus Gittinger
       
    47 "
       
    48 ! !
       
    49 
       
    50 !DataBaseSourceCodeManager class methodsFor:'accessing'!
       
    51 
       
    52 getRepositoryPathForModule:aModuleName
       
    53     "internal: used when accessing a source repository.
       
    54      Return the path to the top directory for a particular module.
       
    55      If no specific path was defined for that module, return the value of
       
    56      the global (fallBack) repositoryPath.
       
    57      Nil is returned if no repository is available." 
       
    58 
       
    59     ModulePathes isNil ifTrue:[^ RepositoryPath].
       
    60     aModuleName isNil ifTrue:[^ RepositoryPath].
       
    61     ^ ModulePathes at:aModuleName ifAbsent:RepositoryPath.
       
    62 
       
    63     "Modified: / 20-05-1998 / 16:30:12 / cg"
       
    64     "Created: / 21-12-2011 / 23:05:51 / cg"
       
    65 !
       
    66 
       
    67 knownModules
       
    68     "return the modules, we currently know"
       
    69 
       
    70     ^ ModulePathes keys
       
    71 
       
    72     "Modified: / 21-12-2011 / 14:54:53 / cg"
       
    73 !
       
    74 
       
    75 repositoryPath
       
    76     "return the path of the default repository"
       
    77 
       
    78     ^ RepositoryPath
       
    79 
       
    80     "Created: / 21-12-2011 / 14:55:12 / cg"
       
    81 ! !
       
    82 
       
    83 !DataBaseSourceCodeManager class methodsFor:'queries'!
       
    84 
       
    85 defaultRepositoryName
       
    86     "/ '<db-type>:[<user>[.<password>]@][<host>]<db-name>[:<table-name>]'
       
    87 
       
    88     ^ 'sqlite:repository.db'
       
    89 
       
    90     "Created: / 22-12-2011 / 00:19:43 / cg"
       
    91 !
       
    92 
       
    93 enabled
       
    94     ^ true "/ false.
       
    95 
       
    96     "Created: / 21-12-2011 / 17:53:34 / cg"
       
    97 !
       
    98 
       
    99 isContainerBased
       
   100     "true, if the SCM uses some kind of source container (,v files).
       
   101      False, if it is like a database or filesystem."
       
   102 
       
   103     ^ false
       
   104 
       
   105     "Created: / 21-12-2011 / 18:53:55 / cg"
       
   106 !
       
   107 
       
   108 isResponsibleForPackage:aString
       
   109     ^ true.
       
   110 
       
   111     "Created: / 09-07-2011 / 14:32:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   112     "Modified (format): / 22-12-2011 / 00:05:39 / cg"
       
   113 !
       
   114 
       
   115 managerTypeName
       
   116     ^ 'DBRepository'
       
   117 
       
   118     "Created: / 16-08-2006 / 11:05:56 / cg"
       
   119 !
       
   120 
       
   121 nameOfVersionMethodForExtensions
       
   122     ^ #'extensionsVersion_DB'
       
   123 
       
   124     "Modified: / 22-12-2011 / 00:06:15 / cg"
       
   125 !
       
   126 
       
   127 nameOfVersionMethodInClasses
       
   128     ^ #'version_DB'
       
   129 
       
   130     "Modified: / 22-12-2011 / 00:06:21 / cg"
       
   131 !
       
   132 
       
   133 repositoryNameForPackage:packageId 
       
   134     "superclass AbstractSourceCodeManager class says that I am responsible to implement this method"
       
   135 
       
   136     ^ self getDBNameForModule:(packageId upTo:$: )
       
   137 
       
   138     "Created: / 21-12-2011 / 23:07:02 / cg"
       
   139 !
       
   140 
       
   141 settingsApplicationClass
       
   142     "link to my settings application (needed for the settings dialog"
       
   143 
       
   144     ^ DataBaseSourceCodeManagementSettingsAppl
       
   145 
       
   146     "Created: / 19-04-2011 / 12:43:29 / cg"
       
   147     "Modified: / 22-12-2011 / 00:06:53 / cg"
       
   148 ! !
       
   149 
       
   150 !DataBaseSourceCodeManager class methodsFor:'saving'!
       
   151 
       
   152 savePreferencesOn:aStream
       
   153     aStream nextPutLine:'DataBaseSourceCodeManager notNil ifTrue:['.
       
   154     self repositoryInfoPerModule notEmptyOrNil ifTrue:[
       
   155         aStream nextPutLine:'    DataBaseSourceCodeManager repositoryInfoPerModule:' , self repositoryInfoPerModule storeString , '.'.
       
   156     ].
       
   157     (Smalltalk at:#SourceCodeManager) == self ifTrue:[
       
   158         aStream nextPutLine:'    Smalltalk at:#SourceCodeManager put:DataBaseSourceCodeManager.'.
       
   159     ].
       
   160     aStream nextPutLine:'    DataBaseSourceCodeManager repositoryPath:' , self repositoryPath storeString , '.'.
       
   161     aStream nextPutLine:'].'.
       
   162 
       
   163     "Created: / 09-11-2006 / 15:09:25 / cg"
       
   164     "Modified: / 22-12-2011 / 00:48:25 / cg"
       
   165 ! !
       
   166 
       
   167 !DataBaseSourceCodeManager class methodsFor:'source code administration'!
       
   168 
       
   169 checkForExistingContainer:fileName inModule:moduleName directory:dirName
       
   170     ^ self checkForExistingModule:moduleName directory:dirName
       
   171 
       
   172     "Created: / 21-12-2011 / 17:56:23 / cg"
       
   173 !
       
   174 
       
   175 checkForExistingModule:moduleDir
       
   176     "check for a package directory to be present"
       
   177 
       
   178     self halt.
       
   179 "/
       
   180 "/    dir := self moduleDirectoryFor:moduleDir.
       
   181 "/    ^ dir exists
       
   182 
       
   183     "Created: / 21-12-2011 / 18:37:28 / cg"
       
   184 !
       
   185 
       
   186 checkForExistingModule:moduleDir directory:packageDir
       
   187     "check for a package directory to be present"
       
   188 
       
   189     self halt.
       
   190 "/    |dir|
       
   191 "/
       
   192 "/    dir := self packageDirectoryForModule:moduleDir package:packageDir.
       
   193 "/    ^ dir exists
       
   194 "/
       
   195 "/
       
   196 
       
   197     "Created: / 21-12-2011 / 18:03:33 / cg"
       
   198 !
       
   199 
       
   200 checkinClass:aClass fileName:classFileName directory:packageDir module:moduleDir source:sourceFile logMessage:logMessage force:force
       
   201     "Return true if ok, false if not."
       
   202 
       
   203     self halt.
       
   204 "/    |targetDir newestRevision newRevision newFile packageMode filter outStream|
       
   205 "/
       
   206 "/    targetDir := self packageDirectoryForModule:moduleDir package:packageDir.
       
   207 "/
       
   208 "/    (targetDir filesMatching:(classFileName,'_*')) do:[:eachVersionFile |
       
   209 "/        |versionString|
       
   210 "/
       
   211 "/        versionString := eachVersionFile copyFrom:(classFileName size + 2).
       
   212 "/        (newestRevision isNil 
       
   213 "/        or:[ self isRevision:versionString after:newestRevision ]) ifTrue:[
       
   214 "/            newestRevision := versionString
       
   215 "/        ].
       
   216 "/    ].
       
   217 "/
       
   218 "/    newestRevision isNil ifTrue:[
       
   219 "/        newRevision := '1'
       
   220 "/    ] ifFalse:[
       
   221 "/        newRevision := self revisionAfter:newestRevision
       
   222 "/    ].
       
   223 "/    newFile := (targetDir construct:classFileName,'_',newRevision printString).
       
   224 "/
       
   225 "/    self updateVersionMethodOf:aClass for:(self revisionStringFor:aClass inModule:moduleDir directory:packageDir container:classFileName revision:newRevision).
       
   226 "/
       
   227 "/    packageMode := self checkMethodPackagesOf:aClass.
       
   228 "/    packageMode == #base ifTrue:[
       
   229 "/        filter := [:mthd | mthd package = aClass package].
       
   230 "/    ].
       
   231 "/
       
   232 "/    [
       
   233 "/        outStream := newFile writeStream.
       
   234 "/    ] on:FileStream openErrorSignal do:[:ex|
       
   235 "/        self reportError:('fileout failed').
       
   236 "/        ^ false
       
   237 "/    ].
       
   238 "/
       
   239 "/    Method flushSourceStreamCache.
       
   240 "/    Class fileOutErrorSignal handle:[:ex |
       
   241 "/        outStream close.
       
   242 "/        newFile delete.
       
   243 "/        self reportError:('fileout failed (',ex description,')').
       
   244 "/        ^ false
       
   245 "/    ] do:[
       
   246 "/        self 
       
   247 "/            fileOutSourceCodeOf:aClass 
       
   248 "/            on:outStream 
       
   249 "/            withTimeStamp:false 
       
   250 "/            withInitialize:true 
       
   251 "/            withDefinition:true
       
   252 "/            methodFilter:filter.
       
   253 "/    ].
       
   254 "/    outStream close.
       
   255 "/
       
   256 "/    newFile exists ifFalse:[
       
   257 "/        self reportError:'fileout failed'.
       
   258 "/        ^ false.
       
   259 "/    ].
       
   260 "/
       
   261 "/    ^ true
       
   262 "/
       
   263 "/
       
   264 
       
   265     "Created: / 21-12-2011 / 19:01:07 / cg"
       
   266 !
       
   267 
       
   268 createModule:moduleDir
       
   269     "create a module directory"
       
   270 
       
   271     self halt.
       
   272 "/    |dir|
       
   273 "/
       
   274 "/    dir := self moduleDirectoryFor:moduleDir.
       
   275 "/    dir recursiveMakeDirectory.
       
   276 "/    ^ dir exists.
       
   277 
       
   278     "Created: / 21-12-2011 / 18:38:22 / cg"
       
   279 !
       
   280 
       
   281 createModule:moduleDir directory:packageDir
       
   282     "create a package directory"
       
   283 
       
   284     self halt.
       
   285 "/    |dir|
       
   286 "/
       
   287 "/    dir := self packageDirectoryForModule:moduleDir package:packageDir.
       
   288 "/    dir recursiveMakeDirectory.
       
   289 "/    ^ dir exists.
       
   290 
       
   291     "Created: / 21-12-2011 / 18:44:20 / cg"
       
   292 !
       
   293 
       
   294 initialRevisionStringFor:aClass inModule:moduleDir directory:packageDir container:fileName
       
   295     "return a string usable as initial revision string"
       
   296 
       
   297     ^ self 
       
   298         revisionStringFor:aClass 
       
   299         inModule:moduleDir 
       
   300         directory:packageDir 
       
   301         container:fileName 
       
   302         revision:'1'
       
   303 
       
   304     "Created: / 21-12-2011 / 18:14:03 / cg"
       
   305 !
       
   306 
       
   307 moduleDirectoryFor:moduleDir
       
   308     "a modules directory as filename"
       
   309 
       
   310     self halt.
       
   311 "/    |root|
       
   312 "/
       
   313 "/    root := self getRepositoryPathForModule:moduleDir.
       
   314 "/    root isNil ifTrue:[
       
   315 "/        RepositoryPath := root := self defaultRepositoryPath.
       
   316 "/    ].
       
   317 "/
       
   318 "/    ^ (root asFilename construct:moduleDir)
       
   319 
       
   320     "Created: / 21-12-2011 / 18:38:38 / cg"
       
   321 !
       
   322 
       
   323 packageDirectoryForModule:moduleDir package:package
       
   324     "a packages directory as filename"
       
   325 
       
   326     self halt.
       
   327 "/    |dir|
       
   328 "/
       
   329 "/    dir := self moduleDirectoryFor:moduleDir.
       
   330 "/    ^ dir construct:package
       
   331 
       
   332     "Created: / 21-12-2011 / 18:43:27 / cg"
       
   333 !
       
   334 
       
   335 revisionInfoFromString:aString 
       
   336     "{ Pragma: +optSpace }"
       
   337 
       
   338     "return a VersionInfo object filled with revision info.
       
   339      This extracts the relevant info from aString."
       
   340 
       
   341     |info path version user ts timeStamp idx1 idx2|
       
   342 
       
   343     "/ 'Path: stx/libbasic/Array.st, Version: 123, User: cg, Time: 2011-12-21T21:03:08.826'
       
   344 
       
   345     idx1 := aString indexOfSubCollection:'Path: '.
       
   346     idx1 ~~ 0 ifTrue:[
       
   347         idx1 := idx1 + 'Path: ' size.
       
   348         idx2 := aString indexOfSubCollection:', ' startingAt:idx1.
       
   349         path := aString copyFrom:idx1 to:idx2-1.     
       
   350     ].
       
   351     idx1 := aString indexOfSubCollection:'Version: '.
       
   352     idx1 ~~ 0 ifTrue:[
       
   353         idx1 := idx1 + 'Version: ' size.
       
   354         idx2 := aString indexOfSubCollection:', ' startingAt:idx1.
       
   355         idx2 == 0 ifTrue:[
       
   356             version := aString copyFrom:idx1     
       
   357         ] ifFalse:[
       
   358             version := aString copyFrom:idx1 to:idx2-1.     
       
   359         ].
       
   360     ].
       
   361     idx1 := aString indexOfSubCollection:'User: '.
       
   362     idx1 ~~ 0 ifTrue:[
       
   363         idx1 := idx1 + 'User: ' size.
       
   364         idx2 := aString indexOfSubCollection:', ' startingAt:idx1.
       
   365         idx2 == 0 ifTrue:[
       
   366             user := aString copyFrom:idx1     
       
   367         ] ifFalse:[
       
   368             user := aString copyFrom:idx1 to:idx2-1.     
       
   369         ].
       
   370     ].
       
   371     idx1 := aString indexOfSubCollection:'Time: '.
       
   372     idx1 ~~ 0 ifTrue:[
       
   373         idx1 := idx1 + 'Time: ' size.
       
   374         idx2 := aString indexOfSubCollection:', ' startingAt:idx1.
       
   375         idx2 == 0 ifTrue:[
       
   376             ts := aString copyFrom:idx1     
       
   377         ] ifFalse:[
       
   378             ts := aString copyFrom:idx1 to:idx2-1.     
       
   379         ].
       
   380         timeStamp := Timestamp readIso8601FormatFrom:ts
       
   381     ].
       
   382 
       
   383     info := VersionInfo new.
       
   384     path notNil ifTrue:[ info fileName:(path asFilename baseName) ].
       
   385     info revision:version.
       
   386     user notNil ifTrue:[ info user:user ].
       
   387     timeStamp notNil ifTrue:[ info timeStamp:timeStamp ].
       
   388     ^ info
       
   389 
       
   390     "
       
   391      self revisionInfoFromString:'Path: stx/libbasic/Array.st, Version: 123, User: cg, Time: 2011-12-21T21:03:08.826' 
       
   392     "
       
   393 
       
   394     "Created: / 21-12-2011 / 14:50:12 / cg"
       
   395 !
       
   396 
       
   397 revisionLogOf:clsOrNil fromRevision:rev1OrNil toRevision:rev2OrNil numberOfRevisions:limitOrNil fileName:classFileName directory:packageDir module:moduleDir 
       
   398     "Return true if ok, false if not."
       
   399 
       
   400     self halt.
       
   401 "/    |info log targetDir count newestRevision|
       
   402 "/
       
   403 "/    targetDir := self packageDirectoryForModule:moduleDir package:packageDir.
       
   404 "/    targetDir exists ifFalse:[^ nil ].
       
   405 "/
       
   406 "/    info := IdentityDictionary new.
       
   407 "/    log := OrderedCollection new.
       
   408 "/    count := 0.
       
   409 "/
       
   410 "/    (targetDir filesMatching:(classFileName,'_*')) do:[:eachVersionFile |
       
   411 "/        |versionString cs versionChange info|
       
   412 "/
       
   413 "/        versionString := eachVersionFile copyFrom:(classFileName size + 2).
       
   414 "/        count := count + 1.
       
   415 "/        (newestRevision isNil 
       
   416 "/        or:[ self isRevision:versionString after:newestRevision ]) ifTrue:[
       
   417 "/            newestRevision := versionString
       
   418 "/        ].
       
   419 "/
       
   420 "/        (rev1OrNil isNil 
       
   421 "/            or:[ rev1OrNil = 0
       
   422 "/            or:[ versionString = rev1OrNil
       
   423 "/            or:[ self isRevision:versionString after:rev1OrNil ]]])
       
   424 "/        ifTrue:[
       
   425 "/            (rev2OrNil isNil 
       
   426 "/                or:[ rev2OrNil = 0
       
   427 "/                or:[ versionString = rev2OrNil
       
   428 "/                or:[ self isRevision:rev2OrNil after:versionString ]]])
       
   429 "/            ifTrue:[
       
   430 "/                (limitOrNil isNil
       
   431 "/                or:[ log size < limitOrNil ])
       
   432 "/                ifTrue:[
       
   433 "/                    cs := ChangeSet fromFile:(targetDir construct:eachVersionFile).
       
   434 "/                    versionChange := cs detect:[:chg | chg isMethodChange
       
   435 "/                                                       and:[chg selector = self nameOfVersionMethodInClasses]]
       
   436 "/                                        ifNone:nil.
       
   437 "/                    versionChange notNil ifTrue:[
       
   438 "/                        info := self revisionInfoFromString:versionChange source.
       
   439 "/                    ] ifFalse:[
       
   440 "/                        info := VersionInfo new.
       
   441 "/                    ].
       
   442 "/
       
   443 "/                    info revision:versionString.
       
   444 "/                    log add:info.
       
   445 "/                ]
       
   446 "/            ].
       
   447 "/        ].
       
   448 "/    ].
       
   449 "/    log sort:[:a :b | self isRevision:b revision after:a revision].
       
   450 "/
       
   451 "/    info at:#revisions put:log.
       
   452 "/    info at:#numberOfRevisions put:count.
       
   453 "/    info at:#newestRevision put:newestRevision.
       
   454 "/
       
   455 "/    ^ info
       
   456 "/
       
   457 "/
       
   458 
       
   459     "Created: / 21-12-2011 / 20:39:31 / cg"
       
   460 !
       
   461 
       
   462 revisionStringFor:aClass inModule:moduleDir directory:packageDir container:fileName revision:revisionString
       
   463     "return a string usable as initial revision string"
       
   464 
       
   465     ^ 'Path: %1/%2/%3, Version: %4, User: %5, Time: %6'
       
   466         bindWith:moduleDir
       
   467         with:packageDir
       
   468         with:fileName
       
   469         with:revisionString
       
   470         with:(OperatingSystem getLoginName)
       
   471         with:(Timestamp now printStringIso8601Format)
       
   472 
       
   473     "
       
   474      self revisionStringFor:Array inModule:'stx' directory:'libbasic' container:'Array.st' revision:'123'
       
   475     "
       
   476 
       
   477     "Created: / 21-12-2011 / 19:33:33 / cg"
       
   478 !
       
   479 
       
   480 streamForClass:aClass fileName:classFileName revision:revision directory:packageDir module:moduleDir cache:doCache
       
   481     self halt.
       
   482 "/    |targetDir oldFile|
       
   483 "/
       
   484 "/    targetDir := self packageDirectoryForModule:moduleDir package:packageDir.
       
   485 "/    oldFile := (targetDir construct:classFileName,'_',revision).
       
   486 "/    ^ oldFile readStream
       
   487 
       
   488     "Created: / 21-12-2011 / 20:49:01 / cg"
       
   489 ! !
       
   490 
       
   491 !DataBaseSourceCodeManager class methodsFor:'documentation'!
       
   492 
       
   493 version
       
   494     ^ '$Header: /cvs/stx/stx/libbasic3/DataBaseSourceCodeManager.st,v 1.1 2011-12-22 13:03:16 cg Exp $'
       
   495 !
       
   496 
       
   497 version_CVS
       
   498     ^ '$Header: /cvs/stx/stx/libbasic3/DataBaseSourceCodeManager.st,v 1.1 2011-12-22 13:03:16 cg Exp $'
       
   499 ! !