Index: tests/git_rebase_update_test.py |
diff --git a/tests/git_rebase_update_test.py b/tests/git_rebase_update_test.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..f73eefe07bbfc6ec99f1a6484be20c0547ecbd5b |
--- /dev/null |
+++ b/tests/git_rebase_update_test.py |
@@ -0,0 +1,431 @@ |
+#!/usr/bin/env python |
+# Copyright 2013 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""Unit tests for git_rebase_update.py""" |
+ |
+import os |
+import sys |
+ |
+DEPOT_TOOLS_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
+sys.path.insert(0, DEPOT_TOOLS_ROOT) |
+ |
+from testing_support import coverage_utils |
+from testing_support import git_test_utils |
+ |
+class GitRebaseUpdateTest(git_test_utils.GitRepoReadWriteTestBase): |
+ REPO_SCHEMA = """ |
+ A B C D E F G |
+ B H I J K |
+ J L |
+ """ |
+ |
+ @classmethod |
+ def getRepoContent(cls, commit): |
+ # Every commit X gets a file X with the content X |
+ return {commit: {'data': commit}} |
+ |
+ @classmethod |
+ def setUpClass(cls): |
+ super(GitRebaseUpdateTest, cls).setUpClass() |
+ import git_rebase_update, git_new_branch, git_reparent_branch, git_common |
+ cls.reup = git_rebase_update |
+ cls.rp = git_reparent_branch |
+ cls.nb = git_new_branch |
+ cls.gc = git_common |
+ cls.gc.TEST_MODE = True |
+ |
+ def setUp(self): |
+ super(GitRebaseUpdateTest, self).setUp() |
+ # Include branch_K, branch_L to make sure that ABCDEFG all get the |
+ # same commit hashes as self.repo. Otherwise they get committed with the |
+ # wrong timestamps, due to commit ordering. |
+ # TODO(iannucci): Make commit timestamps deterministic in left to right, top |
+ # to bottom order, not in lexi-topographical order. |
+ origin_schema = git_test_utils.GitRepoSchema(""" |
+ A B C D E F G M N O |
+ B H I J K |
+ J L |
+ """, self.getRepoContent) |
+ self.origin = origin_schema.reify() |
+ self.origin.git('checkout', 'master') |
+ self.origin.git('branch', '-d', *['branch_'+l for l in 'KLG']) |
+ |
+ self.repo.git('remote', 'add', 'origin', self.origin.repo_path) |
+ self.repo.git('update-ref', 'refs/remotes/origin/master', 'tag_E') |
+ self.repo.git('branch', '--set-upstream-to', 'branch_G', 'branch_K') |
+ self.repo.git('branch', '--set-upstream-to', 'branch_K', 'branch_L') |
+ self.repo.git('branch', '--set-upstream-to', 'origin/master', 'branch_G') |
+ |
+ def tearDown(self): |
+ self.origin.nuke() |
+ super(GitRebaseUpdateTest, self).tearDown() |
+ |
+ def testRebaseUpdate(self): |
+ graphlines = lambda: [ |
+ l.strip() for l in self.repo.git( |
+ 'log', '--graph', '--format=%s', '--branches').stdout.splitlines() |
+ ] |
+ |
+ self.repo.git('checkout', 'branch_K') |
+ |
+ self.repo.run(self.nb.main, ['foobar']) |
+ self.assertEqual(self.repo.git('rev-parse', 'HEAD').stdout, |
+ self.repo.git('rev-parse', 'origin/master').stdout) |
+ |
+ with self.repo.open('foobar', 'w') as f: |
+ f.write('this is the foobar file') |
+ self.repo.git('add', 'foobar') |
+ self.repo.git_commit('foobar1') |
+ |
+ with self.repo.open('foobar', 'w') as f: |
+ f.write('totes the Foobar file') |
+ self.repo.git_commit('foobar2') |
+ |
+ self.repo.git('checkout', 'branch_K') |
+ self.repo.run(self.nb.main, ['--upstream_current', 'sub_K']) |
+ with self.repo.open('K', 'w') as f: |
+ f.write('This depends on K') |
+ self.repo.git_commit('sub_K') |
+ |
+ self.repo.run(self.nb.main, ['old_branch']) |
+ self.repo.git('reset', '--hard', self.repo['A']) |
+ with self.repo.open('old_file', 'w') as f: |
+ f.write('old_files we want to keep around') |
+ self.repo.git('add', 'old_file') |
+ self.repo.git_commit('old_file') |
+ self.repo.git('config', 'branch.old_branch.dormant', 'true') |
+ |
+ self.repo.git('checkout', 'origin/master') |
+ |
+ self.assertEqual( |
+ graphlines(), [ |
+ '* old_file', |
+ '| * sub_K', |
+ '| * K', |
+ '| | * foobar2', |
+ '| | * foobar1', |
+ '| | | * G', |
+ '| | | * F', |
+ '| | |/', |
+ '| | * E', |
+ '| | * D', |
+ '| | * C', |
+ '| | | * L', |
+ '| | |/', |
+ '| |/|', |
+ '| * | J', |
+ '| * | I', |
+ '| * | H', |
+ '| |/', |
+ '| * B', |
+ '|/', |
+ '* A' |
+ ] |
+ ) |
+ self.assertEquals(self.repo['A'], self.origin['A']) |
+ self.assertEquals(self.repo['E'], self.origin['E']) |
+ |
+ with self.repo.open('bob', 'wb') as f: |
+ f.write('testing auto-freeze/thaw') |
+ |
+ output, _ = self.repo.capture_stdio(self.reup.main) |
+ self.assertIn('Cannot rebase-update', output) |
+ |
+ self.repo.git('checkout', 'branch_K') |
+ |
+ output, _ = self.repo.capture_stdio(self.reup.main) |
+ |
+ self.assertIn('Rebasing: branch_G', output) |
+ self.assertIn('Rebasing: branch_K', output) |
+ self.assertIn('Rebasing: branch_L', output) |
+ self.assertIn('Rebasing: foobar', output) |
+ self.assertIn('Rebasing: sub_K', output) |
+ self.assertIn('Deleted branch branch_G', output) |
+ self.assertIn('Reparented branch_K to track origin/master', output) |
+ |
+ self.assertEqual( |
+ graphlines(), [ |
+ '* old_file', |
+ '| * sub_K', |
+ '| | * foobar2', |
+ '| | * foobar1', |
+ '| | | * L', |
+ '| | |/', |
+ '| |/|', |
+ '| * | K', |
+ '| * | J', |
+ '| * | I', |
+ '| * | H', |
+ '| |/', |
+ '| * O', |
+ '| * N', |
+ '| * M', |
+ '| * G', |
+ '| * F', |
+ '| * E', |
+ '| * D', |
+ '| * C', |
+ '| * B', |
+ '|/', |
+ '* A' |
+ ] |
+ ) |
+ |
+ output, _ = self.repo.capture_stdio(self.reup.main) |
+ self.assertIn('branch_K up-to-date', output) |
+ self.assertIn('branch_L up-to-date', output) |
+ self.assertIn('foobar up-to-date', output) |
+ self.assertIn('sub_K up-to-date', output) |
+ |
+ with self.repo.open('bob') as f: |
+ self.assertEquals('testing auto-freeze/thaw', f.read()) |
+ |
+ self.assertEqual(self.repo.git('status', '--porcelain').stdout, '?? bob\n') |
+ |
+ self.repo.git('checkout', 'origin/master') |
+ _, err = self.repo.capture_stdio(self.rp.main, ['foobar']) |
+ self.assertIn('Must be on the branch', err) |
+ |
+ self.repo.git('checkout', 'branch_K') |
+ _, err = self.repo.capture_stdio(self.rp.main, ['origin/master']) |
+ self.assertIn('Cannot reparent a branch to its existing parent', err) |
+ output, _ = self.repo.capture_stdio(self.rp.main, ['foobar']) |
+ self.assertIn('Rebasing: branch_K', output) |
+ self.assertIn('Rebasing: sub_K', output) |
+ self.assertIn('Rebasing: branch_L', output) |
+ |
+ self.assertEqual( |
+ graphlines(), [ |
+ '* old_file', |
+ '| * sub_K', |
+ '| | * L', |
+ '| |/', |
+ '| * K', |
+ '| * J', |
+ '| * I', |
+ '| * H', |
+ '| * foobar2', |
+ '| * foobar1', |
+ '| * O', |
+ '| * N', |
+ '| * M', |
+ '| * G', |
+ '| * F', |
+ '| * E', |
+ '| * D', |
+ '| * C', |
+ '| * B', |
+ '|/', |
+ '* A' |
+ ] |
+ ) |
+ |
+ self.repo.git('checkout', 'sub_K') |
+ output, _ = self.repo.capture_stdio(self.rp.main, ['foobar']) |
+ self.assertIn('Squashing failed', output) |
+ |
+ self.assertTrue(self.repo.run(self.gc.in_rebase)) |
+ |
+ self.repo.git('rebase', '--abort') |
+ self.repo.git('thaw') |
+ |
+ self.assertEqual( |
+ graphlines(), [ |
+ '* old_file', |
+ '| * sub_K', |
+ '| | * L', |
+ '| |/', |
+ '| * K', |
+ '| * J', |
+ '| * I', |
+ '| * H', |
+ '| * foobar2', |
+ '| * foobar1', |
+ '| * O', |
+ '| * N', |
+ '| * M', |
+ '| * G', |
+ '| * F', |
+ '| * E', |
+ '| * D', |
+ '| * C', |
+ '| * B', |
+ '|/', |
+ '* A' |
+ ] |
+ ) |
+ |
+ self.assertEqual(self.repo.git('status', '--porcelain').stdout, '?? bob\n') |
+ |
+ |
+ def testRebaseConflicts(self): |
+ # Pretend that branch_L landed |
+ self.origin.git('checkout', 'master') |
+ with self.origin.open('L', 'w') as f: |
+ f.write('L') |
+ self.origin.git('add', 'L') |
+ self.origin.git_commit('L') |
+ |
+ # Add a commit to branch_K so that things fail |
+ self.repo.git('checkout', 'branch_K') |
+ with self.repo.open('M', 'w') as f: |
+ f.write('NOPE') |
+ self.repo.git('add', 'M') |
+ self.repo.git_commit('K NOPE') |
+ |
+ # Add a commits to branch_L which will work when squashed |
+ self.repo.git('checkout', 'branch_L') |
+ self.repo.git('reset', 'branch_L~') |
+ with self.repo.open('L', 'w') as f: |
+ f.write('NOPE') |
+ self.repo.git('add', 'L') |
+ self.repo.git_commit('L NOPE') |
+ with self.repo.open('L', 'w') as f: |
+ f.write('L') |
+ self.repo.git('add', 'L') |
+ self.repo.git_commit('L YUP') |
+ |
+ # start on a branch which will be deleted |
+ self.repo.git('checkout', 'branch_G') |
+ |
+ output, _ = self.repo.capture_stdio(self.reup.main) |
+ self.assertIn('branch.branch_K.dormant true', output) |
+ |
+ output, _ = self.repo.capture_stdio(self.reup.main) |
+ self.assertIn('Rebase in progress', output) |
+ |
+ self.repo.git('checkout', '--theirs', 'M') |
+ self.repo.git('rebase', '--skip') |
+ |
+ output, _ = self.repo.capture_stdio(self.reup.main) |
+ self.assertIn('Failed! Attempting to squash', output) |
+ self.assertIn('Deleted branch branch_G', output) |
+ self.assertIn('Deleted branch branch_L', output) |
+ self.assertIn('\'branch_G\' was merged', output) |
+ self.assertIn('checking out \'origin/master\'', output) |
+ |
+ |
+ def testTrackTag(self): |
+ self.origin.git('tag', 'lkgr', self.origin['M']) |
+ self.repo.git('tag', 'lkgr', self.repo['D']) |
+ |
+ self.repo.git('config', 'branch.branch_G.remote', '.') |
+ self.repo.git('config', 'branch.branch_G.merge', 'refs/tags/lkgr') |
+ |
+ self.assertIn( |
+ 'fatal: \'foo bar\' is not a valid branch name', |
+ self.repo.capture_stdio(self.nb.main, ['--lkgr', 'foo bar'])[1]) |
+ |
+ self.repo.run(self.nb.main, ['--lkgr', 'foobar']) |
+ |
+ with self.repo.open('foobar', 'w') as f: |
+ f.write('this is the foobar file') |
+ self.repo.git('add', 'foobar') |
+ self.repo.git_commit('foobar1') |
+ |
+ with self.repo.open('foobar', 'w') as f: |
+ f.write('totes the Foobar file') |
+ self.repo.git_commit('foobar2') |
+ |
+ graphlines = lambda: [ |
+ l.strip() for l in self.repo.git( |
+ 'log', '--graph', '--format=%s', '--branches', 'origin/master' |
+ ).stdout.splitlines() |
+ ] |
+ self.assertEqual( |
+ graphlines(), [ |
+ '* foobar2', |
+ '* foobar1', |
+ '| * G', |
+ '| * F', |
+ '| * E', |
+ '|/', |
+ '* D', |
+ '* C', |
+ '| * L', |
+ '| | * K', |
+ '| |/', |
+ '| * J', |
+ '| * I', |
+ '| * H', |
+ '|/', |
+ '* B', |
+ '* A', |
+ ] |
+ ) |
+ self.assertEquals(self.repo['A'], self.origin['A']) |
+ self.assertEquals(self.repo['G'], self.origin['G']) |
+ |
+ output, _ = self.repo.capture_stdio(self.reup.main) |
+ self.assertIn('Rebasing: branch_G', output) |
+ self.assertIn('Rebasing: branch_K', output) |
+ self.assertIn('Rebasing: branch_L', output) |
+ self.assertIn('Rebasing: foobar', output) |
+ self.assertEquals(self.repo.git('rev-parse', 'lkgr').stdout.strip(), |
+ self.origin['M']) |
+ |
+ self.assertEqual( |
+ graphlines(), [ |
+ '* O', |
+ '* N', |
+ '| * foobar2', |
+ '| * foobar1', |
+ '|/', |
+ '| * L', |
+ '| * K', |
+ '| * J', |
+ '| * I', |
+ '| * H', |
+ '|/', |
+ '* M', |
+ '* G', |
+ '* F', |
+ '* E', |
+ '* D', |
+ '* C', |
+ '* B', |
+ '* A' |
+ ] |
+ ) |
+ |
+ _, err = self.repo.capture_stdio(self.rp.main, ['tag F']) |
+ self.assertIn('fatal: invalid reference', err) |
+ |
+ output, _ = self.repo.capture_stdio(self.rp.main, ['tag_F']) |
+ self.assertIn('to track tag_F [tag] (was lkgr [tag])', output) |
+ |
+ self.assertEqual( |
+ graphlines(), [ |
+ '* O', |
+ '* N', |
+ '| * foobar2', |
+ '| * foobar1', |
+ '| | * L', |
+ '| | * K', |
+ '| | * J', |
+ '| | * I', |
+ '| | * H', |
+ '| |/', |
+ '|/|', |
+ '* | M', |
+ '* | G', |
+ '|/', |
+ '* F', |
+ '* E', |
+ '* D', |
+ '* C', |
+ '* B', |
+ '* A' |
+ ] |
+ ) |
+ |
+ |
+ |
+if __name__ == '__main__': |
+ sys.exit(coverage_utils.covered_main(( |
+ os.path.join(DEPOT_TOOLS_ROOT, 'git_rebase_update.py'), |
+ os.path.join(DEPOT_TOOLS_ROOT, 'git_new_branch.py'), |
+ os.path.join(DEPOT_TOOLS_ROOT, 'git_reparent_branch.py') |
+ ))) |