def test_modified_changelogs(self): scm = Mock() scm.checkout_root = "/foo/bar" scm.changed_files = lambda git_commit: ["file1", "ChangeLog", "relative/path/ChangeLog"] checkout = Checkout(scm) expected_changlogs = ["/foo/bar/ChangeLog", "/foo/bar/relative/path/ChangeLog"] self.assertEqual(checkout.modified_changelogs(git_commit=None), expected_changlogs)
def test_commit_message_for_this_commit(self): checkout = Checkout(None) checkout.modified_changelogs = lambda: ["ChangeLog1", "ChangeLog2"] output = OutputCapture() expected_stderr = "Parsing ChangeLog: ChangeLog1\nParsing ChangeLog: ChangeLog2\n" commit_message = output.assert_outputs(self, checkout.commit_message_for_this_commit, expected_stderr=expected_stderr) self.assertEqual(commit_message.message(), self.expected_commit_message)
def test_bug_id_for_this_commit(self): scm = Mock() checkout = Checkout(scm) checkout.commit_message_for_this_commit = lambda git_commit, changed_files=None: CommitMessage( ChangeLogEntry(_changelog1entry1).contents().splitlines()) self.assertEqual(checkout.bug_id_for_this_commit(git_commit=None), 36629)
def setUp(self): SVNTestRepository.setup(self) self._setup_git_clone_of_svn_repository() os.chdir(self.git_checkout_path) self.scm = detect_scm_system(self.git_checkout_path) # For historical reasons, we test some checkout code here too. self.checkout = Checkout(self.scm)
def test_bug_id_for_revision(self): scm = Mock() scm.committer_email_for_revision = lambda revision: "*****@*****.**" checkout = Checkout(scm) checkout.changelog_entries_for_revision = lambda revision: [ ChangeLogEntry(_changelog1entry1) ] self.assertEqual(checkout.bug_id_for_revision(4), 36629)
def test_latest_entry_for_changelog_at_revision(self): scm = Mock() def mock_contents_at_revision(changelog_path, revision): self.assertEqual(changelog_path, "foo") self.assertEqual(revision, "bar") return _changelog1 scm.contents_at_revision = mock_contents_at_revision checkout = Checkout(scm) entry = checkout._latest_entry_for_changelog_at_revision("foo", "bar") self.assertEqual(entry.contents(), _changelog1entry1)
def test_latest_entry_for_changelog_at_revision(self): scm = Mock() def mock_contents_at_revision(changelog_path, revision): self.assertEqual(changelog_path, "foo") self.assertEqual(revision, "bar") # contents_at_revision is expected to return a byte array (str) # so we encode our unicode ChangeLog down to a utf-8 stream. return _changelog1.encode("utf-8") scm.contents_at_revision = mock_contents_at_revision checkout = Checkout(scm) entry = checkout._latest_entry_for_changelog_at_revision("foo", "bar") self.assertEqual(entry.contents(), _changelog1entry1)
def test_modified_changelogs(self): scm = Mock() scm.checkout_root = "/foo/bar" scm.changed_files = lambda git_commit: [ "file1", "ChangeLog", "relative/path/ChangeLog" ] checkout = Checkout(scm) expected_changlogs = [ "/foo/bar/ChangeLog", "/foo/bar/relative/path/ChangeLog" ] self.assertEqual(checkout.modified_changelogs(git_commit=None), expected_changlogs)
def test_commit_info_for_revision(self): scm = Mock() scm.committer_email_for_revision = lambda revision: "*****@*****.**" checkout = Checkout(scm) checkout.changelog_entries_for_revision = lambda revision: [ChangeLogEntry(_changelog1entry1)] commitinfo = checkout.commit_info_for_revision(4) self.assertEqual(commitinfo.bug_id(), 36629) self.assertEqual(commitinfo.author_name(), "Eric Seidel") self.assertEqual(commitinfo.author_email(), "*****@*****.**") self.assertEqual(commitinfo.reviewer_text(), None) self.assertEqual(commitinfo.reviewer(), None) self.assertEqual(commitinfo.committer_email(), "*****@*****.**") self.assertEqual(commitinfo.committer(), None)
def test_commit_message_for_this_commit(self): checkout = Checkout(None) checkout.modified_changelogs = lambda git_commit, changed_files=None: [ "ChangeLog1", "ChangeLog2" ] output = OutputCapture() expected_stderr = "Parsing ChangeLog: ChangeLog1\nParsing ChangeLog: ChangeLog2\n" commit_message = output.assert_outputs( self, checkout.commit_message_for_this_commit, kwargs={"git_commit": None}, expected_stderr=expected_stderr) self.assertEqual(commit_message.message(), self.expected_commit_message)
def test_apply_git_patch_force(self): scm = detect_scm_system(self.git_checkout_path) patch = self._create_patch(_git_diff('HEAD~2..HEAD')) self._setup_webkittools_scripts_symlink(scm) self.assertRaises(ScriptError, Checkout(scm).apply_patch, patch, force=True)
def test_apply_git_patch(self): scm = detect_scm_system(self.git_checkout_path) # We carefullly pick a diff which does not have a directory addition # as currently svn-apply will error out when trying to remove directories # in Git: https://bugs.webkit.org/show_bug.cgi?id=34871 patch = self._create_patch(_git_diff('HEAD..HEAD^')) self._setup_webkittools_scripts_symlink(scm) Checkout(scm).apply_patch(patch)
def test_apply_svn_patch_force(self): scm = detect_scm_system(self.svn_checkout_path) patch = self._create_patch(_svn_diff("-r3:5")) self._setup_webkittools_scripts_symlink(scm) self.assertRaises(ScriptError, Checkout(scm).apply_patch, patch, force=True)
def setUp(self): self.original_dir = os.getcwd() SVNTestRepository.setup(self) self._setup_git_checkout() self.scm = detect_scm_system(self.git_checkout_path) # For historical reasons, we test some checkout code here too. self.checkout = Checkout(self.scm)
def test_changelog_entries_for_revision(self): scm = Mock() scm.changed_files_for_revision = lambda revision: [ 'foo/ChangeLog', 'bar/ChangeLog' ] checkout = Checkout(scm) def mock_latest_entry_for_changelog_at_revision(path, revision): if path == "foo/ChangeLog": return 'foo' raise ScriptError() checkout._latest_entry_for_changelog_at_revision = mock_latest_entry_for_changelog_at_revision # Even though fetching one of the entries failed, the other should succeed. entries = checkout.changelog_entries_for_revision(1) self.assertEqual(len(entries), 1) self.assertEqual(entries[0], 'foo')
def test_suggested_reviewers(self): def mock_changelog_entries_for_revision(revision): if revision % 2 == 0: return [ChangeLogEntry(_changelog1entry1)] return [ChangeLogEntry(_changelog1entry2)] def mock_revisions_changing_file(path, limit=5): if path.endswith("ChangeLog"): return [3] return [4, 8] scm = Mock() scm.checkout_root = "/foo/bar" scm.changed_files = lambda git_commit: ["file1", "file2", "relative/path/ChangeLog"] scm.revisions_changing_file = mock_revisions_changing_file checkout = Checkout(scm) checkout.changelog_entries_for_revision = mock_changelog_entries_for_revision reviewers = checkout.suggested_reviewers(git_commit=None) reviewer_names = [reviewer.full_name for reviewer in reviewers] self.assertEqual(reviewer_names, [u'Tor Arne Vestb\xf8'])
def test_suggested_reviewers(self): def mock_changelog_entries_for_revision(revision): if revision % 2 == 0: return [ChangeLogEntry(_changelog1entry1)] return [ChangeLogEntry(_changelog1entry2)] def mock_revisions_changing_file(path, limit=5): if path.endswith("ChangeLog"): return [3] return [4, 8] scm = Mock() scm.checkout_root = "/foo/bar" scm.changed_files = lambda git_commit: [ "file1", "file2", "relative/path/ChangeLog" ] scm.revisions_changing_file = mock_revisions_changing_file checkout = Checkout(scm) checkout.changelog_entries_for_revision = mock_changelog_entries_for_revision reviewers = checkout.suggested_reviewers(git_commit=None) reviewer_names = [reviewer.full_name for reviewer in reviewers] self.assertEqual(reviewer_names, [u'Tor Arne Vestb\xf8'])
def test_commit_info_for_revision(self): scm = Mock() scm.committer_email_for_revision = lambda revision: "*****@*****.**" checkout = Checkout(scm) checkout.changelog_entries_for_revision = lambda revision: [ ChangeLogEntry(_changelog1entry1) ] commitinfo = checkout.commit_info_for_revision(4) self.assertEqual(commitinfo.bug_id(), 36629) self.assertEqual(commitinfo.author_name(), u"Tor Arne Vestb\u00f8") self.assertEqual(commitinfo.author_email(), "*****@*****.**") self.assertEqual(commitinfo.reviewer_text(), None) self.assertEqual(commitinfo.reviewer(), None) self.assertEqual(commitinfo.committer_email(), "*****@*****.**") self.assertEqual(commitinfo.committer(), None) checkout.changelog_entries_for_revision = lambda revision: [] self.assertEqual(checkout.commit_info_for_revision(1), None)
class GitSVNTest(SCMTest): def _setup_git_checkout(self): self.git_checkout_path = tempfile.mkdtemp(suffix="git_test_checkout") # --quiet doesn't make git svn silent, so we use run_silent to redirect output run_silent(['git', 'svn', 'clone', '-T', 'trunk', self.svn_repo_url, self.git_checkout_path]) os.chdir(self.git_checkout_path) def _tear_down_git_checkout(self): # Change back to a valid directory so that later calls to os.getcwd() do not fail. os.chdir(self.original_dir) run_command(['rm', '-rf', self.git_checkout_path]) def setUp(self): self.original_dir = os.getcwd() SVNTestRepository.setup(self) self._setup_git_checkout() self.scm = detect_scm_system(self.git_checkout_path) # For historical reasons, we test some checkout code here too. self.checkout = Checkout(self.scm) def tearDown(self): SVNTestRepository.tear_down(self) self._tear_down_git_checkout() def test_detection(self): scm = detect_scm_system(self.git_checkout_path) self.assertEqual(scm.display_name(), "git") self.assertEqual(scm.supports_local_commits(), True) def test_read_git_config(self): key = 'test.git-config' value = 'git-config value' run_command(['git', 'config', key, value]) self.assertEqual(self.scm.read_git_config(key), value) def test_local_commits(self): test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') run_command(['git', 'commit', '-a', '-m', 'local commit']) self.assertEqual(len(self.scm.local_commits()), 1) def test_discard_local_commits(self): test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') run_command(['git', 'commit', '-a', '-m', 'local commit']) self.assertEqual(len(self.scm.local_commits()), 1) self.scm.discard_local_commits() self.assertEqual(len(self.scm.local_commits()), 0) def test_delete_branch(self): new_branch = 'foo' run_command(['git', 'checkout', '-b', new_branch]) self.assertEqual(run_command(['git', 'symbolic-ref', 'HEAD']).strip(), 'refs/heads/' + new_branch) run_command(['git', 'checkout', '-b', 'bar']) self.scm.delete_branch(new_branch) self.assertFalse(re.search(r'foo', run_command(['git', 'branch']))) def test_remote_merge_base(self): # Diff to merge-base should include working-copy changes, # which the diff to svn_branch.. doesn't. test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') diff_to_common_base = _git_diff(self.scm.remote_branch_ref() + '..') diff_to_merge_base = _git_diff(self.scm.remote_merge_base()) self.assertFalse(re.search(r'foo', diff_to_common_base)) self.assertTrue(re.search(r'foo', diff_to_merge_base)) def test_rebase_in_progress(self): svn_test_file = os.path.join(self.svn_checkout_path, 'test_file') write_into_file_at_path(svn_test_file, "svn_checkout") run_command(['svn', 'commit', '--message', 'commit to conflict with git commit'], cwd=self.svn_checkout_path) git_test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(git_test_file, "git_checkout") run_command(['git', 'commit', '-a', '-m', 'commit to be thrown away by rebase abort']) # --quiet doesn't make git svn silent, so use run_silent to redirect output self.assertRaises(ScriptError, run_silent, ['git', 'svn', '--quiet', 'rebase']) # Will fail due to a conflict leaving us mid-rebase. scm = detect_scm_system(self.git_checkout_path) self.assertTrue(scm.rebase_in_progress()) # Make sure our cleanup works. scm.clean_working_directory() self.assertFalse(scm.rebase_in_progress()) # Make sure cleanup doesn't throw when no rebase is in progress. scm.clean_working_directory() def test_commitish_parsing(self): scm = detect_scm_system(self.git_checkout_path) # Multiple revisions are cherry-picked. self.assertEqual(len(scm.commit_ids_from_commitish_arguments(['HEAD~2'])), 1) self.assertEqual(len(scm.commit_ids_from_commitish_arguments(['HEAD', 'HEAD~2'])), 2) # ... is an invalid range specifier self.assertRaises(ScriptError, scm.commit_ids_from_commitish_arguments, ['trunk...HEAD']) def test_commitish_order(self): scm = detect_scm_system(self.git_checkout_path) commit_range = 'HEAD~3..HEAD' actual_commits = scm.commit_ids_from_commitish_arguments([commit_range]) expected_commits = [] expected_commits += reversed(run_command(['git', 'rev-list', commit_range]).splitlines()) self.assertEqual(actual_commits, expected_commits) def test_apply_git_patch(self): scm = detect_scm_system(self.git_checkout_path) # We carefullly pick a diff which does not have a directory addition # as currently svn-apply will error out when trying to remove directories # in Git: https://bugs.webkit.org/show_bug.cgi?id=34871 patch = self._create_patch(_git_diff('HEAD..HEAD^')) self._setup_webkittools_scripts_symlink(scm) Checkout(scm).apply_patch(patch) def test_apply_git_patch_force(self): scm = detect_scm_system(self.git_checkout_path) patch = self._create_patch(_git_diff('HEAD~2..HEAD')) self._setup_webkittools_scripts_symlink(scm) self.assertRaises(ScriptError, Checkout(scm).apply_patch, patch, force=True) def test_commit_text_parsing(self): write_into_file_at_path('test_file', 'more test content') self.scm.commit_locally_with_message("another test commit") commit_text = self.scm.commit_with_message("another test commit") self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '6') self.scm.dryrun = True write_into_file_at_path('test_file', 'still more test content') self.scm.commit_locally_with_message("yet another test commit") commit_text = self.scm.commit_with_message("yet another test commit") self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '0') def _one_local_commit_plus_working_copy_changes(self): write_into_file_at_path('test_file_commit1', 'more test content') run_command(['git', 'add', 'test_file_commit1']) self.scm.commit_locally_with_message("another test commit") write_into_file_at_path('test_file_commit2', 'still more test content') run_command(['git', 'add', 'test_file_commit2']) def test_commit_with_message_working_copy_only(self): write_into_file_at_path('test_file_commit1', 'more test content') run_command(['git', 'add', 'test_file_commit1']) scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("yet another test commit") self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit1', svn_log)) def test_commit_with_message_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("yet another test commit", squash=True) self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit2', svn_log)) self.assertTrue(re.search(r'test_file_commit1', svn_log)) def _two_local_commits(self): write_into_file_at_path('test_file_commit1', 'more test content') run_command(['git', 'add', 'test_file_commit1']) self.scm.commit_locally_with_message("another test commit") write_into_file_at_path('test_file_commit2', 'still more test content') run_command(['git', 'add', 'test_file_commit2']) self.scm.commit_locally_with_message("yet another test commit") def _three_local_commits(self): write_into_file_at_path('test_file_commit0', 'more test content') run_command(['git', 'add', 'test_file_commit0']) self.scm.commit_locally_with_message("another test commit") self._two_local_commits() def test_commit_with_message_git_commit(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("another test commit", git_commit="HEAD^") self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit1', svn_log)) self.assertFalse(re.search(r'test_file_commit2', svn_log)) def test_commit_with_message_git_commit_range(self): self._three_local_commits() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("another test commit", git_commit="HEAD~2..HEAD") self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertFalse(re.search(r'test_file_commit0', svn_log)) self.assertTrue(re.search(r'test_file_commit1', svn_log)) self.assertTrue(re.search(r'test_file_commit2', svn_log)) def test_commit_with_message_multiple_local_commits(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.commit_with_message, ["another test commit"]) def test_commit_with_message_multiple_local_commits_and_working_copy(self): self._two_local_commits() write_into_file_at_path('test_file_commit1', 'working copy change') scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.commit_with_message, ["another test commit"]) def test_commit_with_message_git_commit_and_working_copy(self): self._two_local_commits() write_into_file_at_path('test_file_commit1', 'working copy change') scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.commit_with_message, ["another test commit", 'git_commit="HEAD^"']) def test_commit_with_message_multiple_local_commits_no_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("yet another test commit", squash=False) self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit2', svn_log)) self.assertFalse(re.search(r'test_file_commit1', svn_log)) svn_log = run_command(['git', 'svn', 'log', '--limit=2', '--verbose']) self.assertTrue(re.search(r'test_file_commit1', svn_log)) def test_commit_with_message_multiple_local_commits_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("yet another test commit", squash=True) self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit2', svn_log)) self.assertTrue(re.search(r'test_file_commit1', svn_log)) def test_commit_with_message_not_synced_squash(self): run_command(['git', 'checkout', '-b', 'my-branch', 'trunk~3']) self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.commit_with_message, "another test commit", squash=True) def test_remote_branch_ref(self): self.assertEqual(self.scm.remote_branch_ref(), 'refs/remotes/trunk') def test_reverse_diff(self): self._shared_test_reverse_diff() def test_diff_for_revision(self): self._shared_test_diff_for_revision() def test_svn_apply_git_patch(self): self._shared_test_svn_apply_git_patch() def test_create_patch_local_plus_working_copy(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.create_patch) def test_create_patch_multiple_local_commits(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.create_patch) def test_create_patch_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(squash=True) self.assertTrue(re.search(r'test_file_commit2', patch)) self.assertTrue(re.search(r'test_file_commit1', patch)) def test_create_patch_not_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(squash=False) self.assertTrue(re.search(r'test_file_commit2', patch)) self.assertFalse(re.search(r'test_file_commit1', patch)) def test_create_patch_git_commit(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(git_commit="HEAD^") self.assertTrue(re.search(r'test_file_commit1', patch)) self.assertFalse(re.search(r'test_file_commit2', patch)) def test_create_patch_git_commit_range(self): self._three_local_commits() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(git_commit="HEAD~2..HEAD") self.assertFalse(re.search(r'test_file_commit0', patch)) self.assertTrue(re.search(r'test_file_commit2', patch)) self.assertTrue(re.search(r'test_file_commit1', patch)) def test_create_patch_multiple_local_commits_no_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(squash=False) # FIXME: It's weird that with squash=False, create_patch/changed_files ignores local commits, # but commit_with_message commits them. self.assertTrue(patch == "") def test_create_patch_multiple_local_commits_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(squash=True) self.assertTrue(re.search(r'test_file_commit2', patch)) self.assertTrue(re.search(r'test_file_commit1', patch)) def test_create_patch_not_synced_squash(self): run_command(['git', 'checkout', '-b', 'my-branch', 'trunk~3']) self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.create_patch, squash=True) def test_create_binary_patch(self): # Create a git binary patch and check the contents. scm = detect_scm_system(self.git_checkout_path) test_file_name = 'binary_file' test_file_path = os.path.join(self.git_checkout_path, test_file_name) file_contents = ''.join(map(chr, range(256))) write_into_file_at_path(test_file_path, file_contents, encoding=None) run_command(['git', 'add', test_file_name]) patch = scm.create_patch() self.assertTrue(re.search(r'\nliteral 0\n', patch)) self.assertTrue(re.search(r'\nliteral 256\n', patch)) # Check if we can apply the created patch. run_command(['git', 'rm', '-f', test_file_name]) self._setup_webkittools_scripts_symlink(scm) self.checkout.apply_patch(self._create_patch(patch)) self.assertEqual(file_contents, read_from_path(test_file_path, encoding=None)) # Check if we can create a patch from a local commit. write_into_file_at_path(test_file_path, file_contents, encoding=None) run_command(['git', 'add', test_file_name]) run_command(['git', 'commit', '-m', 'binary diff']) patch_from_local_commit = scm.create_patch('HEAD') self.assertTrue(re.search(r'\nliteral 0\n', patch_from_local_commit)) self.assertTrue(re.search(r'\nliteral 256\n', patch_from_local_commit)) def test_changed_files_local_plus_working_copy(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.changed_files) def test_changed_files_multiple_local_commits(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.changed_files) def test_changed_files_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(squash=True) self.assertTrue('test_file_commit2' in files) self.assertTrue('test_file_commit1' in files) def test_changed_files_not_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(squash=False) self.assertTrue('test_file_commit2' in files) self.assertFalse('test_file_commit1' in files) def test_changed_files_git_commit(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(git_commit="HEAD^") self.assertTrue('test_file_commit1' in files) self.assertFalse('test_file_commit2' in files) def test_changed_files_git_commit_range(self): self._three_local_commits() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(git_commit="HEAD~2..HEAD") self.assertTrue('test_file_commit0' not in files) self.assertTrue('test_file_commit1' in files) self.assertTrue('test_file_commit2' in files) def test_changed_files_multiple_local_commits_no_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(squash=False) # FIXME: It's weird that with squash=False, create_patch/changed_files ignores local commits, # but commit_with_message commits them. self.assertTrue(len(files) == 0) def test_changed_files_multiple_local_commits_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(squash=True) self.assertTrue('test_file_commit2' in files) self.assertTrue('test_file_commit1' in files) def test_changed_files_not_synced_squash(self): run_command(['git', 'checkout', '-b', 'my-branch', 'trunk~3']) self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.changed_files, squash=True) def test_changed_files(self): self._shared_test_changed_files() def test_changed_files_for_revision(self): self._shared_test_changed_files_for_revision() def test_contents_at_revision(self): self._shared_test_contents_at_revision() def test_added_files(self): self._shared_test_added_files() def test_committer_email_for_revision(self): self._shared_test_committer_email_for_revision()
class SVNTest(SCMTest): @staticmethod def _set_date_and_reviewer(changelog_entry): # Joe Cool matches the reviewer set in SCMTest._create_patch changelog_entry = changelog_entry.replace('REVIEWER_HERE', 'Joe Cool') # svn-apply will update ChangeLog entries with today's date. return changelog_entry.replace('DATE_HERE', date.today().isoformat()) def test_svn_apply(self): first_entry = """2009-10-26 Eric Seidel <*****@*****.**> Reviewed by Foo Bar. Most awesome change ever. * scm_unittest.py: """ intermediate_entry = """2009-10-27 Eric Seidel <*****@*****.**> Reviewed by Baz Bar. A more awesomer change yet! * scm_unittest.py: """ one_line_overlap_patch = """Index: ChangeLog =================================================================== --- ChangeLog (revision 5) +++ ChangeLog (working copy) @@ -1,5 +1,13 @@ 2009-10-26 Eric Seidel <*****@*****.**> + Reviewed by NOBODY (OOPS!). + + Second most awesome change ever. + + * scm_unittest.py: + +2009-10-26 Eric Seidel <*****@*****.**> + Reviewed by Foo Bar. Most awesome change ever. """ one_line_overlap_entry = """DATE_HERE Eric Seidel <*****@*****.**> Reviewed by REVIEWER_HERE. Second most awesome change ever. * scm_unittest.py: """ two_line_overlap_patch = """Index: ChangeLog =================================================================== --- ChangeLog (revision 5) +++ ChangeLog (working copy) @@ -2,6 +2,14 @@ Reviewed by Foo Bar. + Second most awesome change ever. + + * scm_unittest.py: + +2009-10-26 Eric Seidel <*****@*****.**> + + Reviewed by Foo Bar. + Most awesome change ever. * scm_unittest.py: """ two_line_overlap_entry = """DATE_HERE Eric Seidel <*****@*****.**> Reviewed by Foo Bar. Second most awesome change ever. * scm_unittest.py: """ write_into_file_at_path('ChangeLog', first_entry) run_command(['svn', 'add', 'ChangeLog']) run_command(['svn', 'commit', '--quiet', '--message', 'ChangeLog commit']) # Patch files were created against just 'first_entry'. # Add a second commit to make svn-apply have to apply the patches with fuzz. changelog_contents = "%s\n%s" % (intermediate_entry, first_entry) write_into_file_at_path('ChangeLog', changelog_contents) run_command(['svn', 'commit', '--quiet', '--message', 'Intermediate commit']) self._setup_webkittools_scripts_symlink(self.scm) self.checkout.apply_patch(self._create_patch(one_line_overlap_patch)) expected_changelog_contents = "%s\n%s" % (self._set_date_and_reviewer(one_line_overlap_entry), changelog_contents) self.assertEquals(read_from_path('ChangeLog'), expected_changelog_contents) self.scm.revert_files(['ChangeLog']) self.checkout.apply_patch(self._create_patch(two_line_overlap_patch)) expected_changelog_contents = "%s\n%s" % (self._set_date_and_reviewer(two_line_overlap_entry), changelog_contents) self.assertEquals(read_from_path('ChangeLog'), expected_changelog_contents) def setUp(self): SVNTestRepository.setup(self) os.chdir(self.svn_checkout_path) self.scm = detect_scm_system(self.svn_checkout_path) # For historical reasons, we test some checkout code here too. self.checkout = Checkout(self.scm) def tearDown(self): SVNTestRepository.tear_down(self) def test_detect_scm_system_relative_url(self): scm = detect_scm_system(".") # I wanted to assert that we got the right path, but there was some # crazy magic with temp folder names that I couldn't figure out. self.assertTrue(scm.checkout_root) def test_create_patch_is_full_patch(self): test_dir_path = os.path.join(self.svn_checkout_path, "test_dir2") os.mkdir(test_dir_path) test_file_path = os.path.join(test_dir_path, 'test_file2') write_into_file_at_path(test_file_path, 'test content') run_command(['svn', 'add', 'test_dir2']) # create_patch depends on 'svn-create-patch', so make a dummy version. scripts_path = os.path.join(self.svn_checkout_path, 'WebKitTools', 'Scripts') os.makedirs(scripts_path) create_patch_path = os.path.join(scripts_path, 'svn-create-patch') write_into_file_at_path(create_patch_path, '#!/bin/sh\necho $PWD') # We could pass -n to prevent the \n, but not all echo accept -n. os.chmod(create_patch_path, stat.S_IXUSR | stat.S_IRUSR) # Change into our test directory and run the create_patch command. os.chdir(test_dir_path) scm = detect_scm_system(test_dir_path) self.assertEqual(scm.checkout_root, self.svn_checkout_path) # Sanity check that detection worked right. patch_contents = scm.create_patch() # Our fake 'svn-create-patch' returns $PWD instead of a patch, check that it was executed from the root of the repo. self.assertEqual("%s\n" % os.path.realpath(scm.checkout_root), patch_contents) # Add a \n because echo adds a \n. def test_detection(self): scm = detect_scm_system(self.svn_checkout_path) self.assertEqual(scm.display_name(), "svn") self.assertEqual(scm.supports_local_commits(), False) def test_apply_small_binary_patch(self): patch_contents = """Index: test_file.swf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: test_file.swf ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== """ expected_contents = base64.b64decode("Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==") self._setup_webkittools_scripts_symlink(self.scm) patch_file = self._create_patch(patch_contents) self.checkout.apply_patch(patch_file) actual_contents = read_from_path("test_file.swf", encoding=None) self.assertEqual(actual_contents, expected_contents) def test_apply_svn_patch(self): scm = detect_scm_system(self.svn_checkout_path) patch = self._create_patch(_svn_diff("-r5:4")) self._setup_webkittools_scripts_symlink(scm) Checkout(scm).apply_patch(patch) def test_apply_svn_patch_force(self): scm = detect_scm_system(self.svn_checkout_path) patch = self._create_patch(_svn_diff("-r3:5")) self._setup_webkittools_scripts_symlink(scm) self.assertRaises(ScriptError, Checkout(scm).apply_patch, patch, force=True) def test_commit_logs(self): # Commits have dates and usernames in them, so we can't just direct compare. self.assertTrue(re.search('fourth commit', self.scm.last_svn_commit_log())) self.assertTrue(re.search('second commit', self.scm.svn_commit_log(3))) def _shared_test_commit_with_message(self, username=None): write_into_file_at_path('test_file', 'more test content') commit_text = self.scm.commit_with_message("another test commit", username) self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '6') self.scm.dryrun = True write_into_file_at_path('test_file', 'still more test content') commit_text = self.scm.commit_with_message("yet another test commit", username) self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '0') def test_commit_text_parsing(self): self._shared_test_commit_with_message() def test_commit_with_username(self): self._shared_test_commit_with_message("*****@*****.**") def test_has_authorization_for_realm(self): scm = detect_scm_system(self.svn_checkout_path) fake_home_dir = tempfile.mkdtemp(suffix="fake_home_dir") svn_config_dir_path = os.path.join(fake_home_dir, ".subversion") os.mkdir(svn_config_dir_path) fake_webkit_auth_file = os.path.join(svn_config_dir_path, "fake_webkit_auth_file") write_into_file_at_path(fake_webkit_auth_file, SVN.svn_server_realm) self.assertTrue(scm.has_authorization_for_realm(home_directory=fake_home_dir)) os.remove(fake_webkit_auth_file) os.rmdir(svn_config_dir_path) os.rmdir(fake_home_dir) def test_not_have_authorization_for_realm(self): scm = detect_scm_system(self.svn_checkout_path) fake_home_dir = tempfile.mkdtemp(suffix="fake_home_dir") svn_config_dir_path = os.path.join(fake_home_dir, ".subversion") os.mkdir(svn_config_dir_path) self.assertFalse(scm.has_authorization_for_realm(home_directory=fake_home_dir)) os.rmdir(svn_config_dir_path) os.rmdir(fake_home_dir) def test_reverse_diff(self): self._shared_test_reverse_diff() def test_diff_for_revision(self): self._shared_test_diff_for_revision() def test_svn_apply_git_patch(self): self._shared_test_svn_apply_git_patch() def test_changed_files(self): self._shared_test_changed_files() def test_changed_files_for_revision(self): self._shared_test_changed_files_for_revision() def test_added_files(self): self._shared_test_added_files() def test_contents_at_revision(self): self._shared_test_contents_at_revision() def test_committer_email_for_revision(self): self._shared_test_committer_email_for_revision()
def test_apply_svn_patch(self): scm = detect_scm_system(self.svn_checkout_path) patch = self._create_patch(_svn_diff("-r5:4")) self._setup_webkittools_scripts_symlink(scm) Checkout(scm).apply_patch(patch)
def _initialize_scm(self, patch_directories=None): self._scm = default_scm(patch_directories) self._checkout = Checkout(self.scm())
class GitTest(SCMTest): def _setup_git_clone_of_svn_repository(self): self.git_checkout_path = tempfile.mkdtemp(suffix="git_test_checkout") # --quiet doesn't make git svn silent, so we use run_silent to redirect output run_silent([ 'git', 'svn', 'clone', '-T', 'trunk', self.svn_repo_url, self.git_checkout_path ]) def _tear_down_git_clone_of_svn_repository(self): run_command(['rm', '-rf', self.git_checkout_path]) def setUp(self): SVNTestRepository.setup(self) self._setup_git_clone_of_svn_repository() os.chdir(self.git_checkout_path) self.scm = detect_scm_system(self.git_checkout_path) # For historical reasons, we test some checkout code here too. self.checkout = Checkout(self.scm) def tearDown(self): SVNTestRepository.tear_down(self) self._tear_down_git_clone_of_svn_repository() def test_detection(self): scm = detect_scm_system(self.git_checkout_path) self.assertEqual(scm.display_name(), "git") self.assertEqual(scm.supports_local_commits(), True) def test_read_git_config(self): key = 'test.git-config' value = 'git-config value' run_command(['git', 'config', key, value]) self.assertEqual(self.scm.read_git_config(key), value) def test_local_commits(self): test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') run_command(['git', 'commit', '-a', '-m', 'local commit']) self.assertEqual(len(self.scm.local_commits()), 1) def test_discard_local_commits(self): test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') run_command(['git', 'commit', '-a', '-m', 'local commit']) self.assertEqual(len(self.scm.local_commits()), 1) self.scm.discard_local_commits() self.assertEqual(len(self.scm.local_commits()), 0) def test_delete_branch(self): old_branch = run_command(['git', 'symbolic-ref', 'HEAD']).strip() new_branch = 'foo' run_command(['git', 'checkout', '-b', new_branch]) self.assertEqual( run_command(['git', 'symbolic-ref', 'HEAD']).strip(), 'refs/heads/' + new_branch) run_command(['git', 'checkout', old_branch]) self.scm.delete_branch(new_branch) self.assertFalse(re.search(r'foo', run_command(['git', 'branch']))) def test_svn_merge_base(self): # Diff to merge-base should include working-copy changes, # which the diff to svn_branch.. doesn't. test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') diff_to_common_base = _git_diff(self.scm.svn_branch_name() + '..') diff_to_merge_base = _git_diff(self.scm.svn_merge_base()) self.assertFalse(re.search(r'foo', diff_to_common_base)) self.assertTrue(re.search(r'foo', diff_to_merge_base)) def test_rebase_in_progress(self): svn_test_file = os.path.join(self.svn_checkout_path, 'test_file') write_into_file_at_path(svn_test_file, "svn_checkout") run_command([ 'svn', 'commit', '--message', 'commit to conflict with git commit' ], cwd=self.svn_checkout_path) git_test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(git_test_file, "git_checkout") run_command([ 'git', 'commit', '-a', '-m', 'commit to be thrown away by rebase abort' ]) # --quiet doesn't make git svn silent, so use run_silent to redirect output self.assertRaises( ScriptError, run_silent, ['git', 'svn', '--quiet', 'rebase' ]) # Will fail due to a conflict leaving us mid-rebase. scm = detect_scm_system(self.git_checkout_path) self.assertTrue(scm.rebase_in_progress()) # Make sure our cleanup works. scm.clean_working_directory() self.assertFalse(scm.rebase_in_progress()) # Make sure cleanup doesn't throw when no rebase is in progress. scm.clean_working_directory() def test_commitish_parsing(self): scm = detect_scm_system(self.git_checkout_path) # Multiple revisions are cherry-picked. self.assertEqual( len(scm.commit_ids_from_commitish_arguments(['HEAD~2'])), 1) self.assertEqual( len(scm.commit_ids_from_commitish_arguments(['HEAD', 'HEAD~2'])), 2) # ... is an invalid range specifier self.assertRaises(ScriptError, scm.commit_ids_from_commitish_arguments, ['trunk...HEAD']) def test_commitish_order(self): scm = detect_scm_system(self.git_checkout_path) commit_range = 'HEAD~3..HEAD' actual_commits = scm.commit_ids_from_commitish_arguments( [commit_range]) expected_commits = [] expected_commits += reversed( run_command(['git', 'rev-list', commit_range]).splitlines()) self.assertEqual(actual_commits, expected_commits) def test_apply_git_patch(self): scm = detect_scm_system(self.git_checkout_path) # We carefullly pick a diff which does not have a directory addition # as currently svn-apply will error out when trying to remove directories # in Git: https://bugs.webkit.org/show_bug.cgi?id=34871 patch = self._create_patch(_git_diff('HEAD..HEAD^')) self._setup_webkittools_scripts_symlink(scm) Checkout(scm).apply_patch(patch) def test_apply_git_patch_force(self): scm = detect_scm_system(self.git_checkout_path) patch = self._create_patch(_git_diff('HEAD~2..HEAD')) self._setup_webkittools_scripts_symlink(scm) self.assertRaises(ScriptError, Checkout(scm).apply_patch, patch, force=True) def test_commit_text_parsing(self): write_into_file_at_path('test_file', 'more test content') self.scm.commit_locally_with_message("another test commit") commit_text = self.scm.commit_with_message("another test commit") self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '6') self.scm.dryrun = True write_into_file_at_path('test_file', 'still more test content') self.scm.commit_locally_with_message("yet another test commit") commit_text = self.scm.commit_with_message("yet another test commit") self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '0') def _one_local_commit_plus_working_copy_changes(self): write_into_file_at_path('test_file_commit1', 'more test content') run_command(['git', 'add', 'test_file_commit1']) self.scm.commit_locally_with_message("another test commit") write_into_file_at_path('test_file_commit2', 'still more test content') run_command(['git', 'add', 'test_file_commit2']) def test_commit_with_message_working_copy_only(self): write_into_file_at_path('test_file_commit1', 'more test content') run_command(['git', 'add', 'test_file_commit1']) scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("yet another test commit") self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit1', svn_log)) def test_commit_with_message_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("yet another test commit", squash=True) self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit2', svn_log)) self.assertTrue(re.search(r'test_file_commit1', svn_log)) def _two_local_commits(self): write_into_file_at_path('test_file_commit1', 'more test content') run_command(['git', 'add', 'test_file_commit1']) self.scm.commit_locally_with_message("another test commit") write_into_file_at_path('test_file_commit2', 'still more test content') run_command(['git', 'add', 'test_file_commit2']) self.scm.commit_locally_with_message("yet another test commit") def test_commit_with_message_git_commit(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("another test commit", git_commit="HEAD^") self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit1', svn_log)) self.assertFalse(re.search(r'test_file_commit2', svn_log)) def test_commit_with_message_git_commit_range(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("another test commit", git_commit="HEAD~2..HEAD") self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit1', svn_log)) self.assertTrue(re.search(r'test_file_commit2', svn_log)) def test_commit_with_message_multiple_local_commits(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.commit_with_message, ["another test commit"]) def test_commit_with_message_multiple_local_commits_and_working_copy(self): self._two_local_commits() write_into_file_at_path('test_file_commit1', 'working copy change') scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.commit_with_message, ["another test commit"]) def test_commit_with_message_git_commit_and_working_copy(self): self._two_local_commits() write_into_file_at_path('test_file_commit1', 'working copy change') scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.commit_with_message, ["another test commit", 'git_commit="HEAD^"']) def test_commit_with_message_multiple_local_commits_no_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("yet another test commit", squash=False) self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit2', svn_log)) self.assertFalse(re.search(r'test_file_commit1', svn_log)) svn_log = run_command(['git', 'svn', 'log', '--limit=2', '--verbose']) self.assertTrue(re.search(r'test_file_commit1', svn_log)) def test_commit_with_message_multiple_local_commits_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) commit_text = scm.commit_with_message("yet another test commit", squash=True) self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) self.assertTrue(re.search(r'test_file_commit2', svn_log)) self.assertTrue(re.search(r'test_file_commit1', svn_log)) def test_reverse_diff(self): self._shared_test_reverse_diff() def test_diff_for_revision(self): self._shared_test_diff_for_revision() def test_svn_apply_git_patch(self): self._shared_test_svn_apply_git_patch() def test_create_patch_local_plus_working_copy(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.create_patch) def test_create_patch_multiple_local_commits(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.create_patch) def test_create_patch_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(squash=True) self.assertTrue(re.search(r'test_file_commit2', patch)) self.assertTrue(re.search(r'test_file_commit1', patch)) def test_create_patch_not_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(squash=False) self.assertTrue(re.search(r'test_file_commit2', patch)) self.assertFalse(re.search(r'test_file_commit1', patch)) def test_create_patch_git_commit(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(git_commit="HEAD^") self.assertTrue(re.search(r'test_file_commit1', patch)) self.assertFalse(re.search(r'test_file_commit2', patch)) def test_create_patch_git_commit_range(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(git_commit="HEAD~2..HEAD") self.assertTrue(re.search(r'test_file_commit2', patch)) self.assertTrue(re.search(r'test_file_commit1', patch)) def test_create_patch_multiple_local_commits_no_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(squash=False) # FIXME: It's weird that with squash=False, create_patch/changed_files ignores local commits, # but commit_with_message commits them. self.assertTrue(patch == "") def test_create_patch_multiple_local_commits_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) patch = scm.create_patch(squash=True) self.assertTrue(re.search(r'test_file_commit2', patch)) self.assertTrue(re.search(r'test_file_commit1', patch)) def test_create_binary_patch(self): # Create a git binary patch and check the contents. scm = detect_scm_system(self.git_checkout_path) test_file_name = 'binary_file' test_file_path = os.path.join(self.git_checkout_path, test_file_name) file_contents = ''.join(map(chr, range(256))) write_into_file_at_path(test_file_path, file_contents, encoding=None) run_command(['git', 'add', test_file_name]) patch = scm.create_patch() self.assertTrue(re.search(r'\nliteral 0\n', patch)) self.assertTrue(re.search(r'\nliteral 256\n', patch)) # Check if we can apply the created patch. run_command(['git', 'rm', '-f', test_file_name]) self._setup_webkittools_scripts_symlink(scm) self.checkout.apply_patch(self._create_patch(patch)) self.assertEqual(file_contents, read_from_path(test_file_path, encoding=None)) # Check if we can create a patch from a local commit. write_into_file_at_path(test_file_path, file_contents, encoding=None) run_command(['git', 'add', test_file_name]) run_command(['git', 'commit', '-m', 'binary diff']) patch_from_local_commit = scm.create_patch('HEAD') self.assertTrue(re.search(r'\nliteral 0\n', patch_from_local_commit)) self.assertTrue(re.search(r'\nliteral 256\n', patch_from_local_commit)) def test_changed_files_local_plus_working_copy(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.changed_files) def test_changed_files_multiple_local_commits(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) self.assertRaises(ScriptError, scm.changed_files) def test_changed_files_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(squash=True) self.assertTrue('test_file_commit2' in files) self.assertTrue('test_file_commit1' in files) def test_changed_files_not_squashed(self): self._one_local_commit_plus_working_copy_changes() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(squash=False) self.assertTrue('test_file_commit2' in files) self.assertFalse('test_file_commit1' in files) def test_changed_files_git_commit(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(git_commit="HEAD^") self.assertTrue('test_file_commit1' in files) self.assertFalse('test_file_commit2' in files) def test_changed_files_git_commit_range(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(git_commit="HEAD~2..HEAD") self.assertTrue('test_file_commit1' in files) self.assertTrue('test_file_commit2' in files) def test_changed_files_multiple_local_commits_no_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(squash=False) # FIXME: It's weird that with squash=False, create_patch/changed_files ignores local commits, # but commit_with_message commits them. self.assertTrue(len(files) == 0) def test_changed_files_multiple_local_commits_squash(self): self._two_local_commits() scm = detect_scm_system(self.git_checkout_path) files = scm.changed_files(squash=True) self.assertTrue('test_file_commit2' in files) self.assertTrue('test_file_commit1' in files) def test_changed_files(self): self._shared_test_changed_files() def test_changed_files_for_revision(self): self._shared_test_changed_files_for_revision() def test_contents_at_revision(self): self._shared_test_contents_at_revision() def test_added_files(self): self._shared_test_added_files() def test_committer_email_for_revision(self): self._shared_test_committer_email_for_revision()
class GitTest(SCMTest): def _setup_git_clone_of_svn_repository(self): self.git_checkout_path = tempfile.mkdtemp(suffix="git_test_checkout") # --quiet doesn't make git svn silent, so we use run_silent to redirect output run_silent(['git', 'svn', '--quiet', 'clone', self.svn_repo_url, self.git_checkout_path]) def _tear_down_git_clone_of_svn_repository(self): run_command(['rm', '-rf', self.git_checkout_path]) def setUp(self): SVNTestRepository.setup(self) self._setup_git_clone_of_svn_repository() os.chdir(self.git_checkout_path) self.scm = detect_scm_system(self.git_checkout_path) # For historical reasons, we test some checkout code here too. self.checkout = Checkout(self.scm) def tearDown(self): SVNTestRepository.tear_down(self) self._tear_down_git_clone_of_svn_repository() def test_detection(self): scm = detect_scm_system(self.git_checkout_path) self.assertEqual(scm.display_name(), "git") self.assertEqual(scm.supports_local_commits(), True) def test_read_git_config(self): key = 'test.git-config' value = 'git-config value' run_command(['git', 'config', key, value]) self.assertEqual(self.scm.read_git_config(key), value) def test_local_commits(self): test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') run_command(['git', 'commit', '-a', '-m', 'local commit']) self.assertEqual(len(self.scm.local_commits()), 1) def test_discard_local_commits(self): test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') run_command(['git', 'commit', '-a', '-m', 'local commit']) self.assertEqual(len(self.scm.local_commits()), 1) self.scm.discard_local_commits() self.assertEqual(len(self.scm.local_commits()), 0) def test_delete_branch(self): old_branch = run_command(['git', 'symbolic-ref', 'HEAD']).strip() new_branch = 'foo' run_command(['git', 'checkout', '-b', new_branch]) self.assertEqual(run_command(['git', 'symbolic-ref', 'HEAD']).strip(), 'refs/heads/' + new_branch) run_command(['git', 'checkout', old_branch]) self.scm.delete_branch(new_branch) self.assertFalse(re.search(r'foo', run_command(['git', 'branch']))) def test_svn_merge_base(self): # Diff to merge-base should include working-copy changes, # which the diff to svn_branch.. doesn't. test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') diff_to_common_base = run_command(['git', 'diff', self.scm.svn_branch_name() + '..']) diff_to_merge_base = run_command(['git', 'diff', self.scm.svn_merge_base()]) self.assertFalse(re.search(r'foo', diff_to_common_base)) self.assertTrue(re.search(r'foo', diff_to_merge_base)) def test_rebase_in_progress(self): svn_test_file = os.path.join(self.svn_checkout_path, 'test_file') write_into_file_at_path(svn_test_file, "svn_checkout") run_command(['svn', 'commit', '--message', 'commit to conflict with git commit'], cwd=self.svn_checkout_path) git_test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(git_test_file, "git_checkout") run_command(['git', 'commit', '-a', '-m', 'commit to be thrown away by rebase abort']) # --quiet doesn't make git svn silent, so use run_silent to redirect output self.assertRaises(ScriptError, run_silent, ['git', 'svn', '--quiet', 'rebase']) # Will fail due to a conflict leaving us mid-rebase. scm = detect_scm_system(self.git_checkout_path) self.assertTrue(scm.rebase_in_progress()) # Make sure our cleanup works. scm.clean_working_directory() self.assertFalse(scm.rebase_in_progress()) # Make sure cleanup doesn't throw when no rebase is in progress. scm.clean_working_directory() def test_commitish_parsing(self): scm = detect_scm_system(self.git_checkout_path) # Multiple revisions are cherry-picked. self.assertEqual(len(scm.commit_ids_from_commitish_arguments(['HEAD~2'])), 1) self.assertEqual(len(scm.commit_ids_from_commitish_arguments(['HEAD', 'HEAD~2'])), 2) # ... is an invalid range specifier self.assertRaises(ScriptError, scm.commit_ids_from_commitish_arguments, ['trunk...HEAD']) def test_commitish_order(self): scm = detect_scm_system(self.git_checkout_path) commit_range = 'HEAD~3..HEAD' actual_commits = scm.commit_ids_from_commitish_arguments([commit_range]) expected_commits = [] expected_commits += reversed(run_command(['git', 'rev-list', commit_range]).splitlines()) self.assertEqual(actual_commits, expected_commits) def test_apply_git_patch(self): scm = detect_scm_system(self.git_checkout_path) # We carefullly pick a diff which does not have a directory addition # as currently svn-apply will error out when trying to remove directories # in Git: https://bugs.webkit.org/show_bug.cgi?id=34871 patch = self._create_patch(run_command(['git', 'diff', 'HEAD..HEAD^'])) self._setup_webkittools_scripts_symlink(scm) Checkout(scm).apply_patch(patch) def test_apply_git_patch_force(self): scm = detect_scm_system(self.git_checkout_path) patch = self._create_patch(run_command(['git', 'diff', 'HEAD~2..HEAD'])) self._setup_webkittools_scripts_symlink(scm) self.assertRaises(ScriptError, Checkout(scm).apply_patch, patch, force=True) def test_commit_text_parsing(self): self._shared_test_commit_with_message() def test_reverse_diff(self): self._shared_test_reverse_diff() def test_diff_for_revision(self): self._shared_test_diff_for_revision() def test_svn_apply_git_patch(self): self._shared_test_svn_apply_git_patch() def test_create_binary_patch(self): # Create a git binary patch and check the contents. scm = detect_scm_system(self.git_checkout_path) test_file_name = 'binary_file' test_file_path = os.path.join(self.git_checkout_path, test_file_name) file_contents = ''.join(map(chr, range(256))) write_into_file_at_path(test_file_path, file_contents) run_command(['git', 'add', test_file_name]) patch = scm.create_patch() self.assertTrue(re.search(r'\nliteral 0\n', patch)) self.assertTrue(re.search(r'\nliteral 256\n', patch)) # Check if we can apply the created patch. run_command(['git', 'rm', '-f', test_file_name]) self._setup_webkittools_scripts_symlink(scm) self.checkout.apply_patch(self._create_patch(patch)) self.assertEqual(file_contents, read_from_path(test_file_path)) # Check if we can create a patch from a local commit. write_into_file_at_path(test_file_path, file_contents) run_command(['git', 'add', test_file_name]) run_command(['git', 'commit', '-m', 'binary diff']) patch_from_local_commit = scm.create_patch_from_local_commit('HEAD') self.assertTrue(re.search(r'\nliteral 0\n', patch_from_local_commit)) self.assertTrue(re.search(r'\nliteral 256\n', patch_from_local_commit)) patch_since_local_commit = scm.create_patch_since_local_commit('HEAD^1') self.assertTrue(re.search(r'\nliteral 0\n', patch_since_local_commit)) self.assertTrue(re.search(r'\nliteral 256\n', patch_since_local_commit)) self.assertEqual(patch_from_local_commit, patch_since_local_commit) def test_changed_files(self): self._shared_test_changed_files() def test_changed_files_for_revision(self): self._shared_test_changed_files_for_revision() def test_contents_at_revision(self): self._shared_test_contents_at_revision() def test_added_files(self): self._shared_test_added_files() def test_committer_email_for_revision(self): self._shared_test_committer_email_for_revision()
def checkout(self): if not self._checkout: self._checkout = Checkout(self.scm()) return self._checkout
def test_bug_id_for_revision(self): scm = Mock() scm.committer_email_for_revision = lambda revision: "*****@*****.**" checkout = Checkout(scm) checkout.changelog_entries_for_revision = lambda revision: [ChangeLogEntry(_changelog1entry1)] self.assertEqual(checkout.bug_id_for_revision(4), 36629)
def test_bug_id_for_this_commit(self): scm = Mock() checkout = Checkout(scm) checkout.commit_message_for_this_commit = lambda git_commit, changed_files=None: CommitMessage(ChangeLogEntry(_changelog1entry1).contents().splitlines()) self.assertEqual(checkout.bug_id_for_this_commit(git_commit=None), 36629)
class SVNTest(SCMTest): @staticmethod def _set_date_and_reviewer(changelog_entry): # Joe Cool matches the reviewer set in SCMTest._create_patch changelog_entry = changelog_entry.replace('REVIEWER_HERE', 'Joe Cool') # svn-apply will update ChangeLog entries with today's date. return changelog_entry.replace('DATE_HERE', date.today().isoformat()) def test_svn_apply(self): first_entry = """2009-10-26 Eric Seidel <*****@*****.**> Reviewed by Foo Bar. Most awesome change ever. * scm_unittest.py: """ intermediate_entry = """2009-10-27 Eric Seidel <*****@*****.**> Reviewed by Baz Bar. A more awesomer change yet! * scm_unittest.py: """ one_line_overlap_patch = """Index: ChangeLog =================================================================== --- ChangeLog (revision 5) +++ ChangeLog (working copy) @@ -1,5 +1,13 @@ 2009-10-26 Eric Seidel <*****@*****.**> + Reviewed by NOBODY (OOPS!). + + Second most awesome change ever. + + * scm_unittest.py: + +2009-10-26 Eric Seidel <*****@*****.**> + Reviewed by Foo Bar. Most awesome change ever. """ one_line_overlap_entry = """DATE_HERE Eric Seidel <*****@*****.**> Reviewed by REVIEWER_HERE. Second most awesome change ever. * scm_unittest.py: """ two_line_overlap_patch = """Index: ChangeLog =================================================================== --- ChangeLog (revision 5) +++ ChangeLog (working copy) @@ -2,6 +2,14 @@ Reviewed by Foo Bar. + Second most awesome change ever. + + * scm_unittest.py: + +2009-10-26 Eric Seidel <*****@*****.**> + + Reviewed by Foo Bar. + Most awesome change ever. * scm_unittest.py: """ two_line_overlap_entry = """DATE_HERE Eric Seidel <*****@*****.**> Reviewed by Foo Bar. Second most awesome change ever. * scm_unittest.py: """ write_into_file_at_path('ChangeLog', first_entry) run_command(['svn', 'add', 'ChangeLog']) run_command( ['svn', 'commit', '--quiet', '--message', 'ChangeLog commit']) # Patch files were created against just 'first_entry'. # Add a second commit to make svn-apply have to apply the patches with fuzz. changelog_contents = "%s\n%s" % (intermediate_entry, first_entry) write_into_file_at_path('ChangeLog', changelog_contents) run_command( ['svn', 'commit', '--quiet', '--message', 'Intermediate commit']) self._setup_webkittools_scripts_symlink(self.scm) self.checkout.apply_patch(self._create_patch(one_line_overlap_patch)) expected_changelog_contents = "%s\n%s" % (self._set_date_and_reviewer( one_line_overlap_entry), changelog_contents) self.assertEquals(read_from_path('ChangeLog'), expected_changelog_contents) self.scm.revert_files(['ChangeLog']) self.checkout.apply_patch(self._create_patch(two_line_overlap_patch)) expected_changelog_contents = "%s\n%s" % (self._set_date_and_reviewer( two_line_overlap_entry), changelog_contents) self.assertEquals(read_from_path('ChangeLog'), expected_changelog_contents) def setUp(self): SVNTestRepository.setup(self) os.chdir(self.svn_checkout_path) self.scm = detect_scm_system(self.svn_checkout_path) # For historical reasons, we test some checkout code here too. self.checkout = Checkout(self.scm) def tearDown(self): SVNTestRepository.tear_down(self) def test_detect_scm_system_relative_url(self): scm = detect_scm_system(".") # I wanted to assert that we got the right path, but there was some # crazy magic with temp folder names that I couldn't figure out. self.assertTrue(scm.checkout_root) def test_create_patch_is_full_patch(self): test_dir_path = os.path.join(self.svn_checkout_path, "test_dir2") os.mkdir(test_dir_path) test_file_path = os.path.join(test_dir_path, 'test_file2') write_into_file_at_path(test_file_path, 'test content') run_command(['svn', 'add', 'test_dir2']) # create_patch depends on 'svn-create-patch', so make a dummy version. scripts_path = os.path.join(self.svn_checkout_path, 'WebKitTools', 'Scripts') os.makedirs(scripts_path) create_patch_path = os.path.join(scripts_path, 'svn-create-patch') write_into_file_at_path( create_patch_path, '#!/bin/sh\necho $PWD' ) # We could pass -n to prevent the \n, but not all echo accept -n. os.chmod(create_patch_path, stat.S_IXUSR | stat.S_IRUSR) # Change into our test directory and run the create_patch command. os.chdir(test_dir_path) scm = detect_scm_system(test_dir_path) self.assertEqual(scm.checkout_root, self.svn_checkout_path ) # Sanity check that detection worked right. patch_contents = scm.create_patch() # Our fake 'svn-create-patch' returns $PWD instead of a patch, check that it was executed from the root of the repo. self.assertEqual("%s\n" % os.path.realpath(scm.checkout_root), patch_contents) # Add a \n because echo adds a \n. def test_detection(self): scm = detect_scm_system(self.svn_checkout_path) self.assertEqual(scm.display_name(), "svn") self.assertEqual(scm.supports_local_commits(), False) def test_apply_small_binary_patch(self): patch_contents = """Index: test_file.swf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: test_file.swf ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== """ expected_contents = base64.b64decode( "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==") self._setup_webkittools_scripts_symlink(self.scm) patch_file = self._create_patch(patch_contents) self.checkout.apply_patch(patch_file) actual_contents = read_from_path("test_file.swf", encoding=None) self.assertEqual(actual_contents, expected_contents) def test_apply_svn_patch(self): scm = detect_scm_system(self.svn_checkout_path) patch = self._create_patch(_svn_diff("-r5:4")) self._setup_webkittools_scripts_symlink(scm) Checkout(scm).apply_patch(patch) def test_apply_svn_patch_force(self): scm = detect_scm_system(self.svn_checkout_path) patch = self._create_patch(_svn_diff("-r3:5")) self._setup_webkittools_scripts_symlink(scm) self.assertRaises(ScriptError, Checkout(scm).apply_patch, patch, force=True) def test_commit_logs(self): # Commits have dates and usernames in them, so we can't just direct compare. self.assertTrue( re.search('fourth commit', self.scm.last_svn_commit_log())) self.assertTrue(re.search('second commit', self.scm.svn_commit_log(3))) def _shared_test_commit_with_message(self, username=None): write_into_file_at_path('test_file', 'more test content') commit_text = self.scm.commit_with_message("another test commit", username) self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '6') self.scm.dryrun = True write_into_file_at_path('test_file', 'still more test content') commit_text = self.scm.commit_with_message("yet another test commit", username) self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '0') def test_commit_text_parsing(self): self._shared_test_commit_with_message() def test_commit_with_username(self): self._shared_test_commit_with_message("*****@*****.**") def test_has_authorization_for_realm(self): scm = detect_scm_system(self.svn_checkout_path) fake_home_dir = tempfile.mkdtemp(suffix="fake_home_dir") svn_config_dir_path = os.path.join(fake_home_dir, ".subversion") os.mkdir(svn_config_dir_path) fake_webkit_auth_file = os.path.join(svn_config_dir_path, "fake_webkit_auth_file") write_into_file_at_path(fake_webkit_auth_file, SVN.svn_server_realm) self.assertTrue( scm.has_authorization_for_realm(home_directory=fake_home_dir)) os.remove(fake_webkit_auth_file) os.rmdir(svn_config_dir_path) os.rmdir(fake_home_dir) def test_not_have_authorization_for_realm(self): scm = detect_scm_system(self.svn_checkout_path) fake_home_dir = tempfile.mkdtemp(suffix="fake_home_dir") svn_config_dir_path = os.path.join(fake_home_dir, ".subversion") os.mkdir(svn_config_dir_path) self.assertFalse( scm.has_authorization_for_realm(home_directory=fake_home_dir)) os.rmdir(svn_config_dir_path) os.rmdir(fake_home_dir) def test_reverse_diff(self): self._shared_test_reverse_diff() def test_diff_for_revision(self): self._shared_test_diff_for_revision() def test_svn_apply_git_patch(self): self._shared_test_svn_apply_git_patch() def test_changed_files(self): self._shared_test_changed_files() def test_changed_files_for_revision(self): self._shared_test_changed_files_for_revision() def test_added_files(self): self._shared_test_added_files() def test_contents_at_revision(self): self._shared_test_contents_at_revision() def test_committer_email_for_revision(self): self._shared_test_committer_email_for_revision()