Skip to content

Commit 77bc1c6

Browse files
committed
Added tests for merges and conflicts
1 parent 0d8b41b commit 77bc1c6

File tree

2 files changed

+113
-4
lines changed

2 files changed

+113
-4
lines changed

bizarro/repo.py

+24-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import os, logging
22
from os.path import join, split
33

4+
class MergeConflict (Exception):
5+
def __init__(self, remote_tree, local_tree):
6+
pass
7+
48
def start_branch(clone, default_branch_name, new_branch_name):
59
''' Start a new repository branch, push it to origin and return it.
610
'''
@@ -11,8 +15,9 @@ def start_branch(clone, default_branch_name, new_branch_name):
1115
else:
1216
start_point = clone.branches[default_branch_name].commit
1317

18+
# Start or update the branch, letting origin override the local repo.
1419
logging.debug('start_branch() start_point is %s' % repr(start_point))
15-
branch = clone.create_head(new_branch_name, commit=start_point)
20+
branch = clone.create_head(new_branch_name, commit=start_point, force=True)
1621
clone.remotes.origin.push(new_branch_name)
1722

1823
return branch
@@ -49,11 +54,26 @@ def make_working_file(clone, dir, path):
4954
return repo_path, real_path
5055

5156
def save_working_file(clone, path, message, base_sha):
52-
''' Save a file in the working dir and push it to origin.
57+
''' Save a file in the working dir, push it to origin, and return the commit.
5358
'''
5459
if clone.active_branch.commit.hexsha != base_sha:
5560
raise Exception('Out of date SHA: %s' % base_sha)
5661

5762
clone.index.add([path])
58-
clone.index.commit(message)
59-
clone.remotes.origin.push(clone.active_branch.name)
63+
new_commit = clone.index.commit(message)
64+
branch_name = clone.active_branch.name
65+
66+
try:
67+
# sync: pull --rebase followed by push.
68+
clone.remotes.origin.pull(branch_name, rebase=True)
69+
70+
except AssertionError:
71+
# raise the two trees in conflict.
72+
clone.remotes.origin.fetch()
73+
remote_tree = clone.refs['origin/' + branch_name].commit.tree
74+
raise MergeConflict(remote_tree, new_commit.tree)
75+
76+
else:
77+
clone.remotes.origin.push(clone.active_branch.name)
78+
79+
return clone.active_branch.commit

test.py

+89
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ def test_repo_features(self):
3535
self.assertEqual(set(branch_names), set(['master', 'title', 'body']))
3636

3737
def test_start_branch(self):
38+
''' Make a simple edit in a clone, verify that it appears in the other.
39+
'''
3840
name = str(uuid4())
3941
branch1 = bizarro.repo.start_branch(self.clone1, 'master', name)
4042

@@ -62,6 +64,8 @@ def test_start_branch(self):
6264
self.assertEquals(branch2.commit.message, message)
6365

6466
def test_new_file(self):
67+
''' Make a new file in a clone, verify that it appears in the other.
68+
'''
6569
name = str(uuid4())
6670
branch1 = bizarro.repo.start_branch(self.clone1, 'master', name)
6771

@@ -98,6 +102,91 @@ def test_new_file(self):
98102
self.assertEquals(front['title'], 'Hello')
99103
self.assertEquals(body, 'Hello hello.')
100104

105+
def test_simple_merge(self):
106+
''' Test that two simultaneous non-conflicting changes merge cleanly.
107+
'''
108+
name = str(uuid4())
109+
branch1 = bizarro.repo.start_branch(self.clone1, 'master', name)
110+
branch2 = bizarro.repo.start_branch(self.clone2, 'master', name)
111+
112+
#
113+
# Make a new files in each branch and save them.
114+
#
115+
branch1.checkout()
116+
branch2.checkout()
117+
118+
repo_path1, real_path1 = bizarro.repo.make_working_file(self.clone1, '', 'file1.md')
119+
repo_path2, real_path2 = bizarro.repo.make_working_file(self.clone2, '', 'file2.md')
120+
121+
with open(real_path1, 'w') as file:
122+
jekyll.dump_jekyll_doc(dict(title='Hello'), 'Hello hello.', file)
123+
124+
with open(real_path2, 'w') as file:
125+
jekyll.dump_jekyll_doc(dict(title='Goodbye'), 'Goodbye goodbye.', file)
126+
127+
#
128+
# Show that the changes from the first branch made it to origin.
129+
#
130+
args1 = self.clone1, 'file1.md', 'Saving', branch1.commit.hexsha
131+
commit1 = bizarro.repo.save_working_file(*args1)
132+
133+
self.assertEquals(self.origin.branches[name].commit, commit1)
134+
self.assertEquals(commit1, branch1.commit)
135+
136+
#
137+
# Show that the changes from the second branch also made it to origin.
138+
#
139+
args2 = self.clone2, 'file2.md', 'Saving', branch2.commit.hexsha
140+
commit2 = bizarro.repo.save_working_file(*args2)
141+
142+
self.assertEquals(self.origin.branches[name].commit, commit2)
143+
self.assertEquals(commit2, branch2.commit)
144+
145+
#
146+
# Show that the merge from the second branch made it back to the first.
147+
#
148+
branch1b = bizarro.repo.start_branch(self.clone1, 'master', name)
149+
150+
self.assertEquals(branch1b.commit, branch2.commit)
151+
152+
def test_simple_conflict(self):
153+
''' Test that a conflict in two branches appears at the right spot.
154+
'''
155+
name = str(uuid4())
156+
branch1 = bizarro.repo.start_branch(self.clone1, 'master', name)
157+
branch2 = bizarro.repo.start_branch(self.clone2, 'master', name)
158+
159+
#
160+
# Make a new files in each branch and save them.
161+
#
162+
branch1.checkout()
163+
branch2.checkout()
164+
165+
repo_path1, real_path1 = bizarro.repo.make_working_file(self.clone1, '', 'conflict.md')
166+
repo_path2, real_path2 = bizarro.repo.make_working_file(self.clone2, '', 'conflict.md')
167+
168+
with open(real_path1, 'w') as file:
169+
jekyll.dump_jekyll_doc(dict(title='Hello'), 'Hello hello.', file)
170+
171+
with open(real_path2, 'w') as file:
172+
jekyll.dump_jekyll_doc(dict(title='Goodbye'), 'Goodbye goodbye.', file)
173+
174+
#
175+
# Show that the changes from the first branch made it to origin.
176+
#
177+
args1 = self.clone1, 'conflict.md', 'Saving', branch1.commit.hexsha
178+
commit1 = bizarro.repo.save_working_file(*args1)
179+
180+
self.assertEquals(self.origin.branches[name].commit, commit1)
181+
self.assertEquals(commit1, branch1.commit)
182+
183+
#
184+
# Show that the changes from the second branch conflict with the first.
185+
#
186+
with self.assertRaises(bizarro.repo.MergeConflict):
187+
args2 = self.clone2, 'conflict.md', 'Saving', branch2.commit.hexsha
188+
commit2 = bizarro.repo.save_working_file(*args2)
189+
101190
def tearDown(self):
102191
rmtree(self.origin.git_dir)
103192
rmtree(self.clone1.working_dir)

0 commit comments

Comments
 (0)