def main(args): keep = False if args: if len(args) == 1 and args[0] == '-keep': keep = True else: print __doc__ return # Choose a place to work, rather hackily #root_dir = os.path.join('/tmp','muddle_tests') root_dir = normalise_dir(os.path.join(os.getcwd(), 'transient')) with TransientDirectory(root_dir, keep_on_error=True, keep_anyway=keep) as root_d: with NewDirectory('simple'): banner('TEST SIMPLE BUILD (BZR)') test_bzr_simple_build() with NewDirectory('checkout'): banner('TEST CHECKOUT BUILD (BZR)') setup_bzr_checkout_repositories() test_bzr_checkout_build() banner('TEST MUDDLE PATCH (BZR)') test_bzr_muddle_patch() with NewDirectory('just_pulled'): banner('TEST _JUST_PULLED') test_just_pulled()
def main(args): keep = False if args: if len(args) == 1 and args[0] == '-keep': keep = True else: print __doc__ return # Choose a place to work, rather hackily #root_dir = os.path.join('/tmp','muddle_tests') root_dir = normalise_dir(os.path.join(os.getcwd(), 'transient')) with TransientDirectory(root_dir, keep_on_error=True, keep_anyway=keep) as root_d: with NewDirectory('simple'): banner('TEST SIMPLE BUILD (SUBVERSION)') test_svn_simple_build() with NewDirectory('checkout'): banner('TEST BUILD WITH REVISION (SUBVERSION)') test_svn_revisions_build() with NewDirectory('just_pulled'): banner('TEST _JUST_PULLED') test_just_pulled()
def test_svn_simple_build(): """Bootstrap a muddle build tree. """ root_dir = normalise_dir(os.getcwd()) with NewDirectory('repo'): for name in ('main', 'versions'): shell('svnadmin create %s' % name) print 'Repositories are:', ' '.join(os.listdir('.')) root_repo = 'file://' + os.path.join(root_dir, 'repo', 'main') versions_repo = 'file://' + os.path.join(root_dir, 'repo', 'versions') with NewDirectory('test_build1'): banner('Bootstrapping simple build') muddle(['bootstrap', 'svn+%s' % root_repo, 'test_build']) cat('src/builds/01.py') # But, of course, we don't keep the versions/ directory in the same # repository (lest things get very confused) touch('.muddle/VersionsRepository', 'svn+%s\n' % versions_repo) with Directory('versions'): touch('fred.stamp', '# A comment\n# Another comment\n') svn('import . %s -m "Initial import"' % versions_repo) # Is the next really the best we can do? shell('rm -rf versions') svn('checkout %s' % versions_repo) with Directory('src'): with Directory('builds'): svn('import . %s/builds -m "Initial import"' % root_repo) # Is the next really the best we can do? shell('rm -rf builds') svn('checkout %s/builds' % root_repo) banner('Stamping simple build') muddle(['stamp', 'version']) with Directory('versions'): svn('commit -m "A proper stamp file"') cat('test_build.stamp') # We should be able to check everything out from the repository with NewDirectory('test_build2'): banner('Building from init') muddle(['init', 'svn+%s' % root_repo, 'builds/01.py']) muddle(['checkout', '_all']) # We should be able to recreate our state from the stamp file... with NewDirectory('test_build3'): banner('Unstamping simple build') # Note that we do not ask for 'versions/test_build.stamp', since # our repository corresponds to this versions/ directory as a whole... muddle(['unstamp', 'svn+%s' % versions_repo, 'test_build.stamp'])
def test_git_simple_build(): """Bootstrap a muddle build tree. """ root_dir = normalise_dir(os.getcwd()) with NewDirectory('repo'): for name in ('builds', 'versions'): with NewDirectory(name): git('init --bare') print 'Repositories are:', ' '.join(os.listdir('.')) root_repo = 'file://' + os.path.join(root_dir, 'repo') with NewDirectory('test_build1'): banner('Bootstrapping simple build') muddle(['bootstrap', 'git+%s' % root_repo, 'test_build']) cat('src/builds/01.py') with Directory('versions'): touch('fred.stamp', '# A comment\n# Another comment\n') git('add fred.stamp') git('commit -m "New stamp file"') # "muddle stamp push" knows how to setup the appropriate # repository and push - i.e., if effectively does # # git('remote add origin %s/versions'%root_repo) # git('push origin master') # muddle(['stamp', 'push']) with Directory('src/builds'): git('commit -m "New build"') muddle(['push']) banner('Stamping simple build') muddle(['stamp', 'version']) with Directory('versions'): # Muddle should already have done "git add" for us # git('add test_build.stamp') git('commit -m "A proper stamp file"') cat('test_build.stamp') muddle(['stamp', 'push']) # We should be able to check everything out from the repository with NewDirectory('test_build2'): banner('Building from init') muddle(['init', 'git+%s' % root_repo, 'builds/01.py']) muddle(['checkout', '_all']) # We should be able to recreate our state from the stamp file... with NewDirectory('test_build3'): banner('Unstamping simple build') muddle(['unstamp', 'git+%s' % root_repo, 'versions/test_build.stamp'])
def test_just_pulled(): root_dir = normalise_dir(os.getcwd()) root_repo = 'file://' + os.path.join(root_dir, 'repo') # Set up our repositories setup_bzr_checkout_repositories() setup_new_build(root_repo, 'build_0') root_repo = 'file://' + os.path.join(root_dir, 'repo') banner('Build A') with NewDirectory('build_A'): muddle(['init', 'bzr+%s' % root_repo, 'builds/01.py']) muddle(['checkout', '_all']) banner('Build B') with NewDirectory('build_B'): muddle(['init', 'bzr+%s' % root_repo, 'builds/01.py']) muddle(['checkout', '_all']) banner('Change Build A') with Directory('build_A'): with Directory('src'): with Directory('builds'): append('01.py', '# Just a comment\n') # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') bzr('commit -m "A simple change"') muddle(['push']) with Directory('twolevel'): with Directory('checkout2'): append('Makefile.muddle', '# Just a comment\n') bzr('commit -m "A simple change"') muddle(['push']) banner('Pull into Build B') with Directory('build_B') as d: _just_pulled_file = os.path.join(d.where, '.muddle', '_just_pulled') if os.path.exists(_just_pulled_file): raise GiveUp('%s exists when it should not' % _just_pulled_file) muddle(['pull', '_all']) if not same_content( _just_pulled_file, 'checkout:builds/checked_out\n' 'checkout:checkout2/checked_out\n'): raise GiveUp( '%s does not contain expected labels:\n%s' % (_just_pulled_file, open(_just_pulled_file).readlines())) muddle(['pull', '_all']) if not same_content(_just_pulled_file, ''): raise GiveUp('%s should be empty, but is not' % _just_pulled_file)
def make_old_build_tree(): """Make a build tree that deploys a CPIO file, and use/test it """ with NewDirectory('build.old') as d: muddle(['bootstrap', 'git+file:///nowhere', 'cpio-test-build']) with Directory('src'): with Directory('builds'): touch('01.py', DEPLOYMENT_BUILD_DESC) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') with NewDirectory('first_co'): git('init') touch('Makefile.muddle', MUDDLE_MAKEFILE1.format(progname='program1')) touch('program1.c', MAIN_C_SRC.format(progname='program1')) touch('instructions.xml', INSTRUCTIONS) git('add Makefile.muddle program1.c instructions.xml') git('commit -m "A commit"') muddle(['import']) with NewDirectory('second_co'): git('init') touch( 'Makefile.muddle', MUDDLE_MAKEFILE2.format(progname1='program1', progname2='program2')) touch('program2.c', MAIN_C_SRC.format(progname='program2')) # A version of program1 that announces itself as program2 touch('program1.c', MAIN_C_SRC.format(progname='program2')) git('add Makefile.muddle program2.c') git('commit -m "A commit"') muddle(['import']) muddle([]) with Directory('deploy'): with Directory('everything'): check_cpio_archive('firmware.cpio') # Check we got the correct version of program1 extract_file('firmware.cpio', '/bin/program1') text = get_stdout('bin/program1') if text != 'Program program2\n': raise GiveUp( 'Expected the program1 from role2, but it output %s' % text) print 'That looks like the correct program1'
def test_git_checkout_build(): """Test single, twolevel and multilevel checkouts. Relies on setup_git_checkout_repositories() having been called. """ root_dir = normalise_dir(os.getcwd()) root_repo = 'file://' + os.path.join(root_dir, 'repo') setup_new_build(root_repo, 'test_build1') with Directory('test_build1'): banner('Stamping checkout build') muddle(['stamp', 'version']) with Directory('versions'): git('add checkout_test.stamp') git('commit -m "A stamp file"') # We have to associate it with a repository git('remote add origin %s/versions' % root_repo) git('push origin master') cat('checkout_test.stamp') # We should be able to use muddle to push the stamp file muddle(['stamp', 'push']) # We should be able to check everything out from the repository with NewDirectory('test_build2'): banner('Building checkout build from init') muddle(['init', 'git+%s' % root_repo, 'builds/01.py']) muddle(['checkout', '_all']) check_files([ 'src/builds/01.py', 'src/checkout1/Makefile.muddle', 'src/twolevel/checkout2/Makefile.muddle', 'src/multilevel/inner/checkout3/Makefile.muddle', ]) # We should be able to recreate our state from the stamp file... with NewDirectory('test_build3'): banner('Unstamping checkout build') muddle( ['unstamp', 'git+%s' % root_repo, 'versions/checkout_test.stamp']) check_files([ 'src/builds/01.py', 'versions/checkout_test.stamp', 'src/checkout1/Makefile.muddle', 'src/twolevel/checkout2/Makefile.muddle', 'src/multilevel/inner/checkout3/Makefile.muddle', ])
def add_some_instructions(d): """Add some instruction file by hand. We should do this properly, via Makefiles copying instructions with ``$(MUDDLE_INSTRUCT)``, but this is simpler. """ with Directory('.muddle'): with NewDirectory('instructions'): with NewDirectory('first_pkg'): touch('_default.xml', INSTRUCTIONS) with NewDirectory('second_pkg'): touch('_default.xml', INSTRUCTIONS) touch('x86.xml', INSTRUCTIONS) touch('arm.xml', INSTRUCTIONS) touch('fred.xml', INSTRUCTIONS) # How did that get here?
def test_bzr_simple_build(): """Bootstrap a muddle build tree. """ root_dir = normalise_dir(os.getcwd()) with NewDirectory('repo'): for name in ('builds', 'versions'): with NewDirectory(name): bzr('init') print 'Repositories are:', ' '.join(os.listdir('.')) root_repo = 'file://' + os.path.join(root_dir, 'repo') with NewDirectory('test_build1'): banner('Bootstrapping simple build') muddle(['bootstrap', 'bzr+%s' % root_repo, 'test_build']) cat('src/builds/01.py') with Directory('versions'): touch('fred.stamp', '# A comment\n# Another comment\n') bzr('add fred.stamp') bzr('commit -m "New stamp file"') # We should be able to use muddle to push the stamp file muddle(['stamp', 'push']) with Directory('src/builds'): bzr('commit -m "New build"') muddle(['push']) banner('Stamping simple build') muddle(['stamp', 'version']) with Directory('versions'): # Muddle should have added the stamp file to bzr for us bzr('commit -m "A proper stamp file"') cat('test_build.stamp') muddle(['stamp', 'push']) # We should be able to check everything out from the repository with NewDirectory('test_build2'): banner('Building from init') muddle(['init', 'bzr+%s' % root_repo, 'builds/01.py']) muddle(['checkout', '_all']) # We should be able to recreate our state from the stamp file... with NewDirectory('test_build3'): banner('Unstamping simple build') muddle(['unstamp', 'bzr+%s' % root_repo, 'versions/test_build.stamp'])
def make_old_build_tree(): """Make a build tree that does a romfs deployment, and use/test it """ with NewDirectory('build.old') as d: muddle(['bootstrap', 'git+file:///nowhere', 'cpio-test-build']) with Directory('src'): with Directory('builds'): touch('01.py', DEPLOYMENT_BUILD_DESC_12) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') with NewDirectory('first_co'): git('init') touch('Makefile.muddle', MUDDLE_MAKEFILE1.format(progname='program1')) touch('program1.c', MAIN_C_SRC.format(progname='program1')) touch('instructions.xml', INSTRUCTIONS) os.makedirs('etc/init.d') touch('etc/init.d/rcS', '# A pretend rcS file\n') git('add Makefile.muddle program1.c instructions.xml') git('commit -m "A commit"') muddle(['import']) with NewDirectory('second_co'): git('init') touch( 'Makefile.muddle', MUDDLE_MAKEFILE2.format(progname1='program1', progname2='program2')) touch('program2.c', MAIN_C_SRC.format(progname='program2')) # A version of program1 that announces itself as program2 touch('program1.c', MAIN_C_SRC.format(progname='program2')) git('add Makefile.muddle program2.c') git('commit -m "A commit"') muddle(['import']) muddle([]) with Directory('deploy'): with Directory('everything'): check_specific_files_in_this_dir(['root.romfs'])
def setup_new_build(root_repo, name): with NewDirectory(name): banner('Bootstrapping checkout build') muddle(['bootstrap', 'git+%s' % root_repo, 'test_build']) cat('src/builds/01.py') banner('Setting up src/') with Directory('src'): with Directory('builds'): touch('01.py', CHECKOUT_BUILD_LEVELS) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') git('add 01.py') git('commit -m "New build"') git('push %s/builds HEAD' % root_repo) with NewDirectory('checkout1'): touch('Makefile.muddle', MUDDLE_MAKEFILE) git('init') git('add Makefile.muddle') git('commit -m "Add muddle makefile"') # Assert that this checkout *has* been checked out # (this also does a "muddle reparent" for us, setting # up our remote origin for pushing) muddle(['import']) # And thus we can now ask muddle to push for us # (although a plain "git push" would also work) muddle(['push']) with NewDirectory('twolevel'): with NewDirectory('checkout2'): touch('Makefile.muddle', MUDDLE_MAKEFILE) git('init') git('add Makefile.muddle') git('commit -m "Add muddle makefile"') muddle(['import']) # As was said in 'checkout1', we can "git push" if # we prefer, once we've done import - although we do # need to be specific about *what* we're pushing, this # first time round git('push origin master') with NewDirectory('multilevel'): with NewDirectory('inner'): with NewDirectory('checkout3'): touch('Makefile.muddle', MUDDLE_MAKEFILE) git('init') git('add Makefile.muddle') git('commit -m "Add muddle makefile"') # Or we can do a more complicated sequence of things # Just assert checkout via its tagged label muddle(['assert', 'checkout:alice/checked_out']) # then reparent by hand muddle(['reparent']) # and now we can git push git('push origin master')
def make_repos(root_dir): """Create git repositories for our tests. """ def new_repo(prog_name, repo_name): with NewDirectory(repo_name) as d: make_standard_checkout(d.where, prog_name, prog_name) repo = os.path.join(root_dir, 'repo') with NewDirectory('repo'): with NewDirectory('main'): with NewDirectory('builds') as d: make_build_desc( d.where, BUILD_DESC.format(repo=repo, subdomain1='subdomain1', subdomain2='subdomain2')) with NewDirectory('repo1') as d: make_standard_checkout(d.where, 'program1', 'first program') # Several very similar repositories other_repo_names = ('repo1.1', 'repo1.2', 'repo1.3') for repo_name in other_repo_names: with NewDirectory(repo_name) as d: git('init --bare') global g_UPSTREAMS g_UPSTREAMS[repo_name] = d.where repo_url = os.path.join(repo, 'main', repo_name) with Directory('repo1'): git('remote add %s %s' % (repo_name, repo_url)) git('push %s master' % repo_name) with NewDirectory('subdomain1'): with NewDirectory('builds') as d: make_build_desc(d.where, SUBDOMAIN1_BUILD_DESC.format(repo=repo)) with NewDirectory('subdomain2'): with NewDirectory('builds') as d: make_build_desc(d.where, SUBDOMAIN2_BUILD_DESC.format(repo=repo))
def main(args): keep = False if args: if len(args) == 1 and args[0] == '-keep': keep = True else: print __doc__ raise GiveUp('Unexpected arguments %s' % ' '.join(args)) # This test is independent check_push_pull_permissions() # Working in a local transient directory seems to work OK # although if it's anyone other than me they might prefer # somewhere in $TMPDIR... root_dir = normalise_dir(os.path.join(os.getcwd(), 'transient')) with TransientDirectory(root_dir, keep_on_error=True, keep_anyway=keep) as root: banner('MAKE REPOSITORIES') make_repos(root_dir) with NewDirectory('build') as d: banner('CHECK REPOSITORIES OUT') muddle([ 'init', 'git+file://{repo}/main'.format(repo=root.join('repo')), 'builds/01.py' ]) muddle(['checkout', '_all']) banner('BUILD') muddle([]) banner('STAMP VERSION') muddle(['stamp', 'version']) test_builds_ok_upstream_1(root) test_builds_ok_upstream_2(root) test_builds_ok_upstream_3(root) test_builds_bad_upstream_1(root) test_builds_bad_upstream_2(root) banner('CHECK USING UPSTREAMS') with Directory(d.where): test_using_upstreams(root_dir)
def setup_new_build(root_repo, name): with NewDirectory('test_build1'): banner('Bootstrapping checkout build') muddle(['bootstrap', 'bzr+%s' % root_repo, 'test_build']) cat('src/builds/01.py') banner('Setting up src/') with Directory('src'): with Directory('builds'): touch('01.py', CHECKOUT_BUILD_LEVELS) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') bzr('add 01.py') bzr('commit -m "New build"') # The obvious thing to do is to push with muddle muddle(['push']) with NewDirectory('checkout1'): touch('Makefile.muddle', MUDDLE_MAKEFILE) bzr('init') bzr('add Makefile.muddle') bzr('commit -m "Add muddle makefile"') muddle(['import', 'checkout1']) # Or we can push by hand with bzr bzr('push %s/checkout1' % root_repo) with NewDirectory('twolevel'): with NewDirectory('checkout2'): touch('Makefile.muddle', MUDDLE_MAKEFILE) bzr('init') bzr('add Makefile.muddle') bzr('commit -m "Add muddle makefile"') muddle(['import', 'checkout2']) muddle(['push']) with NewDirectory('multilevel'): with NewDirectory('inner'): with NewDirectory('checkout3'): touch('Makefile.muddle', MUDDLE_MAKEFILE) bzr('init') bzr('add Makefile.muddle') bzr('commit -m "Add muddle makefile"') # If we push directly with BZR bzr('push %s/multilevel/inner/checkout3' % root_repo) muddle(['import', 'alice'])
def setup_bzr_checkout_repositories(): """Set up our testing repositories in the current directory. """ banner('Setting up checkout repos') with NewDirectory('repo'): # The standards for name in ('builds', 'versions'): with NewDirectory(name): bzr('init') # Single level checkouts with NewDirectory('checkout1'): bzr('init') # Two-level checkouts with NewDirectory('twolevel'): with NewDirectory('checkout2'): bzr('init') # Multilevel checkouts with NewDirectory('multilevel'): with NewDirectory('inner'): with NewDirectory('checkout3'): bzr('init')
def new_repo(prog_name, repo_name): with NewDirectory(repo_name) as d: make_standard_checkout(d.where, prog_name, prog_name)
def main(args): keep = False if args: if len(args) == 1 and args[0] == '-keep': keep = True else: print __doc__ raise GiveUp('Unexpected arguments %s' % ' '.join(args)) # Working in a local transient directory seems to work OK # although if it's anyone other than me they might prefer # somewhere in $TMPDIR... root_dir = normalise_dir(os.path.join(os.getcwd(), 'transient')) with TransientDirectory(root_dir, keep_on_error=True, keep_anyway=keep) as root_d: banner('MAKE REPOSITORIES') make_repos_with_subdomain(root_dir) with NewDirectory('build') as d: banner('CHECK REPOSITORIES OUT') checkout_build_descriptions(root_dir, d) muddle(['checkout', '_all']) check_checkout_files(d) banner('BUILD') muddle([]) banner('STAMP VERSION') muddle(['stamp', 'version']) banner('ADD SOME INSTRUCTIONS') add_some_instructions(d) banner('TESTING DISTRIBUTE SOURCE RELEASE') target_dir = os.path.join(root_dir, 'source') muddle(['distribute', '_source_release', target_dir]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same(target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', 'obj', 'install', 'deploy', 'versions', '.muddle/instructions', '.muddle/tags/package', '.muddle/tags/deployment', ]) # Issue 250 banner('TESTING DISTRIBUTE SOURCE RELEASE when in a subdirectory') with Directory('src/builds'): target_dir = os.path.join(root_dir, 'source-2') muddle(['distribute', '_source_release', target_dir]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same(target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', 'obj', 'install', 'deploy', 'versions', '.muddle/instructions', '.muddle/tags/package', '.muddle/tags/deployment', ]) banner('TESTING DISTRIBUTE SOURCE RELEASE WITH VCS') target_dir = os.path.join(root_dir, 'source-with-vcs') muddle(['distribute', '-with-vcs', '_source_release', target_dir]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same(target_dir, onedown=True, unwanted_files=[ 'builds/01.pyc', 'obj', 'install', 'deploy', 'versions', '.muddle/instructions', '.muddle/tags/package', '.muddle/tags/deployment', ]) banner('TESTING DISTRIBUTE SOURCE RELEASE WITH VERSIONS') target_dir = os.path.join(root_dir, 'source-with-versions') muddle([ 'distribute', '-with-versions', '_source_release', target_dir ]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same(target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', 'obj', 'install', 'deploy', '.muddle/instructions', '.muddle/tags/package', '.muddle/tags/deployment', ]) banner('TESTING DISTRIBUTE SOURCE RELEASE WITH VCS AND VERSIONS') target_dir = os.path.join(root_dir, 'source-with-vcs-and-versions') muddle([ 'distribute', '-with-vcs', '-with-versions', '_source_release', target_dir ]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same(target_dir, onedown=True, unwanted_files=[ 'builds/01.pyc', 'obj', 'install', 'deploy', '.muddle/instructions', '.muddle/tags/package', '.muddle/tags/deployment', ]) banner( 'TESTING DISTRIBUTE SOURCE RELEASE WITH "-no-muddle-makefile"') # Hint: it shouldn't make any difference at all target_dir = os.path.join(root_dir, 'source-no-muddle-makefile') muddle([ 'distribute', '-no-muddle-makefile', '_source_release', target_dir ]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same(target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', 'obj', 'install', 'deploy', 'versions', '.muddle/instructions', '.muddle/tags/package', '.muddle/tags/deployment', ]) banner('TESTING DISTRIBUTE BINARY RELEASE') target_dir = os.path.join(root_dir, 'binary') muddle(['distribute', '_binary_release', target_dir]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same(target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', '*.c', 'obj', 'deploy', 'versions', '.muddle/instructions/second_pkg/arm.xml', '.muddle/instructions/second_pkg/fred.xml', '.muddle/tags/deployment', ]) banner('TESTING DISTRIBUTE BINARY RELEASE WITHOUT MUDDLE MAKEFILE') target_dir = os.path.join(root_dir, 'binary-no-muddle-makefile') muddle([ 'distribute', '-no-muddle-makefile', '_binary_release', target_dir ]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same( target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', 'src/*co', # no checkouts other than build 'obj', 'deploy', 'versions', '.muddle/instructions/second_pkg/arm.xml', '.muddle/instructions/second_pkg/fred.xml', '.muddle/tags/deployment', ]) banner('TESTING DISTRIBUTE BINARY RELEASE WITH VERSIONS') target_dir = os.path.join(root_dir, 'binary-with-versions') muddle([ 'distribute', '-with-versions', '_binary_release', target_dir ]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same(target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', '*.c', 'obj', 'deploy', '.muddle/instructions/second_pkg/arm.xml', '.muddle/instructions/second_pkg/fred.xml', '.muddle/tags/deployment', ]) banner('TESTING DISTRIBUTE BINARY RELEASE WITH VERSIONS AND VCS') target_dir = os.path.join(root_dir, 'binary-with-versions-and-vcs') muddle([ 'distribute', '-with-versions', '-with-vcs', '_binary_release', target_dir ]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same(target_dir, onedown=True, unwanted_files=[ 'builds/01.pyc', '*.c', 'src/*_co/.git*', 'obj', 'deploy', '.muddle/instructions/second_pkg/arm.xml', '.muddle/instructions/second_pkg/fred.xml', '.muddle/tags/deployment', ]) banner('TESTING DISTRIBUTE "mixed"') target_dir = os.path.join(root_dir, 'mixed') muddle(['distribute', 'mixed', target_dir]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same( target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', # -- Checkouts 'src/main_co', # We want src/first_co # We want the Makefile.muddle in second_co 'src/second_co/*.c', # -- Domains 'domains', # we don't want any subdomains # -- Packages: obj 'obj/main_pkg', 'obj/first_pkg', # We want obj/second_pkg # -- Not install/ 'install', # -- Deployments 'deploy', # -- Tags # We explicitly want tags for first_co # We implicitly want tags for second_co, # because we have package first_pkg which # depends on it '.muddle/tags/checkout/main_co', '.muddle/tags/package/main_pkg', '.muddle/tags/package/first_pkg', '.muddle/tags/deployment', # but we're not transferring install/, # so we don't want [post]installed tags '.muddle/tags/package/second_pkg/*-*installed', # -- etc '.muddle/instructions/first_pkg', '.muddle/instructions/second_pkg/arm.xml', '.muddle/instructions/second_pkg/fred.xml', 'versions', ]) banner('TESTING DISTRIBUTE "mixed" WITH "-no-muddle-makefile"') # Again, shouldn't make any difference target_dir = os.path.join(root_dir, 'mixed') muddle(['distribute', 'mixed', target_dir]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same( target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', # -- Checkouts 'src/main_co', # We want src/first_co # We want the Makefile.muddle in second_co 'src/second_co/*.c', # -- Domains 'domains', # we don't want any subdomains # -- Packages: obj 'obj/main_pkg', 'obj/first_pkg', # We want obj/second_pkg # -- Not install/ 'install', # -- Deployments 'deploy', # -- Tags # We explicitly want tags for first_co # We implicitly want tags for second_co, # because we have package first_pkg which # depends on it '.muddle/tags/checkout/main_co', '.muddle/tags/package/main_pkg', '.muddle/tags/package/first_pkg', '.muddle/tags/deployment', # but we're not transferring install/, # so we don't want [post]installed tags '.muddle/tags/package/second_pkg/*-*installed', # -- etc '.muddle/instructions/first_pkg', '.muddle/instructions/second_pkg/arm.xml', '.muddle/instructions/second_pkg/fred.xml', 'versions', ]) banner('TESTING DISTRIBUTE "role-x86"') target_dir = os.path.join(root_dir, 'role-x86') muddle(['distribute', 'role-x86', target_dir]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same( target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', 'deploy', '.muddle/tags/deployment', 'domains', # we didn't ask for subdomains 'versions', '.muddle/instructions/second_pkg/arm.xml', '.muddle/instructions/second_pkg/fred.xml', # We only want role x86, not role arm '.muddle/tags/package/main_pkg/arm-*', 'obj/main_pkg/arm', 'install/arm', ]) banner('TESTING DISTRIBUTE "vertical"') target_dir = os.path.join(root_dir, 'vertical') muddle(['distribute', 'vertical', target_dir]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same( target_dir, onedown=True, unwanted_files=[ '.git*', 'builds/01.pyc', # -- Checkouts 'src/main_co', 'src/first_co', # We want src/second_co # -- Packages: obj 'obj/main_pkg', 'obj/first_pkg', # We want obj/second_pkg # -- Packages: install 'install/arm', # We want install/x86/second, but have no # way to stop getting ALL of install/x86 # -- Subdomains # We've not asked for owt in subdomain2 'domains/subdomain2', # -- Deployments 'deploy', # -- Tags # We want tags for second_co and second_pkg '.muddle/tags/checkout/main_co', '.muddle/tags/checkout/first_co', '.muddle/tags/package/main_pkg', '.muddle/tags/package/first_pkg', '.muddle/tags/deployment', # -- etc '.muddle/instructions/first_pkg', '.muddle/instructions/second_pkg/arm.xml', '.muddle/instructions/second_pkg/fred.xml', 'versions', ]) banner('TESTING DISTRIBUTE "vertical" WITH VCS AND VERSIONS') target_dir = os.path.join(root_dir, 'vertical-with-vcs-and-versions') # Remember, we're asking for VCS in the build description and version # directories, but not changing what the build description says for # explicitly asked for checkouts... muddle([ 'distribute', '-with-vcs', '-with-versions', 'vertical', target_dir ]) dt = DirTree(d.where, fold_dirs=['.git']) dt.assert_same( target_dir, onedown=True, unwanted_files=[ 'builds/01.pyc', # -- Checkouts 'src/main_co', 'src/first_co', # We want src/second_co, but we didn't # ask for its VCS 'src/second_co/.git*', # -- Packages: obj 'obj/main_pkg', 'obj/first_pkg', # We want obj/second_pkg # -- Packages: install 'install/arm', # We want install/x86/second, but have no # way to stop getting ALL of install/x86 # -- Subdomains # We've not asked for owt in subdomain2 'domains/subdomain2', # -- Deployments 'deploy', # -- Tags # We want tags for second_co and second_pkg '.muddle/tags/checkout/main_co', '.muddle/tags/checkout/first_co', '.muddle/tags/package/main_pkg', '.muddle/tags/package/first_pkg', '.muddle/tags/deployment', # -- etc '.muddle/instructions/first_pkg', '.muddle/instructions/second_pkg/arm.xml', '.muddle/instructions/second_pkg/fred.xml', ])
def make_repos_with_subdomain(root_dir): """Create git repositories for our subdomain tests. """ repo = os.path.join(root_dir, 'repo') with NewDirectory('repo'): with NewDirectory('main'): with NewDirectory('builds') as d: make_build_desc(d.where, TOPLEVEL_BUILD_DESC.format(repo=repo)) with NewDirectory('co0') as d: make_standard_checkout(d.where, 'main0', 'main') with NewDirectory('sub1'): with NewDirectory('builds') as d: make_build_desc(d.where, sub1_BUILD_DESC.format(repo=repo)) with NewDirectory('co0') as d: make_standard_checkout(d.where, 'sub1', 'sub1') with NewDirectory('sub2'): with NewDirectory('builds') as d: make_build_desc(d.where, sub2_BUILD_DESC.format(repo=repo)) with NewDirectory('co0') as d: make_standard_checkout(d.where, 'sub2', 'sub2') with NewDirectory('sub3'): with NewDirectory('builds') as d: make_build_desc(d.where, sub3_BUILD_DESC) with NewDirectory('co0') as d: make_standard_checkout(d.where, 'sub3', 'sub3') with NewDirectory('sub4'): with NewDirectory('builds') as d: make_build_desc(d.where, sub4_BUILD_DESC) with NewDirectory('co0') as d: make_standard_checkout(d.where, 'sub4', 'sub4') with NewDirectory('sub5'): with NewDirectory('builds') as d: make_build_desc(d.where, sub5_BUILD_DESC) with NewDirectory('co0') as d: make_standard_checkout(d.where, 'sub5', 'sub5')
def make_new_build_tree(): """Make a build tree that creates a CPIO file in a package, and use/test it """ with NewDirectory('build.new') as d: muddle(['bootstrap', 'git+file:///nowhere', 'cpio-test-build']) with Directory('src'): with Directory('builds'): touch('01.py', PACKAGE_BUILD_DESC_12) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') with NewDirectory('first_co'): git('init') touch('Makefile.muddle', MUDDLE_MAKEFILE1.format(progname='program1')) touch('program1.c', MAIN_C_SRC.format(progname='program1')) touch('instructions.xml', INSTRUCTIONS) git('add Makefile.muddle program1.c instructions.xml') git('commit -m "A commit"') muddle(['import']) with NewDirectory('second_co'): git('init') touch( 'Makefile.muddle', MUDDLE_MAKEFILE2.format(progname1='program1', progname2='program2')) touch('program2.c', MAIN_C_SRC.format(progname='program2')) # A version of program1 that announces itself as program2 touch('program1.c', MAIN_C_SRC.format(progname='program2')) git('add Makefile.muddle program2.c') git('commit -m "A commit"') muddle(['import']) muddle([]) # Magically, we have package output with no corresponding checkout. with Directory('install'): with Directory('x86-cpiofile'): with Directory('fred'): check_cpio_archive('firmware.cpio') # Check we got the correct version of program1 extract_file('firmware.cpio', '/bin/program1') text = get_stdout('bin/program1') if text != 'Program program2\n': raise GiveUp( 'Expected the program1 from role2, but it output %s' % text) print 'That looks like the correct program1' # Now let's try requesting the roles in the other order with Directory('src'): with Directory('builds'): touch('01.py', PACKAGE_BUILD_DESC_21) # Then remove the .pyc file, because Python probably won't # realise that this new 01.py is later than the previous # version os.remove('01.pyc') muddle(['veryclean']) muddle([]) with Directory('install'): with Directory('x86-cpiofile'): with Directory('fred'): check_cpio_archive('firmware.cpio') # Check we got the other version of program1 extract_file('firmware.cpio', '/bin/program1') text = get_stdout('bin/program1') if text != 'Program program1\n': raise GiveUp( 'Expected the program1 from role1, but it output %s' % text) print 'That looks like the correct program1'
def make_old_build_tree(): """Make a build tree that does a squashfs deployment, and use/test it """ with NewDirectory('build.old') as d: muddle(['bootstrap', 'git+file:///nowhere', 'cpio-test-build']) with Directory('src'): with Directory('builds'): touch('01.py', DEPLOYMENT_BUILD_DESC_12) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') with NewDirectory('first_co'): git('init') touch('Makefile.muddle', MUDDLE_MAKEFILE1.format(progname='program1')) touch('program1.c', MAIN_C_SRC.format(progname='program1')) touch('instructions.xml', INSTRUCTIONS) os.makedirs('etc/init.d') touch('etc/init.d/rcS', '# A pretend rcS file\n') git('add Makefile.muddle program1.c instructions.xml') git('commit -m "A commit"') muddle(['import']) with NewDirectory('second_co'): git('init') touch( 'Makefile.muddle', MUDDLE_MAKEFILE2.format(progname1='program1', progname2='program2')) touch('program2.c', MAIN_C_SRC.format(progname='program2')) # A version of program1 that announces itself as program2 touch('program1.c', MAIN_C_SRC.format(progname='program2')) git('add Makefile.muddle program2.c') git('commit -m "A commit"') muddle(['import']) muddle([]) with Directory('deploy'): with Directory('everything'): shell('unsquashfs -d result root.squashfs') dt = DirTree('result') dt.assert_same_as_list([ ' bin/', ' program1*', ' program2*', ' etc/', ' init.d/', ' rcS', ' objfiles/', ' program1*', ], "expected", onedown=True) with Directory('result'): with Directory('bin'): text = get_stdout('./program1') if text != 'Program program2\n': raise GiveUp( 'Expected the bin/program1 from role2, but it output %s' % text) text = get_stdout('./program2') if text != 'Program program2\n': raise GiveUp('Wrong output from bin/program2: %s' % text) with Directory('objfiles'): text = get_stdout('./program1') if text != 'Program program1\n': raise GiveUp( 'Expected objfiles/the program1 from role1, but it output %s' % text) # Now let's try requesting the roles in the other order with Directory('src'): with Directory('builds'): touch('01.py', DEPLOYMENT_BUILD_DESC_21) # Then remove the .pyc file, because Python probably won't # realise that this new 01.py is later than the previous # version os.remove('01.pyc') muddle(['veryclean']) muddle([]) with Directory('deploy'): with Directory('everything'): shell('unsquashfs -d result root.squashfs') dt = DirTree('result') dt.assert_same_as_list([ ' bin/', ' program1*', ' program2*', ' etc/', ' init.d/', ' rcS', ' objfiles/', ' program1*', ], "expected", onedown=True) with Directory('result'): with Directory('bin'): text = get_stdout('./program1') if text != 'Program program1\n': raise GiveUp( 'Expected the bin/program1 from role1, but it output %s' % text) text = get_stdout('./program2') if text != 'Program program2\n': raise GiveUp('Wrong output from bin/program2: %s' % text) with Directory('objfiles'): # The file from the obj directory should, of course, behave # just as it did before text = get_stdout('./program1') if text != 'Program program1\n': raise GiveUp( 'Expected objfiles/the program1 from role1, but it output %s' % text)
def make_old_build_tree(): """Make a build tree that does filedep deployment, and use/test it """ with NewDirectory('build.old') as d: muddle(['bootstrap', 'git+file:///nowhere', 'cpio-test-build']) with Directory('src'): with Directory('builds'): touch('01.py', DEPLOYMENT_BUILD_DESC_12) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') with NewDirectory('first_co'): git('init') touch('Makefile.muddle', MUDDLE_MAKEFILE1.format(progname='program1')) touch('program1.c', MAIN_C_SRC.format(progname='program1')) touch('instructions.xml', INSTRUCTIONS) os.makedirs('etc/init.d') touch('etc/init.d/rcS', '# A pretend rcS file\n') git('add Makefile.muddle program1.c instructions.xml') git('commit -m "A commit"') muddle(['import']) with NewDirectory('second_co'): git('init') touch( 'Makefile.muddle', MUDDLE_MAKEFILE2.format(progname1='program1', progname2='program2')) touch('program2.c', MAIN_C_SRC.format(progname='program2')) # A version of program1 that announces itself as program2 touch('program1.c', MAIN_C_SRC.format(progname='program2')) git('add Makefile.muddle program2.c') git('commit -m "A commit"') muddle(['import']) muddle([]) shell('ls -lR deploy') dt = DirTree('deploy') dt.assert_same_as_list([ ' everything/', ' bin/', ' program1*', ' program2*', ' dev/', ], "expected", onedown=True) with Directory('deploy'): with Directory('everything'): with Directory('bin'): text = get_stdout('./program1') if text != 'Program program2\n': raise GiveUp( 'Expected the bin/program1 from role2, but it output %s' % text) text = get_stdout('./program2') if text != 'Program program2\n': raise GiveUp('Wrong output from bin/program2: %s' % text) # And the MUDDLE_TARGET_LOCATION environment variable should be set # for the packages in the appropriate roles text = captured_muddle(['query', 'env', 'package:*{role1}']) if text.find('MUDDLE_TARGET_LOCATION=targetdir') == -1: raise GiveUp( 'Cannot see correct MUDDLE_TARGET_LOCATION in role1 environment:\n%s' % text) text = captured_muddle(['query', 'env', 'package:*{role2}']) if text.find('MUDDLE_TARGET_LOCATION=targetdir') == -1: raise GiveUp( 'Cannot see correct MUDDLE_TARGET_LOCATION in role2 environment:\n%s' % text) # Now let's try requesting the roles in the other order with Directory('src'): with Directory('builds'): touch('01.py', DEPLOYMENT_BUILD_DESC_21) # Then remove the .pyc file, because Python probably won't # realise that this new 01.py is later than the previous # version os.remove('01.pyc') muddle(['veryclean']) muddle([]) with Directory('deploy'): with Directory('everything'): with Directory('bin'): text = get_stdout('./program1') if text != 'Program program1\n': raise GiveUp( 'Expected the bin/program1 from role1, but it output %s' % text) text = get_stdout('./program2') if text != 'Program program2\n': raise GiveUp('Wrong output from bin/program2: %s' % text)
def test_just_pulled(): root_dir = normalise_dir(os.getcwd()) # Set up our repository with NewDirectory('repo'): shell('svnadmin create main') root_repo = 'file://' + os.path.join(root_dir, 'repo', 'main') banner('Repository') with NewDirectory('build_0'): muddle(['bootstrap', 'svn+%s' % root_repo, 'test_build']) with Directory('src'): with Directory('builds'): touch('01.py', CHECKOUT_BUILD_SVN_NO_REVISIONS) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') svn('import . %s/builds -m "Initial import"' % root_repo) with TransientDirectory('checkout1'): touch('Makefile.muddle', '# A comment\n') svn('import . %s/checkout1 -m "Initial import"' % root_repo) banner('Build A') with NewDirectory('build_A'): muddle(['init', 'svn+%s' % root_repo, 'builds/01.py']) muddle(['checkout', '_all']) banner('Build B') with NewDirectory('build_B'): muddle(['init', 'svn+%s' % root_repo, 'builds/01.py']) muddle(['checkout', '_all']) banner('Change Build A') with Directory('build_A'): with Directory('src'): with Directory('builds'): append('01.py', '# Just a comment\n') # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') svn('commit -m "A simple change"') muddle(['push']) with Directory('checkout1'): append('Makefile.muddle', '# Just a comment\n') svn('commit -m "A simple change"') muddle(['push']) banner('Pull into Build B') with Directory('build_B') as d: _just_pulled_file = os.path.join(d.where, '.muddle', '_just_pulled') if os.path.exists(_just_pulled_file): raise GiveUp('%s exists when it should not' % _just_pulled_file) muddle(['pull', '_all']) if not same_content( _just_pulled_file, 'checkout:builds/checked_out\n' 'checkout:checkout1/checked_out\n'): raise GiveUp( '%s does not contain expected labels:\n%s' % (_just_pulled_file, open(_just_pulled_file).readlines())) muddle(['pull', '_all']) if not same_content(_just_pulled_file, ''): raise GiveUp('%s should be empty, but is not' % _just_pulled_file)
def create_multiplex_repo(build_name): """Creates repositories for checkouts 'builds', 'co1' .. 'co.branch1.fred' Assumes that we are already in an appropriate directory. Returns the path to the 'src' directory, which is the repo_root to use. """ muddle(['bootstrap', 'git+file:///nowhere', 'test-build']) with Directory('src') as src: with Directory('builds') as builds: # Remove the .pyc file, because Python probably won't realise # that our new 01.py is/are later than the previous version os.remove('01.pyc') touch('01.py', EMPTY_BUILD_DESC) git('commit -a -m "Empty-ish build description"') # ---- branch0 git('checkout -b branch0') touch('01.py', NO_BZR_BUILD_DESC) git('commit -a -m "More interesting build description"') # ---- branch1 git('checkout -b branch1') touch('01.py', NONFOLLOW_BUILD_DESC) git('commit -a -m "More interesting build description"') # ---- branch.follow git('checkout -b branch.follow') touch('01.py', FOLLOW_BUILD_DESC) git('commit -a -m "A following build description"') with NewDirectory('co1'): touch('Makefile.muddle', MUDDLE_MAKEFILE) git('init') git('add Makefile.muddle') git('commit Makefile.muddle -m "A checkout needs a makefile"') # ---- branch1 git('checkout -b branch1') touch('README.txt', EMPTY_README_TEXT) git('add README.txt') git('commit -m "And a README"') # ---- branch.follow git('checkout -b branch.follow') touch('program1.c', EMPTY_C_FILE) git('add program1.c') git('commit -m "And a program"') with NewDirectory('co.branch1'): touch('Makefile.muddle', MUDDLE_MAKEFILE) git('init') git('add Makefile.muddle') git('commit Makefile.muddle -m "A checkout needs a makefile"') # ---- branch1 git('checkout -b branch1') touch('README.txt', EMPTY_README_TEXT) git('add README.txt') git('commit -m "And a README"') # ---- branch.follow git('checkout -b branch.follow') touch('program2.c', EMPTY_C_FILE) git('add program2.c') git('commit -m "And a program"') with NewDirectory('co.fred'): touch('Makefile.muddle', MUDDLE_MAKEFILE) git('init') git('add Makefile.muddle') git('commit Makefile.muddle -m "A checkout needs a makefile"') # ---- branch1 git('checkout -b branch1') touch('README.txt', EMPTY_README_TEXT) git('add README.txt') git('commit -m "And a README"') # ---- branch.follow git('checkout -b branch.follow') touch('program3.c', EMPTY_C_FILE) git('add program3.c') git('commit -m "And a program"') # --- tag fred git('tag fred') with NewDirectory('co.branch1.fred'): touch('Makefile.muddle', MUDDLE_MAKEFILE) git('init') git('add Makefile.muddle') git('commit Makefile.muddle -m "A checkout needs a makefile"') # ---- branch1 git('checkout -b branch1') touch('README.txt', EMPTY_README_TEXT) git('add README.txt') git('commit -m "And a README"') # ---- branch.follow git('checkout -b branch.follow') touch('program4.c', EMPTY_C_FILE) git('add program4.c') git('commit -m "And a program"') # --- tag fred git('tag fred') with NewDirectory('co.bzr'): # -- revision 1 touch('Makefile.muddle', MUDDLE_MAKEFILE) bzr('init') bzr('add Makefile.muddle') bzr('commit Makefile.muddle -m "A checkout needs a makefile"') # -- revision 2 touch('README.txt', EMPTY_README_TEXT) bzr('add README.txt') bzr('commit README.txt -m "And a README"') # -- revision 3 touch('program5.c', EMPTY_C_FILE) bzr('add program5.c') bzr('commit program5.c -m "And a program"') with NewDirectory('co6'): touch('Makefile.muddle', MUDDLE_MAKEFILE) git('init') git('add Makefile.muddle') git('commit Makefile.muddle -m "A checkout needs a makefile"') # ---- branch1 git('checkout -b branch1') touch('README.txt', EMPTY_README_TEXT) git('add README.txt') git('commit -m "And a README"') # --- but we don't have a branch.follow repo = src.where return repo
def make_repos_with_subdomain(repo): """Create git repositories for our subdomain tests. """ with NewDirectory('repo'): with NewDirectory('main'): with NewDirectory('builds') as d: make_build_desc(d.where, TOPLEVEL_BUILD_DESC.format(repo=repo)) with NewDirectory('main_co') as d: make_standard_checkout(d.where, 'main0', 'main') with NewDirectory('first_co') as d: make_standard_checkout(d.where, 'first', 'first') with NewDirectory('second_co') as d: make_bzr_standard_checkout(d.where, 'second', 'second') with NewDirectory('subdomain1'): with NewDirectory('builds') as d: make_build_desc(d.where, SUBDOMAIN1_BUILD_DESC.format(repo=repo)) with NewDirectory('main_co') as d: make_standard_checkout(d.where, 'subdomain1', 'subdomain1') with NewDirectory('first_co') as d: make_standard_checkout(d.where, 'first', 'first') with NewDirectory('second_co') as d: make_standard_checkout(d.where, 'second', 'second') with NewDirectory('subdomain2'): with NewDirectory('builds') as d: make_build_desc(d.where, SUBDOMAIN2_BUILD_DESC.format(repo=repo)) with NewDirectory('main_co') as d: make_standard_checkout(d.where, 'subdomain2', 'subdomain2') with NewDirectory('first_co') as d: make_standard_checkout(d.where, 'first', 'first') with NewDirectory('second_co') as d: make_standard_checkout(d.where, 'second', 'second') with NewDirectory('subdomain3'): with NewDirectory('builds') as d: make_build_desc(d.where, SUBDOMAIN3_BUILD_DESC) with NewDirectory('main_co') as d: make_standard_checkout(d.where, 'subdomain3', 'subdomain3') with NewDirectory('first_co') as d: make_standard_checkout(d.where, 'first', 'first') with NewDirectory('second_co') as d: make_standard_checkout(d.where, 'second', 'second')
def test_lifecycle(root_d): """A linear sequence of plausible actions... """ # Repositories with NewCountedDirectory('repos') as d0: with NewDirectory('builds'): git('init --bare') with NewDirectory('co1'): git('init --bare') with NewDirectory('versions'): git('init --bare') repo_url = 'git+file://%s' % d0.where build_name = 'TestBuild' # First build tree with NewCountedDirectory('build1') as d1: muddle(['bootstrap', repo_url, build_name]) with Directory('src'): with Directory('builds'): os.remove('01.py') os.remove('01.pyc') touch('01.py', BUILD_DESC.format(build_name=build_name)) git('add 01.py' ) # Because we changed it since the last 'git add' git('commit -m "First commit of build description"') muddle(['push']) with NewDirectory('co1'): touch('Makefile.muddle', MUDDLE_MAKEFILE) git('init') git('add Makefile.muddle') git('commit Makefile.muddle -m "A checkout needs a makefile"') muddle(['import']) muddle(['push']) muddle(['stamp', 'version']) with Directory('versions'): check_specific_files_in_this_dir(['.git', 'TestBuild.stamp']) git('add TestBuild.stamp') git('commit -m "First stamp"') muddle(['stamp', 'push']) builds_rev_1 = captured_muddle(['query', 'checkout-id', 'builds']).strip() checkout_rev_1 = captured_muddle(['query', 'checkout-id', 'co1']).strip() # Add some more revisions, so we have something to work with with Directory('src'): with Directory('builds'): append('01.py', '# Additional comment number 1\n') git('add 01.py') git('commit -m "Add comment number 1"') builds_rev_2 = captured_muddle(['query', 'checkout-id']).strip() append('01.py', '# Additional comment number 2\n') git('commit -a -m "Add comment number 2"') builds_rev_3 = captured_muddle(['query', 'checkout-id']).strip() muddle(['push']) with Directory('co1'): append('Makefile.muddle', '# Additional comment number 1\n') git('add Makefile.muddle') git('commit -m "Add comment number 1"') checkout_rev_2 = captured_muddle(['query', 'checkout-id']).strip() append('Makefile.muddle', '# Additional comment number 2\n') git('commit -a -m "Add comment number 2"') checkout_rev_3 = captured_muddle(['query', 'checkout-id']).strip() muddle(['push']) # Find out what branches we are working with text = captured_muddle(['query', 'checkout-branches']) lines = text.splitlines() lines = lines[3:] # ignore the header lines check_text_lines_v_lines(lines, [ "builds master <none> <not following>", "co1 master <none> <not following>" ], fold_whitespace=True) print 'builds/' print ' ', builds_rev_1 print ' ', builds_rev_2 print ' ', builds_rev_3 print 'co1/' print ' ', checkout_rev_1 print ' ', checkout_rev_2 print ' ', checkout_rev_3 # Second build tree, where the build description gives a specific revision # for a checkout. with NewCountedDirectory('build2') as d2: muddle(['init', repo_url, 'builds/01.py']) # But we want to specify the revision for our source checkout with Directory(d2.join('src', 'builds')): # Note we don't need to specify ALL of the SHA1 string, we can # just specify some non-ambiguous subset... touch( '01.py', BUILD_DESC_WITH_REVISION.format(revision=checkout_rev_2[:8], build_name=build_name)) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') muddle(['checkout', '_all']) check_revision('co1', checkout_rev_2) # If we attempt to 'muddle pull' in the checkout, that should fail # because we are already at the requested revision text = captured_muddle(['pull', 'co1'], error_fails=False).strip() if not text.endswith('checkout past the specified revision.'): raise GiveUp( 'Expected muddle pull to fail trying to go "past" revision:\n%s' % text) # Merging should behave just the same text = captured_muddle(['merge', 'co1'], error_fails=False).strip() if not text.endswith('checkout past the specified revision.'): raise GiveUp( 'Expected muddle pull to fail trying to go "past" revision:\n%s' % text) # What if the checkout is at the wrong revision? (e.g., someone used # git explicitly to change it, or equally we changed the build description # itself). # All muddle can really do is go to the revision specified in the # build description... with Directory(d2.join('src', 'co1')): git('checkout %s' % checkout_rev_1) muddle(['pull']) check_revision('co1', checkout_rev_2) git('checkout %s' % checkout_rev_1) muddle(['merge']) check_revision('co1', checkout_rev_2) # What if we try to do work on that specified revision # (and, in git terms, at a detached HEAD) with Directory(d2.join('src', 'co1')): append('Makefile.muddle', '# Additional comment number 3\n') git('commit -a -m "Add comment number 3"') checkout_rev_4 = captured_muddle(['query', 'checkout-id']).strip() # We're not on a branch, so that commit is likely to get lost, # so we'd better allow the user ways of being told that # - muddle status should say something rc, text = captured_muddle2(['status']) if 'Note that this checkout has a detached HEAD' not in text: raise GiveUp('Expected to be told checkout is in detached' ' HEAD state, instead got:\n%s' % text) # And trying to push should fail rc, text = captured_muddle2(['push']) text = text.strip() if 'This checkout is in "detached HEAD" state' not in text: raise GiveUp('Expected to be told checkout is in detached' ' HEAD state, instead got:\n%s' % text) print 'co1/' print ' ', checkout_rev_1 print ' ', checkout_rev_2 print ' ', checkout_rev_3 print ' ', checkout_rev_4 # So fix that by using a branch checkout_branch = 'this-is-a-branch' with Directory('src'): with Directory('builds'): touch( '01.py', BUILD_DESC_WITH_BRANCH.format(branch=checkout_branch, build_name=build_name)) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') with Directory('co1'): git('checkout -b %s' % checkout_branch) muddle(['status']) muddle(['push']) check_revision('co1', checkout_rev_4) # Find out what branches we are working with text = captured_muddle(['query', 'checkout-branches']) lines = text.splitlines() lines = lines[3:] # ignore the header lines check_text_lines_v_lines(lines, [ "builds master <none> <not following>", "co1 this-is-a-branch this-is-a-branch <not following>" ], fold_whitespace=True) # What happens if we specify a revision on a branch? # First, choose the revision before the branch with Directory('src'): with Directory('builds'): touch( '01.py', BUILD_DESC_WITH_REVISION.format(revision=checkout_rev_3, build_name=build_name)) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') with Directory('co1'): muddle(['status']) # Doing 'muddle pull' is the obvious way to get us back to # the right revision muddle(['pull']) check_revision('co1', checkout_rev_3) # Because we specified an exact revision, we should be detached if not is_detached_head(): raise GiveUp('Expected to have a detached HEAD') # Find out what branches we are working with text = captured_muddle(['query', 'checkout-branches']) lines = text.splitlines() lines = lines[3:] # ignore the header lines check_text_lines_v_lines(lines, [ "builds master <none> <not following>", "co1 <none> <none> <not following>" ], fold_whitespace=True) # Then the revision after the branch with Directory('src'): with Directory('builds'): touch( '01.py', BUILD_DESC_WITH_REVISION.format(revision=checkout_rev_4, build_name=build_name)) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') with Directory('co1'): # We're still on the old revision, and detached check_revision('co1', checkout_rev_3) # Because we specified an exact revision, we should be detached if not is_detached_head(): raise GiveUp('Expected to have a detached HEAD') rc, text = captured_muddle2(['status']) if 'Note that this checkout has a detached HEAD' not in text: raise GiveUp('Expected to be told checkout is in detached' ' HEAD state, instead got:\n%s' % text) # Doing 'muddle pull' is the obvious way to get us back to # the right revision muddle(['pull']) check_revision('co1', checkout_rev_4) # Because we specified an exact revision, we should be detached if not is_detached_head(): raise GiveUp('Expected to have a detached HEAD') # But what if we go to "the same place" by a different means? git('checkout %s' % checkout_branch) muddle(['status']) # We're still at the requested revision check_revision('co1', checkout_rev_4) # But we're no longer a detached HEAD if is_detached_head(): raise GiveUp('Surprised to have a detached HEAD') # muddle pull shouldn't need to do anything... text = captured_muddle(['pull'], error_fails=False).strip() if not text.endswith('checkout past the specified revision.'): raise GiveUp( 'Expected muddle pull to fail trying to go "past" revision:\n%s' % text) # Find out what branches we are working with text = captured_muddle(['query', 'checkout-branches']) lines = text.splitlines() lines = lines[3:] # ignore the header lines check_text_lines_v_lines(lines, [ "builds master <none> <not following>", "co1 this-is-a-branch <none> <not following>" ], fold_whitespace=True) # Third build tree, investigating use of "muddle branch-tree" with NewCountedDirectory('build3') as d3: muddle(['init', repo_url, 'builds/01.py']) muddle(['checkout', '_all']) # Check the branches of our checkouts check_branch('src/builds', 'master') check_branch('src/co1', 'master') # And change it muddle(['branch-tree', 'test-v0.1']) # Check the branches of our checkouts - since this isn't using muddle, # it should still show both at the new branch check_branch('src/builds', 'test-v0.1') check_branch('src/co1', 'test-v0.1') # Doing a "mudddle sync" on the checkout should put it back to the # master branch, as that's what is (implicitly) asked for in the # build description. It shouldn't affect the build description. muddle(['sync', 'co1']) check_branch('src/builds', 'test-v0.1') check_branch('src/co1', 'master') # If we amend the build description, though: print 'Setting build description for "follow my branch"' with Directory('src'): with Directory('builds'): append('01.py', ' builder.follow_build_desc_branch = True\n') # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') # and sync again, our checkout should now follow the build # description's branch muddle(['sync', 'co1']) check_branch('src/builds', 'test-v0.1') check_branch('src/co1', 'test-v0.1') # Let's commit and push... with Directory('src'): with Directory('builds'): git('commit -a -m "Branched"') muddle(['push']) with Directory('co1'): # We hadn't changed any files in our checkout muddle(['push']) # Find out what branches we are working with text = captured_muddle(['query', 'checkout-branches']) lines = text.splitlines() lines = lines[3:] # ignore the header lines check_text_lines_v_lines(lines, [ "builds test-v0.1 <none> <it's own>", "co1 test-v0.1 <none> test-v0.1" ], fold_whitespace=True) # And a variant like the documentation with NewCountedDirectory('build4') as d4: muddle(['init', repo_url, 'builds/01.py']) muddle(['checkout', '_all']) # And change it muddle(['branch-tree', 'Widget-v0.1-maintenance']) with Directory('src'): with Directory('builds'): append('01.py', ' builder.follow_build_desc_branch = True\n') # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') muddle([ 'runin', '_all_checkouts', 'git commit -a -m "Create maintenance branch"' ]) muddle(['push', '_all']) # Find out what branches we are working with text = captured_muddle(['query', 'checkout-branches']) lines = text.splitlines() lines = lines[3:] # ignore the header lines check_text_lines_v_lines(lines, [ "builds Widget-v0.1-maintenance <none> <it's own>", "co1 Widget-v0.1-maintenance <none> Widget-v0.1-maintenance" ], fold_whitespace=True) muddle(['stamp', 'version']) with Directory('versions'): check_specific_files_in_this_dir( ['.git', 'TestBuild.Widget-v0.1-maintenance.stamp']) with NewCountedDirectory('build4a') as d4a: muddle([ 'unstamp', d4.join('versions', 'TestBuild.Widget-v0.1-maintenance.stamp') ]) # Check we're working with the expected branches text = captured_muddle(['query', 'checkout-branches']) lines = text.splitlines() lines = lines[3:] # ignore the header lines check_text_lines_v_lines(lines, [ "builds Widget-v0.1-maintenance Widget-v0.1-maintenance <it's own>", "co1 Widget-v0.1-maintenance <none> Widget-v0.1-maintenance" ], fold_whitespace=True) muddle(['stamp', 'version']) with Directory('versions'): check_specific_files_in_this_dir( ['.git', 'TestBuild.Widget-v0.1-maintenance.stamp']) # And that stamp file should be identical to the one we had before # (if we ignore the first few lines with the timestamp comments) with open( d4.join('versions', 'TestBuild.Widget-v0.1-maintenance.stamp')) as fd: that = fd.readlines() with open( os.path.join('versions', 'TestBuild.Widget-v0.1-maintenance.stamp')) as fd: this = fd.readlines() check_text_lines_v_lines(actual_lines=this[3:], wanted_lines=that[3:]) with NewCountedDirectory('build5') as d5: muddle([ 'init', '-branch', 'Widget-v0.1-maintenance', repo_url, 'builds/01.py' ]) muddle(['checkout', '_all']) # Find out what branches we are working with text = captured_muddle(['query', 'checkout-branches']) lines = text.splitlines() lines = lines[3:] # ignore the header lines check_text_lines_v_lines(lines, [ "builds Widget-v0.1-maintenance Widget-v0.1-maintenance <it's own>", "co1 Widget-v0.1-maintenance <none> Widget-v0.1-maintenance" ], fold_whitespace=True) muddle(['stamp', 'version']) with Directory('versions'): check_specific_files_in_this_dir( ['.git', 'TestBuild.Widget-v0.1-maintenance.stamp']) # And that stamp file should also be identical to the one we had before # (if we ignore the first few lines with the timestamp comments) with open( d4.join('versions', 'TestBuild.Widget-v0.1-maintenance.stamp')) as fd: that = fd.readlines() with open( os.path.join('versions', 'TestBuild.Widget-v0.1-maintenance.stamp')) as fd: this = fd.readlines() check_text_lines_v_lines(actual_lines=this[3:], wanted_lines=that[3:]) # Now let's push a change with Directory('src'): with Directory('co1'): append('Makefile.muddle', '# This, this is not a change\n') git('commit Makefile.muddle -m "But a small thing"') muddle(['push']) co1_revision_id = captured_muddle(['query', 'checkout-id', 'co1']).strip() # And pull it elsewhere with Directory(d4a.join('src', 'co1')): old_revision_id = captured_muddle(['query', 'checkout-id']).strip() muddle(['pull']) new_revision_id = captured_muddle(['query', 'checkout-id']).strip() if old_revision_id == new_revision_id: raise GiveUp('Pull did nothing') if new_revision_id != co1_revision_id: raise GiveUp('Result of pull was unexpected\n' 'got: %s\nnot: %s' % (new_revision_id, co1_revision_id)) # And let's be really awkward... with Directory(d4.join('src', 'co1')): git('checkout master') rv, text = run2('git branch') check_text_v_lines(text, [' Widget-v0.1-maintenance', '* master']) old_revision_id = captured_muddle(['query', 'checkout-id']).strip() # We're fondly expecting "muddle pull" to put us back onto the # "following" branch muddle(['pull']) rv, text = run2('git branch') check_text_v_lines(text, ['* Widget-v0.1-maintenance', ' master']) new_revision_id = captured_muddle(['query', 'checkout-id']).strip() if old_revision_id == new_revision_id: raise GiveUp('Pull did nothing') if new_revision_id != co1_revision_id: raise GiveUp('Result of pull was unexpected\n' 'got: %s\nnot: %s' % (new_revision_id, co1_revision_id))
def test_svn_revisions_build(): """Test a build tree where a checkout has a specific revision Doing 'muddle pull' or 'muddle merge' in such a directory should not update it. """ root_dir = normalise_dir(os.getcwd()) with NewDirectory('repo'): shell('svnadmin create main') root_repo = 'file://' + os.path.join(root_dir, 'repo', 'main') with NewDirectory('test_build1'): banner('Bootstrapping SVN revisions build') muddle(['bootstrap', 'svn+%s' % root_repo, 'test_build']) with Directory('src'): with Directory('builds'): touch('01.py', CHECKOUT_BUILD_SVN_REVISIONS) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') svn('import . %s/builds -m "Initial import"' % root_repo) # Is the next really the best we can do? shell('rm -rf builds') svn('checkout %s/builds' % root_repo) with TransientDirectory('checkout1'): touch('Makefile.muddle', '# A comment\n') svn('import . %s/checkout1 -m "Initial import"' % root_repo) svn('checkout %s/checkout1' % root_repo) with Directory('checkout1'): touch('Makefile.muddle', '# A different comment\n') svn('commit -m "Second version of Makefile.muddle"') shell('svnversion') with Directory('checkout1'): touch('Makefile.muddle', '# Yet another different comment\n') svn('commit -m "Third version of Makefile.muddle"') shell('svnversion') # We should be able to check everything out from the repository with NewDirectory('test_build2'): banner('Building from init') muddle(['init', 'svn+%s' % root_repo, 'builds/01.py']) muddle(['checkout', '_all']) with Directory('src'): with Directory('checkout1'): revno = get_stdout('svnversion').strip() if revno != '2': raise GiveUp('Revision number for checkout1 is %s, not 2' % revno) muddle(['pull']) revno = get_stdout('svnversion').strip() if revno != '2': raise GiveUp( 'Revision number for checkout1 is %s, not 2 (after pull)' % revno) muddle(['merge']) revno = get_stdout('svnversion').strip() if revno != '2': raise GiveUp( 'Revision number for checkout1 is %s, not 2 (after merge)' % revno) # But if we remove the restriction on revision number with Directory('builds'): touch('01.py', CHECKOUT_BUILD_SVN_NO_REVISIONS) # Then remove the .pyc file, because Python probably won't realise # that this new 01.py is later than the previous version os.remove('01.pyc') with Directory('checkout1'): muddle(['pull']) revno = get_stdout('svnversion').strip() if revno != '4': raise GiveUp( 'Revision number for checkout1 is %s, not 4 (after pull)' % revno)