diff --git a/src/Fossil/FossilRepo.class.st b/src/Fossil/FossilRepo.class.st new file mode 100644 index 0000000..05a9b8f --- /dev/null +++ b/src/Fossil/FossilRepo.class.st @@ -0,0 +1,213 @@ +" +I model a fossil repository. For details about fossil see: + +http://fossil-scm.org/ + +The protocols are named following Smalltalk conventions, but +also after the Fossil JSON API documentation at [1] + +[1] https://docs.google.com/document/d/1fXViveNhDbiXgCuE7QDXQOKeFzf2qNUkBEgiUvoqFN4/view +" +Class { + #name : #FossilRepo, + #superclass : #Object, + #instVars : [ + 'local', + 'remote' + ], + #category : #Fossil +} + +{ #category : #authentication } +FossilRepo >> authTokenFor: anUserName withPassword: passwordString [ + ^ ((self loginAs: anUserName withPassword: passwordString) at: 'payload') at: 'authToken' +] + +{ #category : #authentication } +FossilRepo >> capabilities [ + | payload name permissions | + payload := self rawCapabilities at: 'payload'. + name := payload at: 'name'. + permissions := ((payload at: 'permissionFlags') select: [ :item | item value ]) keys. + ^ Dictionary new + at: 'name' put: name; + at: 'permissions' put: permissions; + yourself. +] + +{ #category : #querying } +FossilRepo >> checkinsFor: relativeFilePath [ + "I get all histotical checkins information for a full file name, wich includes relative path + in the repository (i.e: 'Doc/Es/Tutoriales/tutorial.ston' or 'index.html')" + | payload | + payload := (self jsonDataFor: relativeFilePath) at: 'payload' ifAbsent: [ + self inform: + 'WARNING! Key not found, verify the file name you are looking in this repository'. + ^ self ]. + ^ payload at: 'checkins' +] + +{ #category : #wiki } +FossilRepo >> createPage: pageName [ + ^ NeoJSONReader fromString: (self jsonWikiDataFor: 'create/', pageName) +] + +{ #category : #wiki } +FossilRepo >> fetchPage: pageName [ + ^ NeoJSONReader fromString: (self jsonWikiDataFor: 'get/', pageName) +] + +{ #category : #'as yet unclassified' } +FossilRepo >> getFileContentsFor: anEmbeddedDocUrl [ + "Given the web page contents for a file, hosted in Fossil, I detect all the standard + page decorations (chrome) and strip them to provide only file contents, contained between +
 HTML tags.."
+
+	| pageContentLines blockQuoteStart blockQuoteEnd fileContentLines fileContent |
+	pageContentLines := (self getPageContentsFor: anEmbeddedDocUrl) lines.
+	pageContentLines
+		doWithIndex: [ :line :index | 
+			line = '
'
+				ifTrue: [ blockQuoteStart := index ].
+			line = '
' + ifTrue: [ blockQuoteEnd := index ] ]. + fileContentLines := pageContentLines + copyFrom: blockQuoteStart + 1 + to: blockQuoteEnd - 1. + fileContent := WriteStream on: ''. + fileContentLines do: [ :line | fileContent nextPutAll: line; crlf ]. + ^ fileContent contents. +] + +{ #category : #utilities } +FossilRepo >> getPageContentsFor: anEmbeddedDocUrl [ + "I use the Fossil web interface to get the contents of a file. + I'm useful if the file is posted online, but the repository contents are + not locally available. + + anEmbeddedDocUrl should have the schema presented at: + + https://www.fossil-scm.org/xfer/doc/trunk/www/embeddeddoc.wiki" + + ^ (ZnEasy get: anEmbeddedDocUrl, '?mimetype=text/plain') contents. +] + +{ #category : #utilities } +FossilRepo >> isUnversioned: aFileNameWithRelativePath [ + + ^ (aFileNameWithRelativePath beginsWith: 'uv') +] + +{ #category : #utilities } +FossilRepo >> jsonDataFor: anUrlSegment [ + + ^ NeoJSONReader fromString: (self jsonStringFor: anUrlSegment) +] + +{ #category : #querying } +FossilRepo >> jsonStringFor: aFileName [ + | baseUrl queryForJSONData | + baseUrl := self remote addPathSegments: #('json' 'finfo'). + queryForJSONData := baseUrl queryAt: 'name' put: aFileName. + ^ (ZnEasy get: queryForJSONData) contents. +] + +{ #category : #wiki } +FossilRepo >> jsonWikiDataFor: anUrlSegment [ + ^ ZnClient new + get: (self wikiRoot addPathSegment: anUrlSegment); + contents. +] + +{ #category : #querying } +FossilRepo >> lastHashNumberFor: aFileName [ + "I'm useful to see if local versions of files are updated to the last versions of the + online repository" + ^ (self checkinsFor: aFileName) first at: 'uuid' +] + +{ #category : #utilities } +FossilRepo >> lastVersionPath: aFileNameWithRelativePath [ + "I dicern if my argument concerns to a versioned or an unversioned file, + and return a relative route to the last version of the file in the first + case or the unversioned one." + + (self isUnversioned: aFileNameWithRelativePath) + ifTrue: [ ^ '/', aFileNameWithRelativePath ] + ifFalse: [ ^ '/doc/tip/', aFileNameWithRelativePath ] +] + +{ #category : #accessing } +FossilRepo >> local [ + ^ local +] + +{ #category : #accessing } +FossilRepo >> local: aLocalFilePath [ + local := aLocalFilePath +] + +{ #category : #authentication } +FossilRepo >> loginAs: anUserName withPassword: password [ + | jsonData | + jsonData := ZnClient new + url: (self loginUrlWithName: anUserName andPassword: password); + get; + contents. + ^ NeoJSONReader fromString: jsonData +] + +{ #category : #authentication } +FossilRepo >> loginUrlWithName: aUser andPassword: passwd [ + ^ self jsonRoot + addPathSegment: 'login'; + queryAt: 'name' put: aUser; + queryAt: 'password' put: passwd. +] + +{ #category : #wiki } +FossilRepo >> pageList [ + ^ NeoJSONReader fromString: (self jsonWikiDataFor: 'list') +] + +{ #category : #authentication } +FossilRepo >> rawCapabilities [ + ^ NeoJSONReader fromString: (self jsonDataFor: 'cap') +] + +{ #category : #accessing } +FossilRepo >> remote [ + ^ remote +] + +{ #category : #accessing } +FossilRepo >> remote: anUrlString [ + remote := anUrlString asUrl +] + +{ #category : #utilities } +FossilRepo >> sanitize: aFileNameWithRelativePath [ + "I dicern if my argument concerns to a versioned or an unversioned file, + and return a relative path to put the file." + + (self isUnversioned: aFileNameWithRelativePath) + ifFalse: [ ^ aFileNameWithRelativePath ] + ifTrue: [ ^ (aFileNameWithRelativePath copyFrom: 4 to: aFileNameWithRelativePath size) ] +] + +{ #category : #authentication } +FossilRepo >> whoAmI [ + ^ NeoJSONReader fromString: (self jsonDataFor: 'whoami') +] + +{ #category : #wiki } +FossilRepo >> wikiRoot [ + ^ self remote + addPathSegments: #('json' 'wiki') + "addPathSegment: 'wiki' " +] + +{ #category : #wiki } +FossilRepo >> wikiTimeline [ + ^ NeoJSONReader fromString: (self jsonWikiDataFor: 'timeline') +] diff --git a/src/Fossil/package.st b/src/Fossil/package.st new file mode 100644 index 0000000..81c36eb --- /dev/null +++ b/src/Fossil/package.st @@ -0,0 +1 @@ +Package { #name : #Fossil }