def setUp(self): self.test_root = shared.create_dir() self.project_dir = os.path.join(self.test_root, 'project') self.state_dir = os.path.join(self.project_dir, '.peru') self.cache_dir = os.path.join(self.state_dir, 'cache') self.yaml = textwrap.dedent('''\ imports: foo: ./ cp module foo: # relative paths should always be interpreted from the dir # containing peru.yaml, even if that's not the sync dir. path: ../foo ''') shared.write_files(self.project_dir, {'peru.yaml': self.yaml}) self.peru_file = os.path.join(self.project_dir, 'peru.yaml') self.foo_dir = os.path.join(self.test_root, 'foo') shared.write_files(self.foo_dir, {'bar': 'baz'}) # We'll run tests from this inner subdirectory, so that we're more # likely to catch places where we're using the cwd incorrectly. self.cwd = os.path.join(self.project_dir, 'cwd', 'in', 'here') makedirs(self.cwd)
def test_git_plugin_with_submodule(self): content_repo = GitRepo(self.content_dir) # Git has a small bug: The .gitmodules file is always created with "\n" # line endings, even on Windows. With core.autocrlf turned on, that # causes a warning when the file is added/committed, because those line # endings would get replaced with "\r\n" when the file was checked out. # We can just turn autocrlf off for this test to silence the warning. content_repo.run('git', 'config', 'core.autocrlf', 'false') submodule_dir = shared.create_dir({'another': 'file'}) submodule_repo = GitRepo(submodule_dir) content_repo.run( 'git', 'submodule', 'add', '-q', submodule_dir, 'subdir/') content_repo.run('git', 'commit', '-m', 'submodule commit') expected_content = self.content.copy() expected_content['subdir/another'] = 'file' with open(os.path.join(self.content_dir, '.gitmodules')) as f: expected_content['.gitmodules'] = f.read() self.do_plugin_test('git', {'url': self.content_dir}, expected_content) # Now move the submodule forward. Make sure it gets fetched again. shared.write_files(submodule_dir, {'more': 'stuff'}) submodule_repo.run('git', 'add', '-A') submodule_repo.run('git', 'commit', '-m', 'more stuff') subprocess.check_output( ['git', 'pull', '-q'], cwd=os.path.join(self.content_dir, 'subdir')) content_repo.run('git', 'commit', '-am', 'submodule update') expected_content['subdir/more'] = 'stuff' self.do_plugin_test('git', {'url': self.content_dir}, expected_content)
def test_git_plugin_with_submodule(self): content_repo = GitRepo(self.content_dir) # Git has a small bug: The .gitmodules file is always created with "\n" # line endings, even on Windows. With core.autocrlf turned on, that # causes a warning when the file is added/committed, because those line # endings would get replaced with "\r\n" when the file was checked out. # We can just turn autocrlf off for this test to silence the warning. content_repo.run('git', 'config', 'core.autocrlf', 'false') submodule_dir = shared.create_dir({'another': 'file'}) submodule_repo = GitRepo(submodule_dir) content_repo.run('git', 'submodule', 'add', '-q', submodule_dir, 'subdir/') content_repo.run('git', 'commit', '-m', 'submodule commit') expected_content = self.content.copy() expected_content['subdir/another'] = 'file' with open(os.path.join(self.content_dir, '.gitmodules')) as f: expected_content['.gitmodules'] = f.read() self.do_plugin_test('git', {'url': self.content_dir}, expected_content) # Now move the submodule forward. Make sure it gets fetched again. shared.write_files(submodule_dir, {'more': 'stuff'}) submodule_repo.run('git', 'add', '-A') submodule_repo.run('git', 'commit', '-m', 'more stuff') subprocess.check_output(['git', 'pull', '-q'], cwd=os.path.join(self.content_dir, 'subdir')) content_repo.run('git', 'commit', '-am', 'submodule update') expected_content['subdir/more'] = 'stuff' self.do_plugin_test('git', {'url': self.content_dir}, expected_content)
def test_hg_plugin_reup(self): repo = HgRepo(self.content_dir) default_tip = repo.run("hg identify --debug -r default").split()[0] plugin_fields = {"url": self.content_dir} # By default, the hg plugin should reup from default. expected_output = {"rev": default_tip} output = plugin_get_reup_fields( self.plugin_context, "hg", plugin_fields) self.assertDictEqual(expected_output, output) # Add some new commits and make sure master gets fetched properly. shared.write_files(self.content_dir, { 'randomfile': "hg doesn't like empty commits"}) repo.run("hg commit -A -m 'junk'") shared.write_files(self.content_dir, { 'randomfile': "hg still doesn't like empty commits"}) repo.run("hg branch newbranch") repo.run("hg commit -A -m 'more junk'") new_default_tip = repo.run("hg identify --debug -r default").split()[0] expected_output["rev"] = new_default_tip output = plugin_get_reup_fields( self.plugin_context, "hg", plugin_fields) self.assertDictEqual(expected_output, output) # Now specify the reup target explicitly. newbranch_tip = repo.run("hg identify --debug -r tip").split()[0] plugin_fields["reup"] = "newbranch" expected_output["rev"] = newbranch_tip output = plugin_get_reup_fields( self.plugin_context, "hg", plugin_fields) self.assertDictEqual(expected_output, output)
def test_hg_plugin_reup(self): repo = HgRepo(self.content_dir) default_tip = repo.run( 'hg', 'identify', '--debug', '-r', 'default' ).split()[0] plugin_fields = {'url': self.content_dir} # By default, the hg plugin should reup from default. expected_output = {'rev': default_tip} output = test_plugin_get_reup_fields( self.plugin_context, 'hg', plugin_fields) self.assertDictEqual(expected_output, output) # Add some new commits and make sure master gets fetched properly. shared.write_files(self.content_dir, { 'randomfile': "hg doesn't like empty commits"}) repo.run('hg', 'commit', '-A', '-m', 'junk') shared.write_files(self.content_dir, { 'randomfile': "hg still doesn't like empty commits"}) repo.run('hg', 'branch', 'newbranch') repo.run('hg', 'commit', '-A', '-m', 'more junk') new_default_tip = repo.run( 'hg', 'identify', '--debug', '-r', 'default' ).split()[0] expected_output['rev'] = new_default_tip output = test_plugin_get_reup_fields( self.plugin_context, 'hg', plugin_fields) self.assertDictEqual(expected_output, output) # Now specify the reup target explicitly. newbranch_tip = repo.run( 'hg', 'identify', '--debug', '-r', 'tip' ).split()[0] plugin_fields['reup'] = 'newbranch' expected_output['rev'] = newbranch_tip output = test_plugin_get_reup_fields( self.plugin_context, 'hg', plugin_fields) self.assertDictEqual(expected_output, output)
def test_assert_contents(self): content = {"foo": "a", "bar/baz": "b"} test_dir = shared.create_dir(content) shared.assert_contents(test_dir, content) shared.write_files(test_dir, {"bing": "c"}) with self.assertRaises(AssertionError): shared.assert_contents(test_dir, content) shared.assert_contents(test_dir, content, excludes=["bing"]) try: shared.assert_contents(test_dir, content, excludes=["foo"]) except AssertionError as e: assert e.args[0].startswith("EXPECTED FILES WERE EXCLUDED")
def test_assert_contents(self): content = {'foo': 'a', 'bar/baz': 'b'} test_dir = shared.create_dir(content) shared.assert_contents(test_dir, content) shared.write_files(test_dir, {'bing': 'c'}) with self.assertRaises(AssertionError): shared.assert_contents(test_dir, content) shared.assert_contents(test_dir, content, excludes=['bing']) try: shared.assert_contents(test_dir, content, excludes=['foo']) except AssertionError as e: assert e.args[0].startswith('EXPECTED FILES WERE EXCLUDED')
def test_clean(self): self.write_peru_yaml('''\ imports: foo: ./ cp module foo: path: {} ''') self.do_integration_test(['clean'], {}) self.do_integration_test(['sync'], {'foo': 'bar'}) shared.write_files(self.test_dir, {'foo': 'DIRTY'}) with self.assertRaises(peru.cache.DirtyWorkingCopyError): self.do_integration_test(['clean'], {}) self.do_integration_test(['clean', '--force'], {})
def test_clean(self): module_dir = shared.create_dir({'foo': 'bar'}) self.write_yaml( '''\ imports: foo: ./ cp module foo: path: {} ''', module_dir) self.do_integration_test(['clean'], {}) self.do_integration_test(['sync'], {'foo': 'bar'}) shared.write_files(self.test_dir, {'foo': 'DIRTY'}) with self.assertRaises(peru.cache.DirtyWorkingCopyError): self.do_integration_test(['clean'], {}) self.do_integration_test(['clean', '--force'], {})
def test_git_plugin_with_submodule(self): content_repo = GitRepo(self.content_dir) # Git has a small bug: The .gitmodules file is always created with "\n" # line endings, even on Windows. With core.autocrlf turned on, that # causes a warning when the file is added/committed, because those line # endings would get replaced with "\r\n" when the file was checked out. # We can just turn autocrlf off for this test to silence the warning. content_repo.run('git', 'config', 'core.autocrlf', 'false') submodule_dir = shared.create_dir({'another': 'file'}) submodule_repo = GitRepo(submodule_dir) content_repo.run( 'git', 'submodule', 'add', '-q', submodule_dir, 'subdir/') content_repo.run('git', 'commit', '-m', 'submodule commit') expected_content = self.content.copy() expected_content['subdir/another'] = 'file' with open(os.path.join(self.content_dir, '.gitmodules')) as f: expected_content['.gitmodules'] = f.read() self.do_plugin_test('git', {'url': self.content_dir}, expected_content) # Now move the submodule forward. Make sure it gets fetched again. shared.write_files(submodule_dir, {'more': 'stuff'}) submodule_repo.run('git', 'add', '-A') submodule_repo.run('git', 'commit', '-m', 'more stuff') subprocess.check_output( ['git', 'pull', '-q'], cwd=os.path.join(self.content_dir, 'subdir')) content_repo.run('git', 'commit', '-am', 'submodule update') expected_content['subdir/more'] = 'stuff' self.do_plugin_test('git', {'url': self.content_dir}, expected_content) # Normally when you run `git submodule add ...`, git puts two things in # your repo: an entry in .gitmodules, and a commit object at the # appropriate path inside your repo. However, it's possible for those # two to get out of sync, especially if you use mv/rm on a directory # followed by `git add`, instead of the smarter `git mv`/`git rm`. We # need to create this condition and check that we then ignore the # submodule. shutil.rmtree(os.path.join(self.content_dir, 'subdir')) content_repo.run('git', 'commit', '-am', 'inconsistent delete') del expected_content['subdir/another'] del expected_content['subdir/more'] self.do_plugin_test('git', {'url': self.content_dir}, expected_content) # Finally, test explicitly disabling submodule fetching. Start by # reverting the 'inconsistent delete' commit from above. content_repo.run('git', 'revert', '--no-edit', 'HEAD') fields = {'url': self.content_dir, 'submodules': 'false'} self.do_plugin_test('git', fields, expected_content)
def test_basic_sync(self): self.write_peru_yaml("""\ cp module foo: path: {} imports: foo: subdir """) self.do_integration_test(["sync"], {"subdir/foo": "bar"}) # Running it again should be a no-op. self.do_integration_test(["sync"], {"subdir/foo": "bar"}) # Running it with a dirty working copy should be an error. shared.write_files(self.test_dir, {'subdir/foo': 'dirty'}) with self.assertRaises(peru.cache.DirtyWorkingCopyError): self.do_integration_test(["sync"], {"subdir/foo": "bar"})
def test_sync_from_subdir(self): peru_yaml = dedent('''\ # Use a relative module path, to make sure it gets resolved # relative to the project root and not the dir where peru was # called. cp module relative_foo: path: {} imports: relative_foo: subdir '''.format(os.path.relpath(self.module_dir, start=self.test_dir))) shared.write_files(self.test_dir, {'peru.yaml': peru_yaml}) subdir = os.path.join(self.test_dir, 'a', 'b') peru.compat.makedirs(subdir) run_peru_command(['sync'], subdir) self.assertTrue(os.path.isdir(os.path.join(self.test_dir, '.peru')), msg=".peru dir didn't end up in the right place") assert_contents(os.path.join(self.test_dir, 'subdir'), {'foo': 'bar'})
def test_basic_sync(self): module_dir = shared.create_dir({'foo': 'bar'}) self.write_yaml('''\ cp module foo: path: {} imports: foo: subdir ''', module_dir) self.do_integration_test(['sync'], {'subdir/foo': 'bar'}) # Running it again should be a no-op. self.do_integration_test(['sync'], {'subdir/foo': 'bar'}) # Running it with a dirty working copy should be an error. shared.write_files(self.test_dir, {'subdir/foo': 'dirty'}) with self.assertRaises(peru.cache.DirtyWorkingCopyError): self.do_integration_test(['sync'], {'subdir/foo': 'bar'})
def test_basic_sync(self): module_dir = shared.create_dir({'foo': 'bar'}) self.write_yaml( '''\ cp module foo: path: {} imports: foo: subdir ''', module_dir) self.do_integration_test(['sync'], {'subdir/foo': 'bar'}) # Running it again should be a no-op. self.do_integration_test(['sync'], {'subdir/foo': 'bar'}) # Running it with a dirty working copy should be an error. shared.write_files(self.test_dir, {'subdir/foo': 'dirty'}) with self.assertRaises(peru.cache.DirtyWorkingCopyError): self.do_integration_test(['sync'], {'subdir/foo': 'bar'})
def test_hg_plugin_multiple_fetches(self): content_repo = HgRepo(self.content_dir) head = content_repo.run("hg identify --debug -r .").split()[0] plugin_fields = {"url": self.content_dir, "rev": head} output = self.do_plugin_test("hg", plugin_fields, self.content) self.assertEqual(output.count("hg clone"), 1) self.assertEqual(output.count("hg pull"), 0) # Add a new file to the directory and commit it. shared.write_files(self.content_dir, {'another': 'file'}) content_repo.run("hg commit -A -m 'committing another file'") # Refetch the original rev. Hg should not do a pull. output = self.do_plugin_test("hg", plugin_fields, self.content) self.assertEqual(output.count("hg clone"), 0) self.assertEqual(output.count("hg pull"), 0) # Not delete the rev field. Git should default to master and fetch. del plugin_fields["rev"] self.content["another"] = "file" output = self.do_plugin_test("hg", plugin_fields, self.content) self.assertEqual(output.count("hg clone"), 0) self.assertEqual(output.count("hg pull"), 1)
def test_no_cache_flag(self): foo_dir = shared.create_dir({'foo': 'bar'}) self.write_yaml('''\ cp module foo: path: {} imports: foo: subdir ''', foo_dir) # Sync the foo module once. self.do_integration_test(['sync'], {'subdir/foo': 'bar'}) # Change the contents of foo and sync again. Because foo is cached, we # shouldn't see any changes. shared.write_files(foo_dir, {'foo': 'woo'}) self.do_integration_test(['sync'], {'subdir/foo': 'bar'}) # Now sync with --no-cache. This time we should see the changes. self.do_integration_test(['sync', '--no-cache'], {'subdir/foo': 'woo'})
def test_no_cache_flag(self): foo_dir = shared.create_dir({'foo': 'bar'}) self.write_yaml( '''\ cp module foo: path: {} imports: foo: subdir ''', foo_dir) # Sync the foo module once. self.do_integration_test(['sync'], {'subdir/foo': 'bar'}) # Change the contents of foo and sync again. Because foo is cached, we # shouldn't see any changes. shared.write_files(foo_dir, {'foo': 'woo'}) self.do_integration_test(['sync'], {'subdir/foo': 'bar'}) # Now sync with --no-cache. This time we should see the changes. self.do_integration_test(['sync', '--no-cache'], {'subdir/foo': 'woo'})
def test_git_plugin_multiple_fetches(self): content_repo = GitRepo(self.content_dir) head = content_repo.run('git', 'rev-parse', 'HEAD') plugin_fields = {"url": self.content_dir, "rev": head} output = self.do_plugin_test("git", plugin_fields, self.content) self.assertEqual(output.count("git clone"), 1) self.assertEqual(output.count("git fetch"), 0) # Add a new file to the directory and commit it. shared.write_files(self.content_dir, {'another': 'file'}) content_repo.run('git', 'add', '-A') content_repo.run('git', 'commit', '-m', 'committing another file') # Refetch the original rev. Git should not do a git-fetch. output = self.do_plugin_test("git", plugin_fields, self.content) self.assertEqual(output.count("git clone"), 0) self.assertEqual(output.count("git fetch"), 0) # Not delete the rev field. Git should default to master and fetch. del plugin_fields["rev"] self.content["another"] = "file" output = self.do_plugin_test("git", plugin_fields, self.content) self.assertEqual(output.count("git clone"), 0) self.assertEqual(output.count("git fetch"), 1)
def test_hg_plugin_multiple_fetches(self): content_repo = HgRepo(self.content_dir) head = content_repo.run('hg', 'identify', '--debug', '-r', '.').split()[0] plugin_fields = {'url': self.content_dir, 'rev': head} output = self.do_plugin_test('hg', plugin_fields, self.content) self.assertEqual(output.count('hg clone'), 1) self.assertEqual(output.count('hg pull'), 0) # Add a new file to the directory and commit it. shared.write_files(self.content_dir, {'another': 'file'}) content_repo.run('hg', 'commit', '-A', '-m', 'committing another file') # Refetch the original rev. Hg should not do a pull. output = self.do_plugin_test('hg', plugin_fields, self.content) self.assertEqual(output.count('hg clone'), 0) self.assertEqual(output.count('hg pull'), 0) # Not delete the rev field. Git should default to master and fetch. del plugin_fields['rev'] self.content['another'] = 'file' output = self.do_plugin_test('hg', plugin_fields, self.content) self.assertEqual(output.count('hg clone'), 0) self.assertEqual(output.count('hg pull'), 1)
def test_git_plugin_with_submodule(self): content_repo = GitRepo(self.content_dir) submodule_dir = shared.create_dir({'another': 'file'}) submodule_repo = GitRepo(submodule_dir) content_repo.run('git submodule add -q "{}" subdir/'.format( submodule_dir)) content_repo.run('git commit -m "submodule commit"') expected_content = self.content.copy() expected_content['subdir/another'] = 'file' with open(os.path.join(self.content_dir, '.gitmodules')) as f: expected_content['.gitmodules'] = f.read() self.do_plugin_test('git', {'url': self.content_dir}, expected_content) # Now move the submodule forward. Make sure it gets fetched again. shared.write_files(submodule_dir, {'more': 'stuff'}) submodule_repo.run('git add -A') submodule_repo.run('git commit -m "more stuff"') subprocess.check_output( ['git', 'pull', '-q'], cwd=os.path.join(self.content_dir, 'subdir')) content_repo.run('git commit -am "submodule udate"') expected_content['subdir/more'] = 'stuff' self.do_plugin_test('git', {'url': self.content_dir}, expected_content)
def write_peru_yaml(self, template): peru_yaml = dedent(template.format(self.module_dir)) shared.write_files(self.test_dir, {'peru.yaml': peru_yaml})