Browse Source

Merge "List changed files for all commits between refs"

tags/3.6.0
Zuul 2 months ago
parent
commit
affc25d189
3 changed files with 86 additions and 20 deletions
  1. 14
    9
      tests/base.py
  2. 66
    0
      tests/unit/test_merger_repo.py
  3. 6
    11
      zuul/merger/merger.py

+ 14
- 9
tests/base.py View File

@@ -2934,10 +2934,10 @@ class ZuulTestCase(BaseTestCase):
2934 2934
         zuul.merger.merger.reset_repo_to_head(repo)
2935 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 2938
         path = os.path.join(self.upstream_root, project)
2939 2939
         repo = git.Repo(path)
2940
-        fn = os.path.join(path, 'README')
2940
+        fn = os.path.join(path, commit_filename)
2941 2941
 
2942 2942
         branch_head = repo.create_head(branch)
2943 2943
         repo.head.reference = branch_head
@@ -2958,15 +2958,20 @@ class ZuulTestCase(BaseTestCase):
2958 2958
         zuul.merger.merger.reset_repo_to_head(repo)
2959 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 2963
         path = os.path.join(self.upstream_root, project)
2963 2964
         repo = git.Repo(path)
2964
-        repo.head.reference = repo.heads['master']
2965
-        file_name = os.path.join(path, 'README')
2966
-        with open(file_name, 'a') as f:
2967
-            f.write('creating fake commit\n')
2968
-        repo.index.add([file_name])
2969
-        commit = repo.index.commit('Creating a fake commit')
2965
+        repo.head.reference = repo.heads[head]
2966
+        repo.head.reset(index=True, working_tree=True)
2967
+
2968
+        files = files or {"README": "creating fake commit\n"}
2969
+        for name, content in files.items():
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 2975
         return commit.hexsha
2971 2976
 
2972 2977
     def orderedRelease(self, count=None):

+ 66
- 0
tests/unit/test_merger_repo.py View File

@@ -13,6 +13,7 @@
13 13
 # License for the specific language governing permissions and limitations
14 14
 # under the License.
15 15
 
16
+import datetime
16 17
 import logging
17 18
 import os
18 19
 
@@ -204,6 +205,71 @@ class TestMergerRepo(ZuulTestCase):
204 205
         # And now reset the repo again. This should not crash
205 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
 
208 274
 class TestMergerWithAuthUrl(ZuulTestCase):
209 275
     config_file = 'zuul-github-driver.conf'

+ 6
- 11
zuul/merger/merger.py View File

@@ -450,17 +450,12 @@ class Repo(object):
450 450
         head = repo.commit(self.revParse('FETCH_HEAD'))
451 451
         files = set()
452 452
 
453
-        merge_bases = []
454
-        if tosha is not None:
455
-            merge_bases = repo.merge_base(head, tosha)
456
-
457
-        files.update(set(head.stats.files.keys()))
458
-        if merge_bases:
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()))
453
+        if tosha:
454
+            commit_diff = "{}..{}".format(tosha, head.hexsha)
455
+            for cmt in repo.iter_commits(commit_diff, no_merges=True):
456
+                files.update(cmt.stats.files.keys())
457
+        else:
458
+            files.update(head.stats.files.keys())
464 459
         return list(files)
465 460
 
466 461
     def deleteRemote(self, remote):

Loading…
Cancel
Save