def test_push_single_dir_one_incoming_and_two_outgoing(self): # Tests simple pushing from default branch to a single dir repo # Pushes two outgoing over one incoming svn rev # (used to cause an "unknown revision") # This can happen if someone committed to svn since our last pull (race). repo, repo_path = self.load_and_fetch('branch_from_tag.svndump', layout='single', subdir='trunk') self.add_svn_rev(repo_path, {'trunk/alpha': 'Changed'}) def file_callback(repo, memctx, path): return compathacks.makememfilectx(repo, memctx=memctx, path=path, data='data of %s' % path, islink=False, isexec=False, copied=False) for fn in ['one', 'two']: ctx = context.memctx(repo, (repo['tip'].node(), node.nullid), 'automated test', [fn], file_callback, 'an_author', '2009-10-19 18:49:30 -0500', { 'branch': 'default', }) repo.commitctx(ctx) hg.update(repo, repo['tip'].node()) self.pushrevisions(expected_extra_back=1) self.assertTrue('trunk/one' in test_util.svnls(repo_path, '')) self.assertTrue('trunk/two' in test_util.svnls(repo_path, ''))
def test_push_single_dir_one_incoming_and_two_outgoing(self): # Tests simple pushing from default branch to a single dir repo # Pushes two outgoing over one incoming svn rev # (used to cause an "unknown revision") # This can happen if someone committed to svn since our last pull (race). repo, repo_path = self.load_and_fetch('branch_from_tag.svndump', layout='single', subdir='trunk') self.add_svn_rev(repo_path, {'trunk/alpha': 'Changed'}) def file_callback(repo, memctx, path): return compathacks.makememfilectx(repo, path=path, data='data of %s' % path, islink=False, isexec=False, copied=False) for fn in ['one', 'two']: ctx = context.memctx(repo, (repo['tip'].node(), node.nullid), 'automated test', [fn], file_callback, 'an_author', '2009-10-19 18:49:30 -0500', {'branch': 'default', }) repo.commitctx(ctx) hg.update(repo, repo['tip'].node()) self.pushrevisions(expected_extra_back=1) self.assertTrue('trunk/one' in test_util.svnls(repo_path, '')) self.assertTrue('trunk/two' in test_util.svnls(repo_path, ''))
def test_push_single_dir_branch(self): # Tests local branches pushing to a single dir repo. Creates a fork at # tip. The default branch adds a file called default, while branch foo # adds a file called foo, then tries to push the foo branch and default # branch in that order. repo, repo_path = self.load_and_fetch('branch_from_tag.svndump', layout='single', subdir='') def file_callback(data): def cb(repo, memctx, path): if path == data: return compathacks.makememfilectx(repo, memctx=memctx, path=path, data=data, islink=False, isexec=False, copied=False) raise IOError(errno.EINVAL, 'Invalid operation: ' + path) return cb def commit_to_branch(name, parent): repo.commitctx( context.memctx(repo, (parent, node.nullid), 'automated test (%s)' % name, [name], file_callback(name), 'an_author', '2009-10-19 18:49:30 -0500', { 'branch': name, })) parent = repo['tip'].node() commit_to_branch('default', parent) commit_to_branch('foo', parent) hg.update(repo, revsymbol(repo, 'foo').node()) self.pushrevisions() repo = self.repo # repo is outdated after the rebase happens, refresh self.assertTrue('foo' in test_util.svnls(repo_path, '')) self.assertEqual(set(repo.branchmap()), set(['default'])) # Have to cross to another branch head, so hg.update doesn't work commands.update(self.ui(), self.repo, node.hex(self.repo.branchheads('default')[1]), clean=True) self.pushrevisions() self.assertTrue('default' in test_util.svnls(repo_path, '')) self.assertEquals(len(self.repo.branchheads('default')), 1)
def test_push_single_dir_renamed_branch(self): # Tests pulling and pushing with a renamed branch # Based on test_push_single_dir repo_path = self.load_svndump('branch_from_tag.svndump') cmd = ['clone', '--layout=single', '--branch=flaf'] if self.stupid: cmd.append('--stupid') cmd += [test_util.fileurl(repo_path), self.wc_path] test_util.dispatch(cmd) def file_callback(repo, memctx, path): if path == 'adding_file': return compathacks.makememfilectx(repo, path=path, data='foo', islink=False, isexec=False, copied=False) raise IOError(errno.EINVAL, 'Invalid operation: ' + path) ctx = context.memctx(self.repo, (self.repo['tip'].node(), node.nullid), 'automated test', ['adding_file'], file_callback, 'an_author', '2009-10-19 18:49:30 -0500', {'branch': 'default', }) self.repo.commitctx(ctx) hg.update(self.repo, self.repo['tip'].node()) self.pushrevisions() self.assertTrue('adding_file' in test_util.svnls(repo_path, '')) self.assertEquals(set(['flaf']), set(self.repo[i].branch() for i in self.repo))
def test_push_single_dir_renamed_branch(self): # Tests pulling and pushing with a renamed branch # Based on test_push_single_dir repo_path = self.load_svndump('branch_from_tag.svndump') cmd = ['clone', '--quiet', '--layout=single', '--branch=flaf'] if self.stupid: cmd.append('--stupid') cmd += [test_util.fileurl(repo_path), self.wc_path] test_util.dispatch(cmd) def file_callback(repo, memctx, path): if path == 'adding_file': return compathacks.makememfilectx(repo, memctx=memctx, path=path, data='foo', islink=False, isexec=False, copied=False) raise IOError(errno.EINVAL, 'Invalid operation: ' + path) lr = self.repo ctx = context.memctx(lr, (lr['tip'].node(), node.nullid), 'automated test', ['adding_file'], file_callback, 'an_author', '2009-10-19 18:49:30 -0500', { 'branch': 'default', }) lr.commitctx(ctx) hg.update(self.repo, self.repo['tip'].node()) self.pushrevisions() self.assertTrue('adding_file' in test_util.svnls(repo_path, '')) self.assertEquals(set(['flaf']), set(self.repo[i].branch() for i in self.repo))
def test_push_single_dir_branch(self): # Tests local branches pushing to a single dir repo. Creates a fork at # tip. The default branch adds a file called default, while branch foo # adds a file called foo, then tries to push the foo branch and default # branch in that order. repo, repo_path = self.load_and_fetch('branch_from_tag.svndump', layout='single', subdir='') def file_callback(data): def cb(repo, memctx, path): if path == data: return compathacks.makememfilectx(repo, path=path, data=data, islink=False, isexec=False, copied=False) raise IOError(errno.EINVAL, 'Invalid operation: ' + path) return cb def commit_to_branch(name, parent): repo.commitctx(context.memctx(repo, (parent, node.nullid), 'automated test (%s)' % name, [name], file_callback(name), 'an_author', '2009-10-19 18:49:30 -0500', {'branch': name, })) parent = repo['tip'].node() commit_to_branch('default', parent) commit_to_branch('foo', parent) hg.update(repo, repo['foo'].node()) self.pushrevisions() repo = self.repo # repo is outdated after the rebase happens, refresh self.assertTrue('foo' in test_util.svnls(repo_path, '')) self.assertEqual(compathacks.branchset(repo), set(['default'])) # Have to cross to another branch head, so hg.update doesn't work commands.update(ui.ui(), self.repo, self.repo.branchheads('default')[1], clean=True) self.pushrevisions() self.assertTrue('default' in test_util.svnls(repo_path, '')) self.assertEquals(len(self.repo.branchheads('default')), 1)
def test_push_new_file_existing_dir_root_not_repo_root(self): repo_path = self.load_and_fetch('empty_dir_in_trunk_not_repo_root.svndump', subdir='project')[1] changes = [('narf/a', 'narf/a', 'ohai',), ] self.commitchanges(changes) self.assertEqual(test_util.svnls(repo_path, 'project/trunk'), ['a', 'narf', ]) self.pushrevisions() self.assertEqual(test_util.svnls(repo_path, 'project/trunk'), ['a', 'narf', 'narf/a']) changes = [('narf/a', None, None,), ] self.commitchanges(changes) self.pushrevisions() self.assertEqual(test_util.svnls(repo_path, 'project/trunk'), ['a'])
def test_push_dirs(self): repo_path = self.load_and_fetch('emptyrepo.svndump')[1] changes = [ # Single file in single directory ('d1/a', 'd1/a', 'a\n'), # Two files in one directory ('d2/a', 'd2/a', 'a\n'), ('d2/b', 'd2/b', 'a\n'), # Single file in empty directory hierarchy ('d31/d32/d33/d34/a', 'd31/d32/d33/d34/a', 'a\n'), ('d31/d32/a', 'd31/d32/a', 'a\n'), ] self.commitchanges(changes) self.pushrevisions() self.assertEqual(test_util.svnls(repo_path, 'trunk'), ['d1', 'd1/a', 'd2', 'd2/a', 'd2/b', 'd31', 'd31/d32', 'd31/d32/a', 'd31/d32/d33', 'd31/d32/d33/d34', 'd31/d32/d33/d34/a']) # Add one revision with changed files only, no directory addition # or deletion. changes = [ ('d1/a', 'd1/a', 'aa\n'), ('d2/a', 'd2/a', 'aa\n'), ] self.commitchanges(changes) self.pushrevisions() changes = [ # Remove single file in single directory ('d1/a', None, None), # Remove one file out of two ('d2/a', None, None), # Removing this file should remove one empty parent dir too ('d31/d32/d33/d34/a', None, None), ] self.commitchanges(changes) self.pushrevisions() self.assertEqual(test_util.svnls(repo_path, 'trunk'), ['d2', 'd2/b', 'd31', 'd31/d32', 'd31/d32/a', ])
def test_push_new_dir_project_root_not_repo_root(self): repo_path = self.load_and_fetch('fetch_missing_files_subdir.svndump', subdir='foo')[1] changes = [('magic_new/a', 'magic_new/a', 'ohai',), ] self.commitchanges(changes) self.pushrevisions() self.assertEqual(test_util.svnls(repo_path, 'foo/trunk'), ['bar', 'bar/alpha', 'bar/beta', 'bar/delta', 'bar/gamma', 'foo', 'magic_new', 'magic_new/a'])
def test_push_rename_tree(self): repo = self.repo changes = [ ('geek/alpha', 'geek/alpha', 'content',), ('geek/beta', 'geek/beta', 'content',), ('geek/delta', 'geek/delta', 'content',), ('geek/gamma', 'geek/gamma', 'content',), ('geek/later/pi', 'geek/later/pi', 'content geek/later/pi',), ('geek/later/rho', 'geek/later/rho', 'content geek/later/rho',), ('geek/other/blah', 'geek/other/blah', 'content geek/other/blah',), ('geek/other/another/layer', 'geek/other/another/layer', 'content deep file',), ] self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip']) changes = [ # rename (copy + remove) all of geek to greek ('geek/alpha', 'greek/alpha', None,), ('geek/beta', 'greek/beta', None,), ('geek/delta', 'greek/delta', None,), ('geek/gamma', 'greek/gamma', None,), ('geek/later/pi', 'greek/later/pi', None,), ('geek/later/rho', 'greek/later/rho', None,), ('geek/other/blah', 'greek/other/blah', None,), ('geek/other/another/layer', 'greek/other/another/layer', None,), ('geek/alpha', None, None,), ('geek/beta', None, None,), ('geek/delta', None, None,), ('geek/gamma', None, None,), ('geek/later/pi', None, None,), ('geek/later/rho', None, None,), ('geek/other/blah', None, None,), ('geek/other/another/layer', None, None,), ] self.commitchanges(changes) self.pushrevisions() assert reduce(lambda x, y: x and y, ('geek' not in f for f in test_util.svnls(self.repo_path, 'trunk'))), ( 'This failure means rename of an entire tree is broken.' ' There is a print on the preceding line commented out ' 'that should help you.')
def test_push_single_dir(self): # Tests simple pushing from default branch to a single dir repo repo, repo_path = self.load_and_fetch('branch_from_tag.svndump', layout='single', subdir='') def file_callback(repo, memctx, path): if path == 'adding_file': return compathacks.makememfilectx(repo, memctx=memctx, path=path, data='foo', islink=False, isexec=False, copied=False) elif path == 'adding_binary': return compathacks.makememfilectx(repo, memctx=memctx, path=path, data='\0binary', islink=False, isexec=False, copied=False) raise IOError(errno.EINVAL, 'Invalid operation: ' + path) ctx = context.memctx(repo, (repo['tip'].node(), node.nullid), 'automated test', ['adding_file', 'adding_binary'], file_callback, 'an_author', '2009-10-19 18:49:30 -0500', { 'branch': 'default', }) repo.commitctx(ctx) hg.update(repo, repo['tip'].node()) self.pushrevisions() self.assertTrue('adding_file' in test_util.svnls(repo_path, '')) self.assertEqual( 'application/octet-stream', test_util.svnpropget(repo_path, 'adding_binary', 'svn:mime-type')) # Now add another commit and test mime-type being reset changes = [('adding_binary', 'adding_binary', 'no longer binary')] self.commitchanges(changes) self.pushrevisions() self.assertEqual( '', test_util.svnpropget(repo_path, 'adding_binary', 'svn:mime-type'))
def test_push_single_dir(self): # Tests simple pushing from default branch to a single dir repo repo, repo_path = self.load_and_fetch('branch_from_tag.svndump', layout='single', subdir='') def file_callback(repo, memctx, path): if path == 'adding_file': return compathacks.makememfilectx(repo, path=path, data='foo', islink=False, isexec=False, copied=False) elif path == 'adding_binary': return compathacks.makememfilectx(repo, path=path, data='\0binary', islink=False, isexec=False, copied=False) raise IOError(errno.EINVAL, 'Invalid operation: ' + path) ctx = context.memctx(repo, (repo['tip'].node(), node.nullid), 'automated test', ['adding_file', 'adding_binary'], file_callback, 'an_author', '2009-10-19 18:49:30 -0500', {'branch': 'default', }) repo.commitctx(ctx) hg.update(repo, repo['tip'].node()) self.pushrevisions() self.assertTrue('adding_file' in test_util.svnls(repo_path, '')) self.assertEqual('application/octet-stream', test_util.svnpropget(repo_path, 'adding_binary', 'svn:mime-type')) # Now add another commit and test mime-type being reset changes = [('adding_binary', 'adding_binary', 'no longer binary')] self.commitchanges(changes) self.pushrevisions() self.assertEqual('', test_util.svnpropget(repo_path, 'adding_binary', 'svn:mime-type'))
def test_push_single_dir_change_in_subdir(self): # Tests simple pushing from default branch to a single dir repo # Changes a file in a subdir (regression). repo, repo_path = self.load_and_fetch('branch_from_tag.svndump', layout='single', subdir='tags') changes = [('tag_r3/alpha', 'tag_r3/alpha', 'foo'), ('tag_r3/new', 'tag_r3/new', 'foo'), ('new_dir/new', 'new_dir/new', 'foo'), ] self.commitchanges(changes) self.pushrevisions() self.assertEqual(test_util.svnls(repo_path, 'tags'), ['copied_tag', 'copied_tag/alpha', 'copied_tag/beta', 'new_dir', 'new_dir/new', 'tag_r3', 'tag_r3/alpha', 'tag_r3/beta', 'tag_r3/new'])
def test_push_hgsub(self): if subrepo is None: return repo, repo_path = self.load_and_fetch('pushexternals.svndump', externals='subrepos') # Add a new reference on an existing and non-existing directory changes = [ ('.hgsub', '.hgsub', """\ dir/deps/project2 = [hgsubversion] dir:^/externals/project2 deps/project2 subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1 subdir2/deps/project2 = [hgsubversion] subdir2:^/externals/project2 deps/project2 """), ('.hgsubstate', '.hgsubstate', """\ HEAD dir/deps/project2 HEAD subdir1/deps/project1 HEAD subdir2/deps/project2 """), ('subdir1/a', 'subdir1/a', 'a'), ('subdir2/a', 'subdir2/a', 'a'), ] self.svnco(repo_path, 'externals/project2', '2', 'dir/deps/project2') self.svnco(repo_path, 'externals/project1', '2', 'subdir1/deps/project1') self.svnco(repo_path, 'externals/project2', '2', 'subdir2/deps/project2') self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip']) # Check .hgsub and .hgsubstate were not pushed self.assertEqual( ['dir', 'subdir1', 'subdir1/a', 'subdir2', 'subdir2/a'], test_util.svnls(repo_path, 'trunk')) # Remove all references from one directory, add a new one # to the other (test multiline entries) changes = [ ('.hgsub', '.hgsub', """\ subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1 subdir1/deps/project2 = [hgsubversion] subdir1:^/externals/project2 deps/project2 """), ('.hgsubstate', '.hgsubstate', """\ HEAD subdir1/deps/project1 HEAD subdir1/deps/project2 """), # This removal used to trigger the parent directory removal ('subdir1/a', None, None), ] self.svnco(repo_path, 'externals/project1', '2', 'subdir1/deps/project1') self.svnco(repo_path, 'externals/project2', '2', 'subdir1/deps/project2') self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip']) # Check subdir2/a is still there even if the externals were removed self.assertTrue('subdir2/a' in self.repo['tip']) self.assertTrue('subdir1/a' not in self.repo['tip']) # Move the externals so they are defined on the base directory, # this used to cause full branch removal when deleting the .hgsub changes = [ ('.hgsub', '.hgsub', """\ subdir1/deps/project1 = [hgsubversion] :^/externals/project1 subdir1/deps/project1 """), ('.hgsubstate', '.hgsubstate', """\ HEAD subdir1/deps/project1 """), ] self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip']) # Test externals removal changes = [ ('.hgsub', None, None), ('.hgsubstate', None, None), ] self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip'])
def test_push_rename_tree(self): repo = self.repo changes = [ ( 'geek/alpha', 'geek/alpha', 'content', ), ( 'geek/beta', 'geek/beta', 'content', ), ( 'geek/delta', 'geek/delta', 'content', ), ( 'geek/gamma', 'geek/gamma', 'content', ), ( 'geek/later/pi', 'geek/later/pi', 'content geek/later/pi', ), ( 'geek/later/rho', 'geek/later/rho', 'content geek/later/rho', ), ( 'geek/other/blah', 'geek/other/blah', 'content geek/other/blah', ), ( 'geek/other/another/layer', 'geek/other/another/layer', 'content deep file', ), ] self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip']) changes = [ # rename (copy + remove) all of geek to greek ( 'geek/alpha', 'greek/alpha', None, ), ( 'geek/beta', 'greek/beta', None, ), ( 'geek/delta', 'greek/delta', None, ), ( 'geek/gamma', 'greek/gamma', None, ), ( 'geek/later/pi', 'greek/later/pi', None, ), ( 'geek/later/rho', 'greek/later/rho', None, ), ( 'geek/other/blah', 'greek/other/blah', None, ), ( 'geek/other/another/layer', 'greek/other/another/layer', None, ), ( 'geek/alpha', None, None, ), ( 'geek/beta', None, None, ), ( 'geek/delta', None, None, ), ( 'geek/gamma', None, None, ), ( 'geek/later/pi', None, None, ), ( 'geek/later/rho', None, None, ), ( 'geek/other/blah', None, None, ), ( 'geek/other/another/layer', None, None, ), ] self.commitchanges(changes) self.pushrevisions() assert reduce( lambda x, y: x and y, ('geek' not in f for f in test_util.svnls(self.repo_path, 'trunk'))), ( 'This failure means rename of an entire tree is broken.' ' There is a print on the preceding line commented out ' 'that should help you.')
def test_push_hgsub(self): if subrepo is None: return repo, repo_path = self.load_and_fetch('pushexternals.svndump', externals='subrepos') # Add a new reference on an existing and non-existing directory changes = [ ('.hgsub', '.hgsub', """\ dir/deps/project2 = [hgsubversion] dir:^/externals/project2 deps/project2 subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1 subdir2/deps/project2 = [hgsubversion] subdir2:^/externals/project2 deps/project2 """), ('.hgsubstate', '.hgsubstate', """\ HEAD dir/deps/project2 HEAD subdir1/deps/project1 HEAD subdir2/deps/project2 """), ('subdir1/a', 'subdir1/a', 'a'), ('subdir2/a', 'subdir2/a', 'a'), ] self.svnco(repo_path, 'externals/project2', '2', 'dir/deps/project2') self.svnco(repo_path, 'externals/project1', '2', 'subdir1/deps/project1') self.svnco(repo_path, 'externals/project2', '2', 'subdir2/deps/project2') self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip']) # Check .hgsub and .hgsubstate were not pushed self.assertEqual(['dir', 'subdir1', 'subdir1/a', 'subdir2', 'subdir2/a'], test_util.svnls(repo_path, 'trunk')) # Remove all references from one directory, add a new one # to the other (test multiline entries) changes = [ ('.hgsub', '.hgsub', """\ subdir1/deps/project1 = [hgsubversion] subdir1:^/externals/project1 deps/project1 subdir1/deps/project2 = [hgsubversion] subdir1:^/externals/project2 deps/project2 """), ('.hgsubstate', '.hgsubstate', """\ HEAD subdir1/deps/project1 HEAD subdir1/deps/project2 """), # This removal used to trigger the parent directory removal ('subdir1/a', None, None), ] self.svnco(repo_path, 'externals/project1', '2', 'subdir1/deps/project1') self.svnco(repo_path, 'externals/project2', '2', 'subdir1/deps/project2') self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip']) # Check subdir2/a is still there even if the externals were removed self.assertTrue('subdir2/a' in self.repo['tip']) self.assertTrue('subdir1/a' not in self.repo['tip']) # Move the externals so they are defined on the base directory, # this used to cause full branch removal when deleting the .hgsub changes = [ ('.hgsub', '.hgsub', """\ subdir1/deps/project1 = [hgsubversion] :^/externals/project1 subdir1/deps/project1 """), ('.hgsubstate', '.hgsubstate', """\ HEAD subdir1/deps/project1 """), ] self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip']) # Test externals removal changes = [ ('.hgsub', None, None), ('.hgsubstate', None, None), ] self.commitchanges(changes) self.pushrevisions() self.assertchanges(changes, self.repo['tip'])