summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2019-03-07 16:18:41 +0000
committerGerrit Code Review <review@openstack.org>2019-03-07 16:18:41 +0000
commitaffc25d189feff6072d16408f914bf5703dfd13c (patch)
treec93fb8c5f2f0e06858f0f7a95947289851936090
parent4bf68a40a89a2b9578b66d19d7e8ce3a9d9014f4 (diff)
parentf88bf087c3947990e28a57bb034028d4a3ff95fe (diff)
Merge "List changed files for all commits between refs"
-rw-r--r--tests/base.py23
-rw-r--r--tests/unit/test_merger_repo.py66
-rw-r--r--zuul/merger/merger.py17
3 files changed, 86 insertions, 20 deletions
diff --git a/tests/base.py b/tests/base.py
index 3d7c457..7245537 100644
--- a/tests/base.py
+++ b/tests/base.py
@@ -2934,10 +2934,10 @@ class ZuulTestCase(BaseTestCase):
2934 zuul.merger.merger.reset_repo_to_head(repo) 2934 zuul.merger.merger.reset_repo_to_head(repo)
2935 repo.git.clean('-x', '-f', '-d') 2935 repo.git.clean('-x', '-f', '-d')
2936 2936
2937 def create_branch(self, project, branch): 2937 def create_branch(self, project, branch, commit_filename='README'):
2938 path = os.path.join(self.upstream_root, project) 2938 path = os.path.join(self.upstream_root, project)
2939 repo = git.Repo(path) 2939 repo = git.Repo(path)
2940 fn = os.path.join(path, 'README') 2940 fn = os.path.join(path, commit_filename)
2941 2941
2942 branch_head = repo.create_head(branch) 2942 branch_head = repo.create_head(branch)
2943 repo.head.reference = branch_head 2943 repo.head.reference = branch_head
@@ -2958,15 +2958,20 @@ class ZuulTestCase(BaseTestCase):
2958 zuul.merger.merger.reset_repo_to_head(repo) 2958 zuul.merger.merger.reset_repo_to_head(repo)
2959 repo.delete_head(repo.heads[branch], force=True) 2959 repo.delete_head(repo.heads[branch], force=True)
2960 2960
2961 def create_commit(self, project): 2961 def create_commit(self, project, files=None, head='master',
2962 message='Creating a fake commit', **kwargs):
2962 path = os.path.join(self.upstream_root, project) 2963 path = os.path.join(self.upstream_root, project)
2963 repo = git.Repo(path) 2964 repo = git.Repo(path)
2964 repo.head.reference = repo.heads['master'] 2965 repo.head.reference = repo.heads[head]
2965 file_name = os.path.join(path, 'README') 2966 repo.head.reset(index=True, working_tree=True)
2966 with open(file_name, 'a') as f: 2967
2967 f.write('creating fake commit\n') 2968 files = files or {"README": "creating fake commit\n"}
2968 repo.index.add([file_name]) 2969 for name, content in files.items():
2969 commit = repo.index.commit('Creating a fake commit') 2970 file_name = os.path.join(path, name)
2971 with open(file_name, 'a') as f:
2972 f.write(content)
2973 repo.index.add([file_name])
2974 commit = repo.index.commit(message, **kwargs)
2970 return commit.hexsha 2975 return commit.hexsha
2971 2976
2972 def orderedRelease(self, count=None): 2977 def orderedRelease(self, count=None):
diff --git a/tests/unit/test_merger_repo.py b/tests/unit/test_merger_repo.py
index 06c6314..86323e8 100644
--- a/tests/unit/test_merger_repo.py
+++ b/tests/unit/test_merger_repo.py
@@ -13,6 +13,7 @@
13# License for the specific language governing permissions and limitations 13# License for the specific language governing permissions and limitations
14# under the License. 14# under the License.
15 15
16import datetime
16import logging 17import logging
17import os 18import os
18 19
@@ -204,6 +205,71 @@ class TestMergerRepo(ZuulTestCase):
204 # And now reset the repo again. This should not crash 205 # And now reset the repo again. This should not crash
205 work_repo.reset() 206 work_repo.reset()
206 207
208 def test_files_changes(self):
209 parent_path = os.path.join(self.upstream_root, 'org/project1')
210 self.create_branch('org/project1', 'feature')
211
212 work_repo = Repo(parent_path, self.workspace_root,
213 'none@example.org', 'User Name', '0', '0')
214 changed_files = work_repo.getFilesChanges('feature', 'master')
215
216 self.assertEqual(['README'], changed_files)
217
218 def test_files_changes_master_fork_merges(self):
219 """Regression test for getFilesChanges()
220
221 Check if correct list of changed files is listed for a messy
222 branch that has a merge of a fork, with the fork including a
223 merge of a new master revision.
224
225 The previously used "git merge-base" approach did not handle this
226 case correctly.
227 """
228 parent_path = os.path.join(self.upstream_root, 'org/project1')
229 repo = git.Repo(parent_path)
230
231 self.create_branch('org/project1', 'messy',
232 commit_filename='messy1.txt')
233
234 # Let time pass to reproduce the order for this error case
235 commit_date = datetime.datetime.now() + datetime.timedelta(seconds=5)
236 commit_date = commit_date.replace(microsecond=0).isoformat()
237
238 # Create a commit on 'master' so we can merge it into the fork
239 files = {"master.txt": "master"}
240 master_ref = self.create_commit('org/project1', files=files,
241 message="Add master.txt",
242 commit_date=commit_date)
243 repo.refs.master.commit = master_ref
244
245 # Create a fork of the 'messy' branch and merge
246 # 'master' into the fork (no fast-forward)
247 repo.create_head("messy-fork")
248 repo.heads["messy-fork"].commit = "messy"
249 repo.head.reference = 'messy'
250 repo.head.reset(index=True, working_tree=True)
251 repo.git.checkout('messy-fork')
252 repo.git.merge('master', no_ff=True)
253
254 # Merge fork back into 'messy' branch (no fast-forward)
255 repo.head.reference = 'messy'
256 repo.head.reset(index=True, working_tree=True)
257 repo.git.checkout('messy')
258 repo.git.merge('messy-fork', no_ff=True)
259
260 # Create another commit on top of 'messy'
261 files = {"messy2.txt": "messy2"}
262 messy_ref = self.create_commit('org/project1', files=files,
263 head='messy', message="Add messy2.txt")
264 repo.refs.messy.commit = messy_ref
265
266 # Check that we get all changes for the 'messy' but not 'master' branch
267 work_repo = Repo(parent_path, self.workspace_root,
268 'none@example.org', 'User Name', '0', '0')
269 changed_files = work_repo.getFilesChanges('messy', 'master')
270 self.assertEqual(sorted(['messy1.txt', 'messy2.txt']),
271 sorted(changed_files))
272
207 273
208class TestMergerWithAuthUrl(ZuulTestCase): 274class TestMergerWithAuthUrl(ZuulTestCase):
209 config_file = 'zuul-github-driver.conf' 275 config_file = 'zuul-github-driver.conf'
diff --git a/zuul/merger/merger.py b/zuul/merger/merger.py
index c6eccaf..52757c6 100644
--- a/zuul/merger/merger.py
+++ b/zuul/merger/merger.py
@@ -450,17 +450,12 @@ class Repo(object):
450 head = repo.commit(self.revParse('FETCH_HEAD')) 450 head = repo.commit(self.revParse('FETCH_HEAD'))
451 files = set() 451 files = set()
452 452
453 merge_bases = [] 453 if tosha:
454 if tosha is not None: 454 commit_diff = "{}..{}".format(tosha, head.hexsha)
455 merge_bases = repo.merge_base(head, tosha) 455 for cmt in repo.iter_commits(commit_diff, no_merges=True):
456 456 files.update(cmt.stats.files.keys())
457 files.update(set(head.stats.files.keys())) 457 else:
458 if merge_bases: 458 files.update(head.stats.files.keys())
459 hexsha_list = [b.hexsha for b in merge_bases]
460 for cmt in head.iter_parents():
461 if cmt.hexsha in hexsha_list:
462 break
463 files.update(set(cmt.stats.files.keys()))
464 return list(files) 459 return list(files)
465 460
466 def deleteRemote(self, remote): 461 def deleteRemote(self, remote):