--- a/DataBaseSourceCodeManager.st Sat Nov 29 03:06:15 2014 +0100
+++ b/DataBaseSourceCodeManager.st Sat Nov 29 03:30:39 2014 +0100
@@ -18,6 +18,13 @@
category:'System-SourceCodeManagement'
!
+VersionInfo subclass:#DBVersionInfo
+ instanceVariableNames:'state symbolicVersionName'
+ classVariableNames:''
+ poolDictionaries:''
+ privateIn:DataBaseSourceCodeManager
+!
+
!DataBaseSourceCodeManager class methodsFor:'documentation'!
copyright
@@ -101,6 +108,12 @@
RepositoryName := aDBSpec.
"Created: / 26-12-2011 / 01:13:59 / cg"
+!
+
+utilities
+ "Returns a 'utilities' object that can be used by tools."
+
+ ^ DataBaseSourceCodeManagerUtilities forManager: self
! !
!DataBaseSourceCodeManager class methodsFor:'private'!
@@ -189,34 +202,38 @@
].
(tables includes:'versions') ifTrue:[
- Transcript showCR:'table "versions" already present.'.
+ Transcript showCR:'DBSourceCodeManager: table "versions" already present.'.
] ifFalse:[
- Transcript showCR:'creating table "versions"...'.
- con executeQuery:'CREATE table versions (versionId, name, packageId, author, timestamp);'.
+ Transcript showCR:'DBSourceCodeManager: creating table "versions"...'.
+ con executeQuery:'CREATE table versions (versionId primary key, name, packageId, author, timestamp, state);'.
].
+
(tables includes:'packages') ifTrue:[
- Transcript showCR:'table "packages" already present.'.
+ Transcript showCR:'DBSourceCodeManager: table "packages" already present.'.
] ifFalse:[
- Transcript showCR:'creating table "packages"...'.
- con executeQuery:'CREATE table packages (packageId, name);'.
+ Transcript showCR:'DBSourceCodeManager: creating table "packages"...'.
+ con executeQuery:'CREATE table packages (packageId primary key, name);'.
].
+
(tables includes:'classes') ifTrue:[
- Transcript showCR:'table "classes" already present.'.
+ Transcript showCR:'DBSourceCodeManager: table "classes" already present.'.
] ifFalse:[
- Transcript showCR:'creating table "classes"...'.
- con executeQuery:'CREATE table classes (id, name, superclass, category, definition, packageId, versionId, methodIdList);'.
+ Transcript showCR:'DBSourceCodeManager: creating table "classes"...'.
+ con executeQuery:'CREATE table classes (id primary key, name, superclass, category, definition, packageId, versionId, methodIdList);'.
].
+
(tables includes:'methods') ifTrue:[
- Transcript showCR:'table "methods" already present.'.
+ Transcript showCR:'DBSourceCodeManager: table "methods" already present.'.
] ifFalse:[
- Transcript showCR:'creating table "methods"...'.
- con executeQuery:'CREATE table methods (id, className, selector, source, bytecode, packageId, versionId);'.
+ Transcript showCR:'DBSourceCodeManager: creating table "methods"...'.
+ con executeQuery:'CREATE table methods (id primary key, className, selector, source, bytecode, packageId, versionId);'.
].
+
(tables includes:'chunks') ifTrue:[
- Transcript showCR:'table "chunks" already present.'.
+ Transcript showCR:'DBSourceCodeManager: table "chunks" already present.'.
] ifFalse:[
- Transcript showCR:'creating table "chunks"...'.
- con executeQuery:'CREATE table chunks (id, source);'.
+ Transcript showCR:'DBSourceCodeManager: creating table "chunks"...'.
+ con executeQuery:'CREATE table chunks (id primary key, source);'.
].
^ con
@@ -224,6 +241,101 @@
"Created: / 26-12-2011 / 01:06:37 / cg"
! !
+!DataBaseSourceCodeManager class methodsFor:'private-saving'!
+
+checkInClassAndCollectManifestOf:aClass db:dbConnection
+ "check in a class; write one record for the definition,
+ then one for each method.
+ Return a manifest, which lists each save chunk's key."
+
+ ^ String streamContents:[:s |
+ s nextPutLine:(self manifestOfStoredClassDefinitionOf:aClass db:dbConnection).
+ aClass theMetaclass selectorsAndMethodsDo:[:sel :mthd |
+ (self isVersionMethodSelector:sel) ifTrue:[
+ Transcript showCR:'skip ',sel.
+ ] ifFalse:[
+ s nextPutLine:(self manifestOfStoredMethod:mthd selector:sel meta:true db:dbConnection).
+ ].
+ ].
+ aClass theNonMetaclass selectorsAndMethodsDo:[:sel :mthd |
+ s nextPutLine:(self manifestOfStoredMethod:mthd selector:sel meta:false db:dbConnection).
+ ].
+ ].
+!
+
+insertChunk:chunkData key:key db:dbConnection
+ [
+ dbConnection
+ executeQuery:( 'insert into chunks values (''%1'', ''%2'')'
+ bindWith:key
+ with:(chunkData withCEscapes copyReplaceString:'''' withString:'''''')).
+ ] on:SqliteError do:[
+ "/ already there?
+ |rslt|
+
+ rslt := dbConnection executeQuery:( 'select 1 from chunks where id = ''%1''' bindWith:key).
+ rslt next isNil ifTrue:[
+ "/ not there - error
+ self error:'cannot insert chunk int db'
+ ].
+ "/ ok - already there.
+ ].
+!
+
+keyForChunk:aString
+ "chunks are keyed by their sha1 hash value.
+ This has the advantage, that:
+ - the key alone shows if anything has changed,
+ - no new record is required if a chunk uis unchanged,
+ - going back to an old version automatically reuses/refers to the old chunk,
+ - two independently changed methods will generate the same key"
+
+ ^ (SHA1Stream hashValueOf:aString) hexPrintString
+!
+
+manifestOfStoredClassDefinitionOf:aClass db:dbConnection
+ "save a class definition;
+ return a manifest line"
+
+ |dfn id|
+
+ dfn := aClass theNonMetaclass definition.
+ id := self keyForChunk:dfn.
+
+ self insertChunk:dfn key:id db:dbConnection.
+ ^ 'definition: ' , id.
+!
+
+manifestOfStoredMethod:aMethod selector:aSymbol meta:isMeta db:dbConnection
+ "save a method;
+ return a manifest line"
+
+ |src id|
+
+ src := aMethod source.
+ id := self keyForChunk:src.
+ self insertChunk:src key:id db:dbConnection.
+ ^ (isMeta ifTrue:'class method: ' ifFalse:'method: ')
+ , aSymbol , ' '
+ , id.
+!
+
+savePreferencesOn:aStream
+ aStream nextPutLine:'DataBaseSourceCodeManager notNil ifTrue:['.
+ self repositoryInfoPerModule notEmptyOrNil ifTrue:[
+ aStream nextPutLine:' DataBaseSourceCodeManager repositoryInfoPerModule:' , self repositoryInfoPerModule storeString , '.'.
+ ].
+ (Smalltalk at:#SourceCodeManager) == self ifTrue:[
+ aStream nextPutLine:' Smalltalk at:#SourceCodeManager put:DataBaseSourceCodeManager.'.
+ ].
+ aStream nextPutLine:' DataBaseSourceCodeManager repositoryName:' , self repositoryName storeString , '.'.
+ aStream nextPutLine:'].'.
+
+ "Created: / 09-11-2006 / 15:09:25 / cg"
+ "Modified: / 22-12-2011 / 00:48:25 / cg"
+ "Modified: / 01-01-2012 / 17:02:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
!DataBaseSourceCodeManager class methodsFor:'queries'!
defaultRepositoryName
@@ -240,6 +352,10 @@
"Created: / 21-12-2011 / 17:53:34 / cg"
!
+initialRevisionString
+ ^ '0'
+!
+
isContainerBased
"true, if the SCM uses some kind of source container (,v files).
False, if it is like a database or filesystem."
@@ -289,87 +405,91 @@
"Created: / 19-04-2011 / 12:43:29 / cg"
"Modified: / 22-12-2011 / 00:06:53 / cg"
-! !
-
-!DataBaseSourceCodeManager class methodsFor:'saving'!
-
-checkInClassAndCollectManifestOf:aClass db:dbConnection
- "check in a class;
- return a manifest"
-
- ^ String streamContents:[:s |
- s nextPutLine:(self manifestOfStoredClassDefinitionOf:aClass db:dbConnection).
- aClass theMetaclass selectorsAndMethodsDo:[:sel :mthd |
- (self isVersionMethodSelector:sel) ifFalse:[
- s nextPutLine:(self manifestOfStoredMethod:mthd selector:sel meta:true db:dbConnection).
- ].
- ].
- aClass theNonMetaclass selectorsAndMethodsDo:[:sel :mthd |
- s nextPutLine:(self manifestOfStoredMethod:mthd selector:sel meta:false db:dbConnection).
- ].
- ].
-!
-
-keyForChunk:aString
- ^ (SHA1Stream hashValueOf:aString) hexPrintString
!
-manifestOfStoredClassDefinitionOf:aClass db:dbConnection
- "save a class definition;
- return a manifest line"
-
- |dfn id|
-
- dfn := aClass theNonMetaclass definition.
- id := self keyForChunk:dfn.
-
- dbConnection
- executeQuery:(
- 'insert into chunks values (''%1'', ''%2'')'
- bindWith:id
- with:(dfn withCEscapes copyReplaceString:'''' withString:'''''')).
-
- ^ 'definition: ' , id.
-!
-
-manifestOfStoredMethod:aMethod selector:aSymbol meta:isMeta db:dbConnection
- "save a method;
- return a manifest line"
-
- |src id|
+versionInfoClass
- src := aMethod source.
- id := self keyForChunk:src.
-
- dbConnection
- executeQuery:(
- 'insert into chunks values (''%1'', ''%2'')'
- bindWith:id
- with:(src withCEscapes copyReplaceString:'''' withString:'''''')).
-
- ^ (isMeta ifTrue:'class method: ' ifFalse:'method: ')
- , aSymbol , ' '
- , id.
-!
-
-savePreferencesOn:aStream
- aStream nextPutLine:'DataBaseSourceCodeManager notNil ifTrue:['.
- self repositoryInfoPerModule notEmptyOrNil ifTrue:[
- aStream nextPutLine:' DataBaseSourceCodeManager repositoryInfoPerModule:' , self repositoryInfoPerModule storeString , '.'.
- ].
- (Smalltalk at:#SourceCodeManager) == self ifTrue:[
- aStream nextPutLine:' Smalltalk at:#SourceCodeManager put:DataBaseSourceCodeManager.'.
- ].
- aStream nextPutLine:' DataBaseSourceCodeManager repositoryName:' , self repositoryName storeString , '.'.
- aStream nextPutLine:'].'.
-
- "Created: / 09-11-2006 / 15:09:25 / cg"
- "Modified: / 22-12-2011 / 00:48:25 / cg"
- "Modified: / 01-01-2012 / 17:02:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ ^DBVersionInfo
! !
!DataBaseSourceCodeManager class methodsFor:'source code administration'!
+basicCheckinClass:aClass fileName:classFileName directory:packageDir module:moduleDir logMessage:logMessage force:force
+ "low level checkin of a class into the source repository.
+ Does not deal with any version method updates.
+ Return true if ok, false if not."
+
+ |dbConnection author state|
+
+ aClass isPrivate ifTrue:[
+ self reportError:'refuse to check in private classes.'.
+ ^ false.
+ ].
+
+ dbConnection := self dbHandleForModule:moduleDir.
+ [
+ |collectedVersionSpec hashKey basicRevisionString revisionString
+ oldRevision newRevision oldInfo symbolicVersion|
+
+ collectedVersionSpec := self checkInClassAndCollectManifestOf:aClass db:dbConnection.
+ hashKey := self keyForChunk:collectedVersionSpec.
+
+ self insertChunk:collectedVersionSpec key:hashKey db:dbConnection.
+
+ oldRevision := aClass revisionOfManager:self.
+ newRevision := hashKey.
+ oldRevision ~= newRevision ifTrue:[
+ oldInfo := aClass revisionInfoOfManager:self.
+ oldInfo isNil ifTrue:[
+ symbolicVersion := '1.0'
+ ] ifFalse:[
+ symbolicVersion := oldInfo symbolicVersionName ? '1.0'
+ ].
+
+ basicRevisionString := (self revisionStringFor:aClass inModule:moduleDir directory:packageDir container:classFileName revision:hashKey).
+ revisionString := basicRevisionString,', SymbolicVersion: ',symbolicVersion.
+ self updateVersionMethodOf:aClass for:revisionString.
+
+ author := OperatingSystem getFullUserName.
+ author isEmptyOrNil ifTrue:[ author := OperatingSystem getLoginName ].
+ author isEmptyOrNil ifTrue:[ author := 'unknown' ].
+ state := ''.
+
+ [
+ "/ (versionId primary key, name, packageId, author, timestamp)
+ dbConnection
+ executeQuery:(
+ 'insert into versions (key, name, packageId, author, timestamp) values (''%1'', ''%2'', ''%3'', ''%4'', ''%5'', ''%6'')'
+ bindWith:newRevision
+ with:(symbolicVersion withCEscapes copyReplaceString:'''' withString:'''''')
+ with:(aClass package withCEscapes copyReplaceString:'''' withString:'''''')
+ with:(author withCEscapes copyReplaceString:'''' withString:'''''')
+ with:(UtcTimestamp now printStringIso8601)
+ with:state).
+ ] on:SqliteError do:[
+ "/ already there?
+ |rslt|
+
+ rslt := dbConnection executeQuery:( 'select 1 from versions where key = ''%1''' bindWith:newRevision).
+ rslt next isNil ifTrue:[
+ "/ not there - error
+ self error:'cannot insert chunk int db'
+ ].
+ "/ already there.
+ Dialog information:'An identical version was already present in the repository.'.
+ ].
+ ].
+ ] ensure:[
+ dbConnection close
+ ].
+
+ ^ true.
+
+ "
+ SourceCodeManager checkinClass:Array
+ "
+!
+
checkForExistingContainer:fileName inModule:moduleName directory:dirName
^ self checkForExistingModule:moduleName directory:dirName
@@ -410,25 +530,7 @@
checkinClass:aClass fileName:classFileName directory:packageDir module:moduleDir source:sourceFile logMessage:logMessage force:force
"Return true if ok, false if not."
- |dbConnection|
-
- dbConnection := self dbHandleForModule:moduleDir.
- [
- |collectedVersionSpec hashKey|
-
- collectedVersionSpec := self checkInClassAndCollectManifestOf:aClass db:dbConnection.
- hashKey := self keyForChunk:collectedVersionSpec.
-
- dbConnection
- executeQuery:(
- 'insert into chunks values (''%1'', ''%2'')'
- bindWith:hashKey
- with:(collectedVersionSpec withCEscapes copyReplaceString:'''' withString:'''''')).
- ] ensure:[
- dbConnection close
- ].
-
- ^ true.
+ self halt:'should not be called (not need for a classFile)'
!
createModule:moduleDir
@@ -481,19 +583,23 @@
"Created: / 21-12-2011 / 18:14:03 / cg"
!
-revisionInfoFromString:aString
+revisionInfoFromString:aString
"{ Pragma: +optSpace }"
"return a VersionInfo object filled with revision info.
This extracts the relevant info from aString."
- ^ self revisionInfoFromStandardVersionString:aString
+ |info versionName|
+
+ info := self revisionInfoFromStandardVersionString:aString.
+
+ versionName := self extractKeyValueFor:'SymbolicVersion' fromRevisionString:aString.
+ info symbolicVersionName:versionName.
+ ^ info
"
- self revisionInfoFromString:'Path: stx/libbasic/Array.st, Version: 123, User: cg, Time: 2011-12-21T21:03:08.826'
+ self revisionInfoFromString:'Path: stx/libbasic/Array.st, Version: 123, User: cg, Time: 2011-12-21T21:03:08.826 SymbolicVersion: foo'
"
-
- "Created: / 21-12-2011 / 14:50:12 / cg"
!
revisionLogOf:clsOrNil
@@ -572,15 +678,72 @@
"/ ^ oldFile readStream
"Created: / 21-12-2011 / 20:49:01 / cg"
+!
+
+updateVersionMethodOf:aClass for:newRevisionString
+ "{ Pragma: +optSpace }"
+
+ "helper for the checkin procedure.
+ Update my #version_XXX method, to now return newRevisionString."
+
+ self updateVersionMethod:(self nameOfVersionMethodInClasses) of:aClass for:newRevisionString.
+! !
+
+!DataBaseSourceCodeManager::DBVersionInfo class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 2014 by eXept Software AG
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+documentation
+"
+ In ancient times, Class used to return a Dictionary when asked for versionInfo.
+ This has been replaced by instances of VersionInfo and subclasses.
+
+ DBVersionInfo adds some DataBaseManager specific data.
+
+ [author:]
+ cg
+"
+! !
+
+!DataBaseSourceCodeManager::DBVersionInfo methodsFor:'accessing'!
+
+state
+ ^ state
+!
+
+state:something
+ state := something.
+!
+
+symbolicVersionName
+ "return an additional symbolic version name, which is used for human readers (and not unique)"
+
+ ^ symbolicVersionName ? revision
+!
+
+symbolicVersionName:aString
+ symbolicVersionName := aString.
! !
!DataBaseSourceCodeManager class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic3/DataBaseSourceCodeManager.st,v 1.12 2014-07-21 11:26:10 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic3/DataBaseSourceCodeManager.st,v 1.13 2014-11-29 02:30:39 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic3/DataBaseSourceCodeManager.st,v 1.12 2014-07-21 11:26:10 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic3/DataBaseSourceCodeManager.st,v 1.13 2014-11-29 02:30:39 cg Exp $'
! !