8
8
tig diff
9
9
tig log
10
10
tig branch
11
+ tig merge <branch>
11
12
12
13
Options:
13
14
-b <branch-name> Branch name to checkout.
21
22
import hashlib
22
23
import json
23
24
import time
25
+ import tempfile
26
+ import subprocess
24
27
25
28
26
29
def __sha1 (content ):
@@ -106,24 +109,28 @@ def branch():
106
109
print "{0}{1}" .format (star , branch )
107
110
108
111
112
+ def __create_commit (content_sha1sum , parents , msg ):
113
+ sha1sum_commit = __storedb (json .dumps ({
114
+ "content" : content_sha1sum ,
115
+ "parent" : parents ,
116
+ "log-msg" : msg ,
117
+ "author" : os .getenv ("USER" ),
118
+ "time" : int (time .time ())
119
+ }, indent = 4 ))
120
+ return sha1sum_commit
121
+
122
+
109
123
def commit (msg ):
110
124
branch = __get_current_branch ()
111
125
if branch == None :
112
126
print "tig: not at tip"
113
127
return
114
128
115
129
master_rev = __get_branch_commit (branch )
116
-
117
130
sha1sum_content = __storedb (__read_file ("file.txt" ))
118
- sha1sum_commit = __storedb (json .dumps ({
119
- "content" : sha1sum_content ,
120
- "parent" : master_rev ,
121
- "log-msg" : msg ,
122
- "author" : os .getenv ("USER" ),
123
- "time" : int (time .time ())
124
- }, indent = 4 ))
125
-
131
+ sha1sum_commit = __create_commit (sha1sum_content , [master_rev ], msg )
126
132
__set_branch_commit (branch , sha1sum_commit )
133
+
127
134
print sha1sum_commit
128
135
129
136
@@ -138,12 +145,16 @@ def __commit_from_start_point(start_point):
138
145
return start_point
139
146
140
147
141
- def checkout (start_point , new_branch ):
148
+ def __update_working_copy (start_point ):
142
149
commit_sha1sum = __commit_from_start_point (start_point )
143
150
content_sha1sum = __content_from_commit (commit_sha1sum )
144
151
content = __getdb (content_sha1sum )
145
152
146
153
__write_file ("file.txt" , content )
154
+ return commit_sha1sum
155
+
156
+ def checkout (start_point , new_branch ):
157
+ commit_sha1sum = __update_working_copy (start_point )
147
158
148
159
if new_branch is None :
149
160
__set_head (start_point )
@@ -172,11 +183,98 @@ def log():
172
183
while True :
173
184
commit = json .loads (__getdb (commit_sha1sum ))
174
185
print commit_sha1sum [:6 ], commit ["log-msg" ]
175
- commit_sha1sum = commit ["parent" ]
186
+ commit_sha1sum = commit ["parent" ][ 0 ]
176
187
if commit_sha1sum == "0" :
177
188
break
178
189
179
190
191
+ def __get_common_ancestor (commit1 , commit2 ):
192
+ if commit1 == commit2 :
193
+ return
194
+
195
+ ancestors1 = [commit1 ]
196
+ ancestors2 = [commit2 ]
197
+
198
+ while True :
199
+ commit_obj = json .loads (__getdb (commit1 ))
200
+ parent_commit = commit_obj ["parent" ][0 ]
201
+ if parent_commit in ancestors2 :
202
+ return parent_commit
203
+
204
+ ancestors1 .append (parent_commit )
205
+ commit1 = parent_commit
206
+
207
+ commit_obj = json .loads (__getdb (commit2 ))
208
+ parent_commit = commit_obj ["parent" ][0 ]
209
+ if parent_commit in ancestors1 :
210
+ return parent_commit
211
+
212
+ ancestors2 .append (parent_commit )
213
+ commit2 = parent_commit
214
+
215
+ return None
216
+
217
+
218
+ def __diff3 (mine_sha1sum , orig_sha1sum , your_sha1sum ):
219
+ tmpdir = tempfile .mkdtemp ()
220
+
221
+ diff3_files = [("mine" , mine_sha1sum ),
222
+ ("orig" , orig_sha1sum ),
223
+ ("your" , your_sha1sum )]
224
+
225
+ for filename , sha1sum in diff3_files :
226
+ path = os .path .join (tmpdir , filename )
227
+ content_sha1sum = __content_from_commit (sha1sum )
228
+ __write_file (path , __getdb (content_sha1sum ))
229
+
230
+ conflicted = False
231
+ merged_path = os .path .join (tmpdir , "merged" )
232
+ with open (merged_path , "w" ) as merged_file :
233
+ ret = subprocess .call (["diff3" , "-A" , "-m" , "mine" , "orig" , "your" ],
234
+ cwd = tmpdir , stdout = merged_file )
235
+ if ret != 0 :
236
+ conflicted = True
237
+
238
+ return __read_file (os .path .join (merged_path )), conflicted
239
+
240
+
241
+ def merge (branch ):
242
+ mine_sha1sum = __get_head_commit ()
243
+ your_sha1sum = __get_branch_commit (branch )
244
+
245
+ ca_sha1sum = __get_common_ancestor (mine_sha1sum , your_sha1sum )
246
+ if not ca_sha1sum :
247
+ print "tig: failed to find common ancestor"
248
+ return
249
+
250
+ if ca_sha1sum == your_sha1sum :
251
+ print "tig: up-to-date"
252
+ return
253
+
254
+ if ca_sha1sum == mine_sha1sum :
255
+ print "tig: fast-forward merge"
256
+ mine_branch = __get_current_branch ()
257
+ __set_branch_commit (mine_branch , your_sha1sum )
258
+ __update_working_copy (mine_branch )
259
+ return
260
+
261
+ # True Merge
262
+ merged , conflicted = __diff3 (mine_sha1sum , ca_sha1sum , your_sha1sum )
263
+ __write_file ("file.txt" , merged )
264
+
265
+ if not conflicted :
266
+ content_sha1sum = __storedb (merged )
267
+ commit_sha1sum = __create_commit (content_sha1sum ,
268
+ [mine_sha1sum , your_sha1sum ],
269
+ "Merged changes from '{0}'" .format (branch ))
270
+ mine_branch = __get_current_branch ()
271
+ __set_branch_commit (mine_branch , commit_sha1sum )
272
+ print commit_sha1sum
273
+ else :
274
+ # FIXME: This needs to be handled.
275
+ print "tig: merge conflict occurred"
276
+
277
+
180
278
def main ():
181
279
args = docopt .docopt (__doc__ )
182
280
if args ["commit" ]:
@@ -191,6 +289,8 @@ def main():
191
289
log ()
192
290
elif args ["branch" ]:
193
291
branch ()
292
+ elif args ["merge" ]:
293
+ merge (args ["<branch>" ])
194
294
else :
195
295
# Not reached
196
296
pass
0 commit comments