- GitPrimitives
changed:
#prim_git_remote_list:repo:
#prim_git_strarray_copy:src:
#prim_git_strarray_free:
- GitLibraryObject
added: #documentation
comment/format in:
#getHandleClass
#setHandleFromRef:
- GitCommand
added:42 methods
category of:
- GitRepository
class definition
added:6 methods
category of:
- stx_libscm_git
changed:
#classNamesAndAttributes
#extensionMethodNames
#preRequisites
- GitStringArray
class definition
added:7 methods
changed:
#count
#strings
category of:
#count
#count:
#strings
#strings:
- GitWorkingCopy
class definition
added: #repository
changed: #setRepository:
- GitObject
class definition
- GitRemote
added:7 methods
- GitRepositoryObject
added:6 methods
- GitTests
added: #test_02a
- GitStructure
added: #new
- GitWorkingCopyEntry
added: #isChanged
- extensions
...
"{ Package: 'stx:libscm/git' }"
GitLibraryObject subclass:#GitRepository
instanceVariableNames:'path workdir index remotes'
classVariableNames:''
poolDictionaries:'GitObjectType GitStatusCodes'
category:'SCM-Git-Model'
!
!GitRepository class methodsFor:'instance creation'!
clone: url to: stringOrDirectory
| dir ref fetchStats checkoutStats options |
(url asString startsWith: 'file://') ifTrue:[
"Arghhh...local transport not yet supported by libgit2, use command line..."
GitCommand clone: url to: stringOrDirectory pathName.
^self open: stringOrDirectory pathName
].
dir := stringOrDirectory asFilename.
dir exists ifTrue:[
GitError raiseErrorString:'Destination directory already exists'.
^self
].
dir directory isDirectory ifFalse:[
GitError raiseErrorString:'Parent directory for destination does not exists'.
^self
].
ref := ByteArray new: ExternalBytes sizeofPointer.
fetchStats := GitIndexerStatsStructure new.
checkoutStats := GitIndexerStatsStructure new.
options := GitCheckoutOptions new.
options strategyCreateMissing.
GitError raiseIfError:
(GitPrimitives prim_git_clone: ref origin_url: url asString workdir_path: dir pathName fetch_stats: fetchStats checkout_stats: checkoutStats checkout_opts: options).
^self new
setHandleFromRef:ref;
setPath: dir pathName;
yourself
"Created: / 01-10-2012 / 00:09:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
open: aString
"Opens an existing git repository on given path"
| ref |
ref := ByteArray new: ExternalBytes sizeofPointer.
GitError raiseIfError: (GitPrimitives prim_git_repository_open: ref path: aString).
^self new
setHandleFromRef:ref;
setPath: aString;
yourself
"Created: / 07-09-2012 / 23:45:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository class methodsFor:'accessing'!
structSize
"Returns size of undelaying structure in bytes"
^0
! !
!GitRepository methodsFor:'accessing'!
head
| ref err |
ref := ByteArray new: ExternalBytes sizeofPointer.
err := GitPrimitives prim_git_repository_head: ref repo: handle.
GitError raiseIfError: err.
^GitReference new setHandleFromRef: ref
"Created: / 25-09-2012 / 10:48:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
path
^ path
!
remotes
remotes isNil ifTrue:[
| list |
list := GitStringArray new.
GitError raiseIfError:(GitPrimitives prim_git_remote_list: list repo: handle).
remotes := Dictionary new.
list do:[:name|
remotes at: name put: (self remoteNamed: name)
].
].
^remotes.
"Created: / 30-09-2012 / 20:15:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
workingCopy
self isBare ifTrue:[
GitError raiseErrorString: 'Repository is bare'.
].
^GitWorkingCopy new setRepository: self
"Created: / 19-09-2012 / 15:32:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
workingCopyOn: aStringOrFilename
| repo directory |
directory := aStringOrFilename asFilename.
directory exists ifFalse:[
[ directory recursiveMakeDirectory ] on: Error do:[:cause|
GitError new
parameter: cause;
messageText: 'Cannot create directory for working copy';
raise.
]
] ifTrue:[
directory isDirectory ifFalse:[
GitError raiseErrorString: 'Given directory is not a directory'.
]
].
repo := self workdir = aStringOrFilename asFilename
ifTrue:[self]
ifFalse:[self copy workdir: aStringOrFilename asString update: false].
^GitWorkingCopy new setRepository: repo
"Created: / 19-09-2012 / 09:48:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository methodsFor:'actions'!
commit: message tree: tree parents: parents update: refOrNil commiter: commiterOrNil author: authorOrNil
| oid err committer author parentsA |
committer := commiterOrNil notNil
ifTrue:[committer copyNow]
ifFalse:[GitCommitterQuery query copyNow].
author := commiterOrNil notNil
ifTrue:[author]
ifFalse:[committer copy].
parentsA := ByteArray new: (ExternalBytes sizeofPointer * parents size).
parents withIndexDo:[:each :idx|
parentsA pointerAt: (1 + ((idx - 1) * ExternalBytes sizeofPointer)) put: each getHandle.
].
oid := GitOid new.
err := GitPrimitives prim_git_commit_create: oid
repo: handle
update_ref: (refOrNil notNil ifTrue:[refOrNil name] ifFalse:[nil])
author: author getHandle
committer: committer getHandle
message_encoding: 'utf-8'
message: message utf8Encoded
tree: tree getHandle
parent_count: parents size
parents: parentsA.
GitError raiseIfError: err.
^self lookup: oid type: OBJ_COMMIT.
"Created: / 25-09-2012 / 14:51:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
push: aGitRemote
"pushes all changes to given remote repository"
GitCommand push
remote: aGitRemote name;
execute
"Created: / 30-09-2012 / 23:46:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository methodsFor:'copying'!
cloneTo: aStringOrFilename"^<GitRepository>"
"Clones the receiver to given directory. And equivalent to
git clone <path> <clonePath>
"
^GitRepository
clone: ('file://', self path )
to: (aStringOrFilename)
"Created: / 30-09-2012 / 19:07:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
shallowCopy
^self class open: path
"Created: / 10-09-2012 / 19:04:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository methodsFor:'initialization'!
setPath: aString
path := aString
"Created: / 10-09-2012 / 19:05:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository methodsFor:'initialization & release'!
free
handle notNil ifTrue:[
GitPrimitives prim_git_object_free: handle.
handle := nil.
].
"Created: / 17-09-2012 / 21:16:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository methodsFor:'lookup'!
lookup: oid
"Lookup an object with given OID"
^self lookup: oid type: OBJ_ANY
"Created: / 10-09-2012 / 10:53:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
lookup: oid type: typeId
"Lookup an object with given OID"
| ref err type obj |
oid class == GitOid ifFalse:[
self error: 'Passed oid is not a GitOid'.
^nil.
].
ref := ByteArray new: ExternalBytes sizeofPointer.
err := GitPrimitives prim_git_object_lookup: ref repo: handle id: oid type: typeId.
GitError raiseIfError: err.
typeId == OBJ_ANY ifTrue:[
obj := ExternalAddress new setAddressFromBytes:ref.
type := GitPrimitives prim_git_object_type: obj.
] ifFalse:[
type := typeId.
].
obj := GitObject newForType: type.
^obj
setHandleFromRef: ref;
setOid: oid;
setRepository: self;
yourself
"Created: / 10-09-2012 / 11:01:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository methodsFor:'private'!
checkout: object
| err stats options |
object isGitTreeish ifFalse:[
GitError raiseErrorString:'Invalid argument: ', object printString.
^self.
].
stats := GitIndexerStatsStructure new.
options := GitCheckoutOptions new.
options strategyCreateMissing.
err := GitPrimitives prim_git_checkout_tree: handle treeish: object getHandle opts: options stats: stats.
GitError raiseIfError: err.
"Created: / 19-09-2012 / 09:52:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository methodsFor:'private-accessing'!
getHandleClass
^GitRepositoryHandle
"Created: / 17-09-2012 / 21:20:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
remoteNamed: name
| ref err |
ref := ByteArray new: ExternalBytes sizeofPointer.
err := GitPrimitives prim_git_remote_load: ref repo: handle name: name.
GitError raiseIfError: err.
^GitRemote new
setHandleFromRef: ref;
setRepository: self;
setName: name
"Created: / 30-09-2012 / 20:16:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
statusOf: aFilename
| ref err |
(aFilename pathName startsWith: self workdir pathName ) ifFalse:[
GitError raiseErrorString: 'Given path is within working copy'.
^0.
].
ref := ByteArray new: ExternalBytes sizeofInt.
err := GitPrimitives prim_git_status_file: ref repo: handle path: (aFilename pathName copyFrom: (workdir pathName size + 2)).
GitError raiseIfError: err.
^ref longAt:1
"Created: / 24-09-2012 / 22:27:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
workdir
"Get the path of the working directory for this repository or nil, if
repository is bare"
self isBare ifTrue: [ ^ nil ].
workdir isNil ifTrue:[
workdir := GitPrimitives prim_git_repository_workdir: handle.
workdir := workdir asFilename.
].
^workdir
"Created: / 10-09-2012 / 19:07:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
workdir: aStringOrFilename update: aBoolean
"Set the path of the working directory for this repository.
If update is true, then create/update gitlink in workdir and set
config 'core.worktree' (if workdir is not the parent of the
.git directory)"
GitError raiseIfError:
(GitPrimitives prim_git_repository_set_workdir: handle
workdir: aStringOrFilename asString
update_gitlink: (aBoolean ifTrue:[1] ifFalse:[0])).
workdir := aStringOrFilename asFilename.
"Created: / 10-09-2012 / 19:19:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository methodsFor:'testing'!
headIsDetached
^(GitPrimitives prim_git_repository_head_detached: handle) == 1
"Created: / 25-09-2012 / 11:06:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
headIsOrphan
^(GitPrimitives prim_git_repository_head_orphan: handle) == 1
"Created: / 25-09-2012 / 11:06:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
isBare
"Check if a repository is bare"
^(GitPrimitives prim_git_repository_is_bare: handle) == 1
"Created: / 10-09-2012 / 19:11:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
isEmpty
"An empty repository has just been initialized and contains
no commits."
^(GitPrimitives prim_git_repository_is_empty: self) == 1
"Created: / 10-09-2012 / 19:12:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GitRepository class methodsFor:'documentation'!
version_SVN
^ '$Id:: $'
! !