1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
package git
/*
#include <git2.h>
*/
import "C"
import (
"errors"
"runtime"
"unsafe"
)
// RebaseOperationType is the type of rebase operation
type RebaseOperationType uint
const (
// RebaseOperationPick The given commit is to be cherry-picked. The client should commit the changes and continue if there are no conflicts.
RebaseOperationPick RebaseOperationType = C.GIT_REBASE_OPERATION_PICK
// RebaseOperationEdit The given commit is to be cherry-picked, but the client should stop to allow the user to edit the changes before committing them.
RebaseOperationEdit RebaseOperationType = C.GIT_REBASE_OPERATION_EDIT
// RebaseOperationSquash The given commit is to be squashed into the previous commit. The commit message will be merged with the previous message.
RebaseOperationSquash RebaseOperationType = C.GIT_REBASE_OPERATION_SQUASH
// RebaseOperationFixup No commit will be cherry-picked. The client should run the given command and (if successful) continue.
RebaseOperationFixup RebaseOperationType = C.GIT_REBASE_OPERATION_FIXUP
// RebaseOperationExec No commit will be cherry-picked. The client should run the given command and (if successful) continue.
RebaseOperationExec RebaseOperationType = C.GIT_REBASE_OPERATION_EXEC
)
// RebaseOperation describes a single instruction/operation to be performed during the rebase.
type RebaseOperation struct {
Type RebaseOperationType
ID *Oid
Exec string
}
func rebaseOperationFromC(c *C.git_rebase_operation) *RebaseOperation {
operation := &RebaseOperation{}
operation.Type = RebaseOperationType(c._type)
operation.ID = newOidFromC(&c.id)
operation.Exec = C.GoString(c.exec)
return operation
}
// RebaseOptions are used to tell the rebase machinery how to operate
type RebaseOptions struct{}
// Rebase object wrapper for C pointer
type Rebase struct {
ptr *C.git_rebase
}
//RebaseInit initializes a rebase operation to rebase the changes in branch relative to upstream onto another branch.
func (r *Repository) RebaseInit(branch *AnnotatedCommit, upstream *AnnotatedCommit, onto *AnnotatedCommit, opts *RebaseOptions) (*Rebase, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
//TODO : use real rebase_options
if opts != nil {
return nil, errors.New("RebaseOptions Not implemented yet")
}
if branch == nil {
branch = &AnnotatedCommit{ptr: nil}
}
if upstream == nil {
upstream = &AnnotatedCommit{ptr: nil}
}
if onto == nil {
onto = &AnnotatedCommit{ptr: nil}
}
var ptr *C.git_rebase
err := C.git_rebase_init(&ptr, r.ptr, branch.ptr, upstream.ptr, onto.ptr, nil)
if err < 0 {
return nil, MakeGitError(err)
}
return newRebaseFromC(ptr), nil
}
// Next performs the next rebase operation and returns the information about it.
// If the operation is one that applies a patch (which is any operation except GIT_REBASE_OPERATION_EXEC)
// then the patch will be applied and the index and working directory will be updated with the changes.
// If there are conflicts, you will need to address those before committing the changes.
func (rebase *Rebase) Next() (*RebaseOperation, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var ptr *C.git_rebase_operation
err := C.git_rebase_next(&ptr, rebase.ptr)
if err < 0 {
return nil, MakeGitError(err)
}
return rebaseOperationFromC(ptr), nil
}
// Commit commits the current patch.
// You must have resolved any conflicts that were introduced during the patch application from the git_rebase_next invocation.
func (rebase *Rebase) Commit(ID *Oid, author, committer *Signature, message string) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
authorSig, err := author.toC()
if err != nil {
return err
}
defer C.git_signature_free(authorSig)
committerSig, err := committer.toC()
if err != nil {
return err
}
cmsg := C.CString(message)
defer C.free(unsafe.Pointer(cmsg))
cerr := C.git_rebase_commit(ID.toC(), rebase.ptr, authorSig, committerSig, nil, cmsg)
if cerr < 0 {
return MakeGitError(cerr)
}
return nil
}
// Finish finishes a rebase that is currently in progress once all patches have been applied.
func (rebase *Rebase) Finish() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
err := C.git_rebase_finish(rebase.ptr, nil)
if err < 0 {
return MakeGitError(err)
}
return nil
}
//Free frees the Rebase object and underlying git_rebase C pointer.
func (rebase *Rebase) Free() {
runtime.SetFinalizer(rebase, nil)
C.git_reference_free(rebase.ptr)
}
func newRebaseFromC(ptr *C.git_rebase) *Rebase {
rebase := &Rebase{ptr: ptr}
runtime.SetFinalizer(rebase, (*Rebase).Free)
return rebase
}
|