示例#1
0
    def __init__(self,
                 where,
                 stay_on_error=False,
                 show_pushd=True,
                 show_popd=False,
                 set_PWD=True):
        self.start = normalise_dir(os.getcwd())
        self.where = normalise_dir(where)
        self.close_on_error = not stay_on_error
        self.show_pushd = show_pushd
        self.show_popd = show_popd
        self.set_PWD = set_PWD
        try:
            os.chdir(self.where)
        except OSError as e:
            raise GiveUp('Cannot change to directory %s: %s\n' % (where, e))

        if set_PWD:
            if 'PWD' in os.environ:
                self.got_old_PWD = True
                self.old_PWD = os.environ['PWD']
            else:
                self.got_old_PWD = False
                self.old_PWD = None
            os.environ['PWD'] = self.where

        if show_pushd:
            sys.stdout.write('++ pushd to %s\n' % self.where)
示例#2
0
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()
示例#3
0
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'))
    repo = os.path.join(root_dir, 'repo')

    with TransientDirectory(root_dir, keep_on_error=True,
                            keep_anyway=keep) as root_d:

        banner('TESTING CHECKOUT OPTIONS')
        test_options()

        banner('MAKE REPOSITORIES')
        make_repos_with_subdomain(repo)

        first_stamp = test_stamp_unstamp(root_dir)

        test_stamp_is_current_working_set(first_stamp)

        test_unstamp_update_identity_operation(repo, first_stamp)

        test_unstamp_update_2(repo, first_stamp)

        test_stamping_branches(repo)
示例#4
0
def main(args):

    keep = False
    if args:
        if len(args) == 1 and args[0] == '-keep':
            keep = True
        else:
            print __doc__
            return

    root_dir = normalise_dir(os.path.join(os.getcwd(), 'transient'))
    repo = os.path.join(root_dir, 'repo')

    with TransientDirectory(root_dir, keep_on_error=True, keep_anyway=keep) as root_d:

        test_ReleaseStamp_basics(root_d)

        banner('CREATING REPOSITORIES')
        make_repos_with_subdomain(repo)

        test_simple_release(root_d, repo)
        test_test_release(root_d, repo)
        test_guess_version_number(root_d, repo)

        test_issue_249_single_digit_version_number(root_d, repo)
示例#5
0
def main(args):

    keep = False
    if args:
        if len(args) == 1 and args[0] == '-keep':
            keep = True
        else:
            print __doc__
            return

    root_dir = normalise_dir(os.path.join(os.getcwd(), 'transient'))
    repo = os.path.join(root_dir, 'repo')

    with TransientDirectory(root_dir, keep_on_error=True,
                            keep_anyway=keep) as root_d:

        test_ReleaseStamp_basics(root_d)

        banner('CREATING REPOSITORIES')
        make_repos_with_subdomain(repo)

        test_simple_release(root_d, repo)
        test_test_release(root_d, repo)
        test_guess_version_number(root_d, repo)

        test_issue_249_single_digit_version_number(root_d, repo)
示例#6
0
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'))
    repo = os.path.join(root_dir, 'repo')

    with TransientDirectory(root_dir, keep_on_error=True, keep_anyway=keep) as root_d:

        banner('TESTING CHECKOUT OPTIONS')
        test_options()

        banner('MAKE REPOSITORIES')
        make_repos_with_subdomain(repo)

        first_stamp = test_stamp_unstamp(root_dir)

        test_stamp_is_current_working_set(first_stamp)

        test_unstamp_update_identity_operation(repo, first_stamp)

        test_unstamp_update_2(repo, first_stamp)

        test_stamping_branches(repo)
示例#7
0
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()
示例#8
0
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()
示例#9
0
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()
示例#10
0
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'])
示例#11
0
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'])
示例#12
0
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'])
示例#13
0
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'])
示例#14
0
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)
示例#15
0
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)
示例#16
0
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',
        ])
示例#17
0
    def __init__(self, where, stay_on_error=False, show_pushd=True,
                 show_popd=False, set_PWD=True):
        self.start = normalise_dir(os.getcwd())
        self.where = normalise_dir(where)
        self.close_on_error = not stay_on_error
        self.show_pushd = show_pushd
        self.show_popd = show_popd
        self.set_PWD = set_PWD
        try:
            os.chdir(self.where)
        except OSError as e:
            raise GiveUp('Cannot change to directory %s: %s\n'%(where, e))

        if set_PWD:
            if 'PWD' in os.environ:
                self.got_old_PWD = True
                self.old_PWD = os.environ['PWD']
            else:
                self.got_old_PWD = False
                self.old_PWD = None
            os.environ['PWD'] = self.where

        if show_pushd:
            sys.stdout.write('++ pushd to %s\n'%self.where)
示例#18
0
def main(args):

    keep = False
    if args:
        if len(args) == 1 and args[0] == '-keep':
            keep = True
        else:
            print __doc__
            return

    root_dir = normalise_dir(os.path.join(os.getcwd(), 'transient'))

    with TransientDirectory(root_dir, keep_on_error=True, keep_anyway=keep):
        banner('MAKE OLD BUILD TREE')
        make_old_build_tree()
示例#19
0
def main(args):

    keep = False
    if args:
        if len(args) == 1 and args[0] == '-keep':
            keep = True
        else:
            print __doc__
            return

    root_dir = normalise_dir(os.path.join(os.getcwd(), 'transient'))

    with TransientDirectory(root_dir, keep_on_error=True, keep_anyway=keep):
        banner('MAKE OLD BUILD TREE')
        make_old_build_tree()
示例#20
0
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'])
示例#21
0
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'])
示例#22
0
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)
示例#23
0
def main(args):

    keep = False
    if args:
        if len(args) == 1 and args[0] == '-keep':
            keep = True
        else:
            print __doc__
            return

    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('TESTING MUDDLE SUBST')

        test_muddle_subst(root_d)
示例#24
0
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',
                     ])
示例#25
0
def main(args):

    keep = False
    if args:
        if len(args) == 1 and args[0] == '-keep':
            keep = True
        else:
            print __doc__
            return

    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('TESTING MUDDLE SUBST')

        test_muddle_subst(root_d)
示例#26
0
 def __init__(self, where=None, stay_on_error=False, show_pushd=True,
              show_popd=False, set_PWD=True, show_dirops=True):
     self.show_dirops = show_dirops
     if where is None:
         where = tempfile.mkdtemp()
         if show_dirops:     # Obviously, this is a bit of a bluff
             # The extra spaces are to line up with 'pushd to'
             sys.stdout.write('++ mkdir    %s\n'%where)
     else:
         where = normalise_dir(where)
         if os.path.exists(where):
             raise GiveUp('Directory %s already exists'%where)
         if show_dirops:
             # The extra spaces are to line up with 'pushd to'
             sys.stdout.write('++ mkdir    %s\n'%where)
         os.makedirs(where)
     super(NewDirectory, self).__init__(where, stay_on_error, show_pushd,
                                        show_popd, set_PWD)
示例#27
0
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)
示例#28
0
 def __init__(self,
              where=None,
              stay_on_error=False,
              show_pushd=True,
              show_popd=False,
              set_PWD=True,
              show_dirops=True):
     self.show_dirops = show_dirops
     if where is None:
         where = tempfile.mkdtemp()
         if show_dirops:  # Obviously, this is a bit of a bluff
             # The extra spaces are to line up with 'pushd to'
             sys.stdout.write('++ mkdir    %s\n' % where)
     else:
         where = normalise_dir(where)
         if os.path.exists(where):
             raise GiveUp('Directory %s already exists' % where)
         if show_dirops:
             # The extra spaces are to line up with 'pushd to'
             sys.stdout.write('++ mkdir    %s\n' % where)
         os.makedirs(where)
     super(NewDirectory, self).__init__(where, stay_on_error, show_pushd,
                                        show_popd, set_PWD)
示例#29
0
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:
        banner('TEST INIT WITH BRANCH')
        test_init_with_branch(root_d)

        banner('TEST BRANCH-TREE')
        test_branch_tree(root_d)

        banner('TEST LIFECYCLE')
        test_lifecycle(root_d)
示例#30
0
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 NewCountedDirectory('build.original') as d1:
            banner('CHECK REPOSITORIES OUT INTO FIRST BUILD')
            checkout_build_descriptions(root_dir, d1)
            muddle(['checkout', '_all'])
            orig_dir = d1.where

        banner('TEST A SIMPLE CHANGE')
        # With an insignificant change, this should work identically by
        # both mechanisms

        with NewCountedDirectory('build.simple.noreload.pull') as d2:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_build_descriptions(root_dir, d2)
            muddle(['checkout', '_all'])
            pass1_noreload_dir = d2.where

        with NewCountedDirectory('build.simple.default.pull') as d3:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_build_descriptions(root_dir, d3)
            muddle(['checkout', '_all'])
            pass1_default_dir = d3.where

        with Directory(orig_dir) as d:
            banner('AMEND SUB1 BUILD DESCRIPTION AND PUSH', 2)
            amend_sub1_build_desc_and_push(root_dir, d)

        with Directory(pass1_noreload_dir) as d:
            banner('PULL IN THE ORIGINAL MANNER', 2)
            muddle(['pull', '-noreload', '_all'])
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'), [
                'checkout:(sub1)builds/checked_out\n',
            ])

        with Directory(pass1_default_dir) as d:
            banner('PULL WITH BUILD DESCRIPTIONS PULLED FIRST', 2)
            muddle(['pull', '_all'])
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'), [
                'checkout:(sub1)builds/checked_out\n',
            ])

        banner('TEST A MORE COMPLICATED CHANGE')
        # Since we're changing the layout of the build, this should
        # work substantially differently by the two mechanisms

        with NewCountedDirectory('build.swap.noreload.pull') as d2:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_build_descriptions(root_dir, d2)
            muddle(['checkout', '_all'])
            pass2_noreload_dir = d2.where

        with NewCountedDirectory('build.swap.default.pull') as d3:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_build_descriptions(root_dir, d3)
            muddle(['checkout', '_all'])
            pass2_default_dir = d3.where

        with Directory(orig_dir) as d:
            banner('SWAP SUBDOMAIN BUILD DESCRIPTIONS AND PUSH', 2)
            swap_subdomains_and_push(root_dir, d)

        with Directory(pass2_noreload_dir) as d:
            banner('PULL IN THE ORIGINAL MANNER', 2)
            banner('PULL THE FIRST', 3)
            muddle(['pull', '-noreload', '_all'])
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'), [
                'checkout:(sub1)builds/checked_out\n',
                'checkout:(sub2)builds/checked_out\n',
            ])
            banner('PULL THE SECOND', 3)
            # Our *second* pull should bring us to the same place as the
            # single pull with the "slow" mechanism would achieve.
            #
            # Note that it shouldn't matter where in the build tree we
            # do this command from...
            with Directory('src'):
                with Directory('builds'):
                    muddle(['pull', '-noreload', '_all'])
            # We should have files following the amended build description
            check_amended_build_descs(d)
            # But we have not deleted the files from the original description
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'), [
                'checkout:(sub1(sub4))co0/checked_out\n',
                'checkout:(sub1(sub5))co0/checked_out\n',
                'checkout:(sub2(sub3))co0/checked_out\n',
            ])

        with Directory(pass2_default_dir) as d:
            banner('PULL WITH BUILD DESCRIPTIONS PULLED FIRST', 2)
            # Note that it shouldn't matter where in the build tree we
            # do this command from...
            with Directory('src'):
                with Directory('builds'):
                    muddle(['pull', '_all'])
            # We should have files following the amended build description
            check_amended_build_descs(d)
            # But we have not deleted the files from the original description
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'), [
                'checkout:(sub1)builds/checked_out\n',
                'checkout:(sub1(sub4))builds/checked_out\n',
                'checkout:(sub1(sub4))co0/checked_out\n',
                'checkout:(sub1(sub5))builds/checked_out\n',
                'checkout:(sub1(sub5))co0/checked_out\n',
                'checkout:(sub2)builds/checked_out\n',
                'checkout:(sub2(sub3))builds/checked_out\n',
                'checkout:(sub2(sub3))co0/checked_out\n',
            ])

        banner('TEST NOT CHANGING THE BUILD DESCRIPTIONS')
        # This should work identically by both mechanisms

        with NewCountedDirectory('build.nodesc.noreload.pull') as d2:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_amended_build_descriptions(root_dir, d2)
            muddle(['checkout', '_all'])
            pass3_noreload_dir = d2.where

        with NewCountedDirectory('build.nodesc.default.pull') as d3:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_amended_build_descriptions(root_dir, d3)
            muddle(['checkout', '_all'])
            pass3_default_dir = d3.where

        with Directory(orig_dir) as d:
            banner('CHANGE SOMETHING NOT A BUILD DESCRIPTION AND PUSH', 2)
            change_something_else_and_push(root_dir, d)

        with Directory(pass3_noreload_dir) as d:
            banner('PULL IN THE ORIGINAL MANNER', 2)
            muddle(['pull', '-noreload', '_all'])
            check_amended_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'), [
                'checkout:(sub1)co0/checked_out\n',
            ])

        with Directory(pass3_default_dir) as d:
            banner('PULL WITH BUILD DESCRIPTIONS PULLED FIRST', 2)
            muddle(['pull', '_all'])
            check_amended_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'), [
                'checkout:(sub1)co0/checked_out\n',
            ])
示例#31
0
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)
示例#32
0
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))

    print 'Testing utils.decide'

    suite = unittest.TestLoader().loadTestsFromTestCase(TestChoice)
    results = unittest.TextTestRunner().run(suite)

    if not results.wasSuccessful():
        return False

    # 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'))

    def test_aptget(choice, exc_str=None):
        with Directory(os.path.join('src', 'builds')) as srcdir:
            if os.path.exists('01.py'):
                os.remove('01.py')
            if os.path.exists('01.pyc'):
                os.remove('01.pyc')
            touch('01.py', BUILD_DESC%choice)
            rc, text = captured_muddle2(['query', 'checkouts'])
            print text.strip()
            if rc == 0:
                if text.strip() != 'builds':
                    raise GiveUp('Build broken in unexpected manner')
                if exc_str:
                    raise GiveUp('Expected GiveUp with %r'%exc_str)
                print 'OK'
            else:
                if exc_str:
                    if exc_str not in text:
                        raise GiveUp('Got unexpected failure\n'
                                     'Expected %r'%exc_str)
                else:
                    raise GiveUp('Got unexpected failure')
                print 'Which is what we wanted, so OK'

    with TransientDirectory(root_dir, keep_on_error=True, keep_anyway=keep) as root_d:
        banner('CONSTRUCT BUILD DESCRIPTION')
        muddle(['bootstrap', 'git+file:///something', 'DECIDE'])
        # A simple string
        test_aptget('"fromble-v1"')
        # A string in an array, as we always supported
        test_aptget('["fromble-v1"]')
        # or even two such
        test_aptget('["fromble-v1", "fromble-v2"]')
        # A single choice
        test_aptget('Choice("fromble-v1")')
        test_aptget('Choice([("ubuntu 12.10", "choice1"), ("ubuntu 12.9", "choice3"), "choice2"])')
        test_aptget('Choice([("ubuntu 12.10", "choice1"), ("ubuntu 12.9", "choice3"), None])')
        # Choices in an array
        test_aptget('[Choice("fromble-v1")]')
        test_aptget('['
                    'Choice("fromble-v1"),'
                    'Choice([("ubuntu 12.10", "choice1"), ("ubuntu 12.9", "choice3"), "choice2"]),'
                    ']')
        # Strings and choices
        test_aptget('["fromble-v1", Choice("fromble-v1")]')
        test_aptget('["fromble1", Choice([("ubuntu 12.10", "choice1"), ("ubuntu 12.9", "choice3"), "choice2"])]')
        # Broken choices
        test_aptget('Choice([("ubuntu 12.10", "choice1"), "choice2", ("ubuntu 12.9", "choice3")])',
                    'Only the last item in a choice sequence may be a string')
        test_aptget('["fromble1", Choice([("ubuntu 12.10", "choice1"), "choice2", ("ubuntu 12.9", "choice3")])]',
                    'Only the last item in a choice sequence may be a string')
        # The example from the aptget.simple docstring
        test_aptget("""[
               "gcc-multilib",
               "g++-multilib",
               "lib32ncurses5-dev",
               "lib32z1-dev",
               "bison",
               "flex",
               "gperf",
               "libx11-dev",
               # On Ubuntu 11 or 12, choose icedtea-7, otherwise icedtea-6
               Choice([ ("ubuntu 1[12].*", "icedtea-7-jre"),
                        ("ubuntu *", "icedtea-6-jre") ]),
               # On Ubuntu 10 or later, use libgtiff5
               # On Ubuntu 3 through 9, use libgtiff4
               # Otherwise, just don't try to use libgtiff (and note we didn't
               # remember to think about a prospective Ubuntu 20...)
               Choice([ ("ubuntu 1?.*", "libgtiff5"),
                        ("ubuntu 12.[3456789]", "libgtiff4"),
                        None ])
               ], os_version='ubuntu 12.10'""")
        # What redhat?
        test_aptget("""[
               "gcc-multilib",
               # On Ubuntu 11 or 12, choose icedtea-7, otherwise icedtea-6
               Choice([ ("ubuntu 1[12].*", "icedtea-7-jre"),
                        ("ubuntu *", "icedtea-6-jre") ]),
               ], os_version='redhat 7.0'""",
               "and OS 'redhat 7.0', cannot find a match")

    return True
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 NewCountedDirectory('build.original') as d1:
            banner('CHECK REPOSITORIES OUT INTO FIRST BUILD')
            checkout_build_descriptions(root_dir, d1)
            muddle(['checkout', '_all'])
            orig_dir = d1.where


        banner('TEST A SIMPLE CHANGE')
        # With an insignificant change, this should work identically by
        # both mechanisms

        with NewCountedDirectory('build.simple.noreload.pull') as d2:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_build_descriptions(root_dir, d2)
            muddle(['checkout', '_all'])
            pass1_noreload_dir = d2.where

        with NewCountedDirectory('build.simple.default.pull') as d3:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_build_descriptions(root_dir, d3)
            muddle(['checkout', '_all'])
            pass1_default_dir = d3.where

        with Directory(orig_dir) as d:
            banner('AMEND SUB1 BUILD DESCRIPTION AND PUSH', 2)
            amend_sub1_build_desc_and_push(root_dir, d)

        with Directory(pass1_noreload_dir) as d:
            banner('PULL IN THE ORIGINAL MANNER', 2)
            muddle(['pull', '-noreload', '_all'])
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'),
                              [
                              'checkout:(sub1)builds/checked_out\n',
                              ])

        with Directory(pass1_default_dir) as d:
            banner('PULL WITH BUILD DESCRIPTIONS PULLED FIRST', 2)
            muddle(['pull', '_all'])
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'),
                              [
                              'checkout:(sub1)builds/checked_out\n',
                              ])


        banner('TEST A MORE COMPLICATED CHANGE')
        # Since we're changing the layout of the build, this should
        # work substantially differently by the two mechanisms

        with NewCountedDirectory('build.swap.noreload.pull') as d2:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_build_descriptions(root_dir, d2)
            muddle(['checkout', '_all'])
            pass2_noreload_dir = d2.where

        with NewCountedDirectory('build.swap.default.pull') as d3:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_build_descriptions(root_dir, d3)
            muddle(['checkout', '_all'])
            pass2_default_dir = d3.where

        with Directory(orig_dir) as d:
            banner('SWAP SUBDOMAIN BUILD DESCRIPTIONS AND PUSH', 2)
            swap_subdomains_and_push(root_dir, d)

        with Directory(pass2_noreload_dir) as d:
            banner('PULL IN THE ORIGINAL MANNER', 2)
            banner('PULL THE FIRST', 3)
            muddle(['pull', '-noreload', '_all'])
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'),
                              [
                              'checkout:(sub1)builds/checked_out\n',
                              'checkout:(sub2)builds/checked_out\n',
                              ])
            banner('PULL THE SECOND', 3)
            # Our *second* pull should bring us to the same place as the
            # single pull with the "slow" mechanism would achieve.
            #
            # Note that it shouldn't matter where in the build tree we
            # do this command from...
            with Directory('src'):
                with Directory('builds'):
                    muddle(['pull', '-noreload', '_all'])
            # We should have files following the amended build description
            check_amended_build_descs(d)
            # But we have not deleted the files from the original description
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'),
                              [
                              'checkout:(sub1(sub4))co0/checked_out\n',
                              'checkout:(sub1(sub5))co0/checked_out\n',
                              'checkout:(sub2(sub3))co0/checked_out\n',
                              ])

        with Directory(pass2_default_dir) as d:
            banner('PULL WITH BUILD DESCRIPTIONS PULLED FIRST', 2)
            # Note that it shouldn't matter where in the build tree we
            # do this command from...
            with Directory('src'):
                with Directory('builds'):
                    muddle(['pull', '_all'])
            # We should have files following the amended build description
            check_amended_build_descs(d)
            # But we have not deleted the files from the original description
            check_original_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'),
                              [
                              'checkout:(sub1)builds/checked_out\n',
                              'checkout:(sub1(sub4))builds/checked_out\n',
                              'checkout:(sub1(sub4))co0/checked_out\n',
                              'checkout:(sub1(sub5))builds/checked_out\n',
                              'checkout:(sub1(sub5))co0/checked_out\n',
                              'checkout:(sub2)builds/checked_out\n',
                              'checkout:(sub2(sub3))builds/checked_out\n',
                              'checkout:(sub2(sub3))co0/checked_out\n',
                              ])


        banner('TEST NOT CHANGING THE BUILD DESCRIPTIONS')
        # This should work identically by both mechanisms

        with NewCountedDirectory('build.nodesc.noreload.pull') as d2:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_amended_build_descriptions(root_dir, d2)
            muddle(['checkout', '_all'])
            pass3_noreload_dir = d2.where

        with NewCountedDirectory('build.nodesc.default.pull') as d3:
            banner('CHECK REPOSITORIES OUT', 2)
            checkout_amended_build_descriptions(root_dir, d3)
            muddle(['checkout', '_all'])
            pass3_default_dir = d3.where

        with Directory(orig_dir) as d:
            banner('CHANGE SOMETHING NOT A BUILD DESCRIPTION AND PUSH', 2)
            change_something_else_and_push(root_dir, d)

        with Directory(pass3_noreload_dir) as d:
            banner('PULL IN THE ORIGINAL MANNER', 2)
            muddle(['pull', '-noreload', '_all'])
            check_amended_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'),
                              [
                              'checkout:(sub1)co0/checked_out\n',
                              ])

        with Directory(pass3_default_dir) as d:
            banner('PULL WITH BUILD DESCRIPTIONS PULLED FIRST', 2)
            muddle(['pull', '_all'])
            check_amended_build_descs(d)
            check_file_v_text(d.join('.muddle', '_just_pulled'),
                              [
                              'checkout:(sub1)co0/checked_out\n',
                              ])
示例#34
0
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))

    print 'Testing utils.decide'

    suite = unittest.TestLoader().loadTestsFromTestCase(TestChoice)
    results = unittest.TextTestRunner().run(suite)

    if not results.wasSuccessful():
        return False

    # 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'))

    def test_aptget(choice, exc_str=None):
        with Directory(os.path.join('src', 'builds')) as srcdir:
            if os.path.exists('01.py'):
                os.remove('01.py')
            if os.path.exists('01.pyc'):
                os.remove('01.pyc')
            touch('01.py', BUILD_DESC % choice)
            rc, text = captured_muddle2(['query', 'checkouts'])
            print text.strip()
            if rc == 0:
                if text.strip() != 'builds':
                    raise GiveUp('Build broken in unexpected manner')
                if exc_str:
                    raise GiveUp('Expected GiveUp with %r' % exc_str)
                print 'OK'
            else:
                if exc_str:
                    if exc_str not in text:
                        raise GiveUp('Got unexpected failure\n'
                                     'Expected %r' % exc_str)
                else:
                    raise GiveUp('Got unexpected failure')
                print 'Which is what we wanted, so OK'

    with TransientDirectory(root_dir, keep_on_error=True,
                            keep_anyway=keep) as root_d:
        banner('CONSTRUCT BUILD DESCRIPTION')
        muddle(['bootstrap', 'git+file:///something', 'DECIDE'])
        # A simple string
        test_aptget('"fromble-v1"')
        # A string in an array, as we always supported
        test_aptget('["fromble-v1"]')
        # or even two such
        test_aptget('["fromble-v1", "fromble-v2"]')
        # A single choice
        test_aptget('Choice("fromble-v1")')
        test_aptget(
            'Choice([("ubuntu 12.10", "choice1"), ("ubuntu 12.9", "choice3"), "choice2"])'
        )
        test_aptget(
            'Choice([("ubuntu 12.10", "choice1"), ("ubuntu 12.9", "choice3"), None])'
        )
        # Choices in an array
        test_aptget('[Choice("fromble-v1")]')
        test_aptget(
            '['
            'Choice("fromble-v1"),'
            'Choice([("ubuntu 12.10", "choice1"), ("ubuntu 12.9", "choice3"), "choice2"]),'
            ']')
        # Strings and choices
        test_aptget('["fromble-v1", Choice("fromble-v1")]')
        test_aptget(
            '["fromble1", Choice([("ubuntu 12.10", "choice1"), ("ubuntu 12.9", "choice3"), "choice2"])]'
        )
        # Broken choices
        test_aptget(
            'Choice([("ubuntu 12.10", "choice1"), "choice2", ("ubuntu 12.9", "choice3")])',
            'Only the last item in a choice sequence may be a string')
        test_aptget(
            '["fromble1", Choice([("ubuntu 12.10", "choice1"), "choice2", ("ubuntu 12.9", "choice3")])]',
            'Only the last item in a choice sequence may be a string')
        # The example from the aptget.simple docstring
        test_aptget("""[
               "gcc-multilib",
               "g++-multilib",
               "lib32ncurses5-dev",
               "lib32z1-dev",
               "bison",
               "flex",
               "gperf",
               "libx11-dev",
               # On Ubuntu 11 or 12, choose icedtea-7, otherwise icedtea-6
               Choice([ ("ubuntu 1[12].*", "icedtea-7-jre"),
                        ("ubuntu *", "icedtea-6-jre") ]),
               # On Ubuntu 10 or later, use libgtiff5
               # On Ubuntu 3 through 9, use libgtiff4
               # Otherwise, just don't try to use libgtiff (and note we didn't
               # remember to think about a prospective Ubuntu 20...)
               Choice([ ("ubuntu 1?.*", "libgtiff5"),
                        ("ubuntu 12.[3456789]", "libgtiff4"),
                        None ])
               ], os_version='ubuntu 12.10'""")
        # What redhat?
        test_aptget(
            """[
               "gcc-multilib",
               # On Ubuntu 11 or 12, choose icedtea-7, otherwise icedtea-6
               Choice([ ("ubuntu 1[12].*", "icedtea-7-jre"),
                        ("ubuntu *", "icedtea-6-jre") ]),
               ], os_version='redhat 7.0'""",
            "and OS 'redhat 7.0', cannot find a match")

    return True
示例#35
0
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',
                                         ])
示例#36
0
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',
                ])
示例#37
0
def test_bzr_muddle_patch():
    """Test the workings of the muddle_patch program against bzr

    Relies upon test_bzr_checkout_build() having been called.
    """
    root_dir = normalise_dir(os.getcwd())

    banner('Making changes in build1')
    with Directory('test_build1'):
        with Directory('src/checkout1'):
            touch('empty.c')  # empty
            touch('program1.c', '// This is very dull C file 1\n')
            touch('program2.c', '// This is very dull C file 2\n')
            touch('Makefile.muddle',
                  '# This is our makefile reduced to a single line\n')
            bzr('add empty.c program1.c program2.c')
            bzr('commit -m "Add program1|2.c, empty.c, shrink our Makefile"')
            bzr('push')
            bzr('rm program2.c')
            touch('Makefile.muddle',
                  '# This is our makefile\n# Now with two lines\n')
            bzr('commit -m "Delete program2.c, change our Makefile"')
            bzr('push')

        with Directory('src/twolevel/checkout2'):
            touch('program.c', '// This is very dull C file\n')
            bzr('add program.c')
            bzr('commit -m "Add program.c"')
            bzr('push')

        with Directory('src/multilevel/inner/checkout3'):
            touch('program.c', '// This is very dull C file\n')
            bzr('add program.c')
            bzr('commit -m "Add program.c"')
            bzr('push')

    banner('TEMPORARY: MAKE VERSION STAMP FOR BUILD 1')
    with Directory('test_build1'):
        muddle(['stamp', 'version'])

    banner(
        'Generating patches between build1 (altered, near) and build3 (unaltered, far)'
    )
    # test_build2 doesn't have a stamp file...
    with Directory('test_build1'):
        shell('%s write - ../test_build3/versions/checkout_test.stamp'
              ' ../patch_dir' % MUDDLE_PATCH_COMMAND)

    shell('ls patch_dir')

    banner('Applying patches to build3')
    with Directory('test_build3'):
        shell('%s read ../patch_dir' % MUDDLE_PATCH_COMMAND)

    with Directory('test_build3/src/checkout1'):
        banner('Checking we have the expected files present...')
        check_specific_files_in_this_dir(
            ['Makefile.muddle', 'program1.c', '.bzr'])
        # We'd *like* empty.c to be there as well, but at the moment
        # it won't be...

        banner('Committing the changes in checkout1')
        bzr('add')
        bzr('commit -m "Changes from muddle_patch"')

    with Directory('test_build3/src/twolevel/checkout2'):
        check_specific_files_in_this_dir(
            ['Makefile.muddle', 'program.c', '.bzr'])
        banner('Committing the changes in checkout2')
        bzr('add')
        bzr('commit -m "Changes from muddle_patch"')

    with Directory('test_build3/src/multilevel/inner/checkout3'):
        check_specific_files_in_this_dir(
            ['Makefile.muddle', 'program.c', '.bzr'])
        banner('Committing the changes in checkout3')
        bzr('add')
        bzr('commit -m "Changes from muddle_patch"')
示例#38
0
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:

        banner('MAKE REPOSITORIES')
        make_repos(root_dir)

        with NewCountedDirectory('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'])

            with Directory(g_UPSTREAMS['repo1.1']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master'])
            with Directory(g_UPSTREAMS['repo1.2']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master'])
            with Directory(g_UPSTREAMS['repo1.3']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master'])

            banner('CHECK USING UPSTREAMS')
            test_using_upstreams(root_dir)

            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>",
                         "co_repo1 master <none> <not following>",
                         "(subdomain1)builds master <none> <not following>",
                         "(subdomain1)co_repo1 master <none> <not following>",
                         "(subdomain2)builds master <none> <not following>",
                         "(subdomain2)co_repo1.1 master <none> <not following>"],
                        fold_whitespace=True)

            # What happens if we try to "follow" a subdomain?
            with Directory('domains'):
                with Directory('subdomain1'):
                    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')

            # It shouldn't make a difference - only the top-level build
            # description gets followed
            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>",
                         "co_repo1 master <none> <not following>",
                         "(subdomain1)builds master <none> <not following>",
                         "(subdomain1)co_repo1 master <none> <not following>",
                         "(subdomain2)builds master <none> <not following>",
                         "(subdomain2)co_repo1.1 master <none> <not following>"],
                        fold_whitespace=True)

            # Even if we branch that build description...
            with Directory('domains'):
                with Directory('subdomain1'):
                    with Directory('src'):
                        with Directory('builds'):
                            git('branch Fred')

            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>",
                         "co_repo1 master <none> <not following>",
                         "(subdomain1)builds master <none> <not following>",
                         "(subdomain1)co_repo1 master <none> <not following>",
                         "(subdomain2)builds master <none> <not following>",
                         "(subdomain2)co_repo1.1 master <none> <not following>"],
                        fold_whitespace=True)

            banner('BRANCH TREE')
            muddle(['branch-tree', 'v1-maintenance'])
            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')

            text = captured_muddle(['query', 'checkout-branches'])
            lines = text.splitlines()
            lines = lines[3:]       # ignore the header lines
            check_text_lines_v_lines(lines,
                        ["builds v1-maintenance <none> <it's own>",
                         "co_repo1 v1-maintenance <none> v1-maintenance",
                         "(subdomain1)builds v1-maintenance <none> v1-maintenance",
                         "(subdomain1)co_repo1 v1-maintenance <none> v1-maintenance",
                         "(subdomain2)builds v1-maintenance <none> v1-maintenance",
                         "(subdomain2)co_repo1.1 v1-maintenance <none> v1-maintenance"],
                        fold_whitespace=True)

            muddle(['runin', '_all_checkouts', 'git commit -a -m "Create maintenance branch"'])
            muddle(['push', '_all'])

        # The push causes "(subdomain2)co_repo1.1" to push to our "repo1.1",
        # which it is using as its "local" repository, so we see our branch
        # already there
        with Directory(g_UPSTREAMS['repo1.1']):
            text = get_stdout('git branch -a')
            check_text_v_lines(text, ['* master',
                                      '  v1-maintenance'])
        with Directory(g_UPSTREAMS['repo1.2']):
            text = get_stdout('git branch -a')
            check_text_v_lines(text, ['* master'])
        with Directory(g_UPSTREAMS['repo1.3']):
            text = get_stdout('git branch -a')
            check_text_v_lines(text, ['* master'])

        with NewCountedDirectory('rebuild') as d:
            banner('CHECK REPOSITORIES OUT BRANCHED')
            muddle(['init', '-branch', 'v1-maintenance',
                    'git+file://{repo}/main'.format(repo=root.join('repo')),
                    'builds/01.py'])

            # The subdomain build descriptions should be following the
            # top level build description
            text = captured_muddle(['query', 'checkout-branches'])
            lines = text.splitlines()
            lines = lines[3:]       # ignore the header lines
            check_text_lines_v_lines(lines,
                        ["builds v1-maintenance v1-maintenance <it's own>",
                         "co_repo1 <can't tell> <none> v1-maintenance",
                         "(subdomain1)builds v1-maintenance <none> v1-maintenance",
                         "(subdomain1)co_repo1 <can't tell> <none> v1-maintenance",
                         "(subdomain2)builds v1-maintenance <none> v1-maintenance",
                         "(subdomain2)co_repo1.1 <can't tell> <none> v1-maintenance"],
                        fold_whitespace=True)

            muddle(['checkout', '_all'])
            text = captured_muddle(['query', 'checkout-branches'])
            lines = text.splitlines()
            lines = lines[3:]       # ignore the header lines
            check_text_lines_v_lines(lines,
                        ["builds v1-maintenance v1-maintenance <it's own>",
                         "co_repo1 v1-maintenance <none> v1-maintenance",
                         "(subdomain1)builds v1-maintenance <none> v1-maintenance",
                         "(subdomain1)co_repo1 v1-maintenance <none> v1-maintenance",
                         "(subdomain2)builds v1-maintenance <none> v1-maintenance",
                         "(subdomain2)co_repo1.1 v1-maintenance <none> v1-maintenance"],
                        fold_whitespace=True)

            # What happens if we push upstream?
            muddle(['push-upstream', 'co_repo1', '-u', 'rhubarb', 'platypus'])
            # That should succeed, as we're allowed to push to both of those
            # And now we should see our branch on repo1.3 as well
            with Directory(g_UPSTREAMS['repo1.1']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master',
                                          '  v1-maintenance'])
            with Directory(g_UPSTREAMS['repo1.2']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master'])
            with Directory(g_UPSTREAMS['repo1.3']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master',
                                          '  v1-maintenance'])

            # If we try to pull upstream from wombat, we should fail
            # as it does not have our branch
            retcode, text = captured_muddle2(['pull-upstream', 'co_repo1', '-u', 'wombat'])
            if not retcode:
                raise GiveUp("Expected error trying to pull from wombat, but"
                             " got %d:\n%s"%(retcode, text))
            if "fatal: remotes/wombat/v1-maintenance - not something we can merge" not in text:
                raise GiveUp("Expected error 'fatal: remotes/wombat/v1-maintenance"
                             " - not something we can merge' trying to pull from"
                             " wombat, but got:\n%s"%text)
示例#39
0
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)
示例#40
0
def test_git_muddle_patch():
    """Test the workings of the muddle_patch program against git

    Relies upon test_git_checkout_build() having been called.
    """
    root_dir = normalise_dir(os.getcwd())

    banner('Making changes in build1')
    with Directory('test_build1'):
        with Directory('src/checkout1'):
            touch('empty.c')      # empty
            touch('program1.c','// This is very dull C file 1\n')
            touch('program2.c','// This is very dull C file 2\n')
            touch('Makefile.muddle',
                  '# This is our makefile reduced to a single line\n')
            git('add empty.c program1.c program2.c Makefile.muddle')
            git('commit -m "Add program1|2.c, empty.c, shrink our Makefile"')
            muddle(['push'])  # muddle remembers the repository for us
            git('rm program2.c')
            touch('Makefile.muddle',
                  '# This is our makefile\n# Now with two lines\n')
            git('add Makefile.muddle')
            git('commit -m "Delete program2.c, change our Makefile"')
            muddle(['push'])  # muddle remembers the repository for us

        with Directory('src/twolevel/checkout2'):
            touch('program.c','// This is very dull C file\n')
            git('add program.c')
            git('commit -m "Add program.c"')
            muddle(['push'])  # muddle remembers the repository for us

        with Directory('src/multilevel/inner/checkout3'):
            touch('program.c','// This is very dull C file\n')
            git('add program.c')
            git('commit -m "Add program.c"')
            muddle(['push'])  # muddle remembers the repository for us

    banner('Generating patches between build1 (altered, near) and build3 (unaltered, far)')
    # test_build2 doesn't have a stamp file...
    with Directory('test_build1'):
        shell('%s write - ../test_build3/versions/checkout_test.stamp'
              ' ../patch_dir'%MUDDLE_PATCH_COMMAND)

    shell('ls patch_dir')

    banner('Applying patches to build3')
    with Directory('test_build3'):
        shell('%s read ../patch_dir'%MUDDLE_PATCH_COMMAND)

    with Directory('test_build1/src/checkout1'):
        git('rev-parse HEAD')
        git('rev-parse master')

    with Directory('test_build3/src/checkout1'):
        git('rev-parse HEAD')
        git('rev-parse master')
        banner('"git am" leaves our HEAD detached, so we should then do something like:')
        git('branch post-am-branch')    # to stop our HEAD being detached
        git('checkout master')          # assuming we were on master, of course
        git('merge post-am-branch')     # and we should now be where we want...
        git('rev-parse HEAD')
        git('rev-parse master')

    with Directory('test_build3/src/checkout1'):
        check_specific_files_in_this_dir(['Makefile.muddle', 'empty.c',
                                          'program1.c', '.git'])

    with Directory('test_build3/src/twolevel/checkout2'):
        check_specific_files_in_this_dir(['Makefile.muddle',
                                          'program.c', '.git'])

    with Directory('test_build3/src/multilevel/inner/checkout3'):
        check_specific_files_in_this_dir(['Makefile.muddle',
                                          'program.c', '.git'])
示例#41
0
def test_bzr_muddle_patch():
    """Test the workings of the muddle_patch program against bzr

    Relies upon test_bzr_checkout_build() having been called.
    """
    root_dir = normalise_dir(os.getcwd())

    banner('Making changes in build1')
    with Directory('test_build1'):
        with Directory('src/checkout1'):
            touch('empty.c')      # empty
            touch('program1.c','// This is very dull C file 1\n')
            touch('program2.c','// This is very dull C file 2\n')
            touch('Makefile.muddle',
                  '# This is our makefile reduced to a single line\n')
            bzr('add empty.c program1.c program2.c')
            bzr('commit -m "Add program1|2.c, empty.c, shrink our Makefile"')
            bzr('push')
            bzr('rm program2.c')
            touch('Makefile.muddle',
                  '# This is our makefile\n# Now with two lines\n')
            bzr('commit -m "Delete program2.c, change our Makefile"')
            bzr('push')

        with Directory('src/twolevel/checkout2'):
            touch('program.c','// This is very dull C file\n')
            bzr('add program.c')
            bzr('commit -m "Add program.c"')
            bzr('push')

        with Directory('src/multilevel/inner/checkout3'):
            touch('program.c','// This is very dull C file\n')
            bzr('add program.c')
            bzr('commit -m "Add program.c"')
            bzr('push')

    banner('TEMPORARY: MAKE VERSION STAMP FOR BUILD 1')
    with Directory('test_build1'):
        muddle(['stamp', 'version'])

    banner('Generating patches between build1 (altered, near) and build3 (unaltered, far)')
    # test_build2 doesn't have a stamp file...
    with Directory('test_build1'):
        shell('%s write - ../test_build3/versions/checkout_test.stamp'
              ' ../patch_dir'%MUDDLE_PATCH_COMMAND)

    shell('ls patch_dir')

    banner('Applying patches to build3')
    with Directory('test_build3'):
        shell('%s read ../patch_dir'%MUDDLE_PATCH_COMMAND)

    with Directory('test_build3/src/checkout1'):
        banner('Checking we have the expected files present...')
        check_specific_files_in_this_dir(['Makefile.muddle', 'program1.c', '.bzr'])
        # We'd *like* empty.c to be there as well, but at the moment
        # it won't be...

        banner('Committing the changes in checkout1')
        bzr('add')
        bzr('commit -m "Changes from muddle_patch"')

    with Directory('test_build3/src/twolevel/checkout2'):
        check_specific_files_in_this_dir(['Makefile.muddle',
                                          'program.c', '.bzr'])
        banner('Committing the changes in checkout2')
        bzr('add')
        bzr('commit -m "Changes from muddle_patch"')

    with Directory('test_build3/src/multilevel/inner/checkout3'):
        check_specific_files_in_this_dir(['Makefile.muddle',
                                          'program.c', '.bzr'])
        banner('Committing the changes in checkout3')
        bzr('add')
        bzr('commit -m "Changes from muddle_patch"')
示例#42
0
try:
    import muddled.cmdline
    from muddled.utils import MuddleBug, GiveUp, ShellError, normalise_dir
except ImportError:
    # Hah - maybe we're being run throught the 'muddle' soft link
    # from the same directory that contains the muddled/ package,
    # with PYTHONPATH unset (this is different to PYTHONPATH set
    # to nothing - ho hum). So try:
    sys.path = [this_dir] + sys.path[1:]
    import muddled.cmdline
    from muddled.utils import MuddleBug, GiveUp, ShellError, normalise_dir

if __name__ == "__main__":
    try:
        muddle_binary = normalise_dir(__file__)
        muddled.cmdline.cmdline(sys.argv[1:], muddle_binary)
        sys.exit(0)
    except MuddleBug, e:
        # We assume this represents a bug in muddle itself, so give a full
        # traceback to help locate it.
        print
        print "%s"%e
        traceback.print_exc()
        sys.exit(e.retcode)
    except ShellError, e:
        # A ShellError is a subclass of GiveUp. If it reaches this level,
        # though, it indicates that some shell command (probably run with
        # utils.run0()) failed and was not caught elsewhere. This is normally
        # a problem in the muddle infrastructure, so we treat it as a
        # MuddleBug, with a full traceback
示例#43
0
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:

        banner('MAKE REPOSITORIES')
        make_repos(root_dir)

        with NewCountedDirectory('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'])

            with Directory(g_UPSTREAMS['repo1.1']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master'])
            with Directory(g_UPSTREAMS['repo1.2']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master'])
            with Directory(g_UPSTREAMS['repo1.3']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master'])

            banner('CHECK USING UPSTREAMS')
            test_using_upstreams(root_dir)

            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>",
                "co_repo1 master <none> <not following>",
                "(subdomain1)builds master <none> <not following>",
                "(subdomain1)co_repo1 master <none> <not following>",
                "(subdomain2)builds master <none> <not following>",
                "(subdomain2)co_repo1.1 master <none> <not following>"
            ],
                                     fold_whitespace=True)

            # What happens if we try to "follow" a subdomain?
            with Directory('domains'):
                with Directory('subdomain1'):
                    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')

            # It shouldn't make a difference - only the top-level build
            # description gets followed
            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>",
                "co_repo1 master <none> <not following>",
                "(subdomain1)builds master <none> <not following>",
                "(subdomain1)co_repo1 master <none> <not following>",
                "(subdomain2)builds master <none> <not following>",
                "(subdomain2)co_repo1.1 master <none> <not following>"
            ],
                                     fold_whitespace=True)

            # Even if we branch that build description...
            with Directory('domains'):
                with Directory('subdomain1'):
                    with Directory('src'):
                        with Directory('builds'):
                            git('branch Fred')

            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>",
                "co_repo1 master <none> <not following>",
                "(subdomain1)builds master <none> <not following>",
                "(subdomain1)co_repo1 master <none> <not following>",
                "(subdomain2)builds master <none> <not following>",
                "(subdomain2)co_repo1.1 master <none> <not following>"
            ],
                                     fold_whitespace=True)

            banner('BRANCH TREE')
            muddle(['branch-tree', 'v1-maintenance'])
            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')

            text = captured_muddle(['query', 'checkout-branches'])
            lines = text.splitlines()
            lines = lines[3:]  # ignore the header lines
            check_text_lines_v_lines(lines, [
                "builds v1-maintenance <none> <it's own>",
                "co_repo1 v1-maintenance <none> v1-maintenance",
                "(subdomain1)builds v1-maintenance <none> v1-maintenance",
                "(subdomain1)co_repo1 v1-maintenance <none> v1-maintenance",
                "(subdomain2)builds v1-maintenance <none> v1-maintenance",
                "(subdomain2)co_repo1.1 v1-maintenance <none> v1-maintenance"
            ],
                                     fold_whitespace=True)

            muddle([
                'runin', '_all_checkouts',
                'git commit -a -m "Create maintenance branch"'
            ])
            muddle(['push', '_all'])

        # The push causes "(subdomain2)co_repo1.1" to push to our "repo1.1",
        # which it is using as its "local" repository, so we see our branch
        # already there
        with Directory(g_UPSTREAMS['repo1.1']):
            text = get_stdout('git branch -a')
            check_text_v_lines(text, ['* master', '  v1-maintenance'])
        with Directory(g_UPSTREAMS['repo1.2']):
            text = get_stdout('git branch -a')
            check_text_v_lines(text, ['* master'])
        with Directory(g_UPSTREAMS['repo1.3']):
            text = get_stdout('git branch -a')
            check_text_v_lines(text, ['* master'])

        with NewCountedDirectory('rebuild') as d:
            banner('CHECK REPOSITORIES OUT BRANCHED')
            muddle([
                'init', '-branch', 'v1-maintenance',
                'git+file://{repo}/main'.format(repo=root.join('repo')),
                'builds/01.py'
            ])

            # The subdomain build descriptions should be following the
            # top level build description
            text = captured_muddle(['query', 'checkout-branches'])
            lines = text.splitlines()
            lines = lines[3:]  # ignore the header lines
            check_text_lines_v_lines(lines, [
                "builds v1-maintenance v1-maintenance <it's own>",
                "co_repo1 <can't tell> <none> v1-maintenance",
                "(subdomain1)builds v1-maintenance <none> v1-maintenance",
                "(subdomain1)co_repo1 <can't tell> <none> v1-maintenance",
                "(subdomain2)builds v1-maintenance <none> v1-maintenance",
                "(subdomain2)co_repo1.1 <can't tell> <none> v1-maintenance"
            ],
                                     fold_whitespace=True)

            muddle(['checkout', '_all'])
            text = captured_muddle(['query', 'checkout-branches'])
            lines = text.splitlines()
            lines = lines[3:]  # ignore the header lines
            check_text_lines_v_lines(lines, [
                "builds v1-maintenance v1-maintenance <it's own>",
                "co_repo1 v1-maintenance <none> v1-maintenance",
                "(subdomain1)builds v1-maintenance <none> v1-maintenance",
                "(subdomain1)co_repo1 v1-maintenance <none> v1-maintenance",
                "(subdomain2)builds v1-maintenance <none> v1-maintenance",
                "(subdomain2)co_repo1.1 v1-maintenance <none> v1-maintenance"
            ],
                                     fold_whitespace=True)

            # What happens if we push upstream?
            muddle(['push-upstream', 'co_repo1', '-u', 'rhubarb', 'platypus'])
            # That should succeed, as we're allowed to push to both of those
            # And now we should see our branch on repo1.3 as well
            with Directory(g_UPSTREAMS['repo1.1']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master', '  v1-maintenance'])
            with Directory(g_UPSTREAMS['repo1.2']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master'])
            with Directory(g_UPSTREAMS['repo1.3']):
                text = get_stdout('git branch -a')
                check_text_v_lines(text, ['* master', '  v1-maintenance'])

            # If we try to pull upstream from wombat, we should fail
            # as it does not have our branch
            retcode, text = captured_muddle2(
                ['pull-upstream', 'co_repo1', '-u', 'wombat'])
            if not retcode:
                raise GiveUp("Expected error trying to pull from wombat, but"
                             " got %d:\n%s" % (retcode, text))
            if "fatal: remotes/wombat/v1-maintenance - not something we can merge" not in text:
                raise GiveUp(
                    "Expected error 'fatal: remotes/wombat/v1-maintenance"
                    " - not something we can merge' trying to pull from"
                    " wombat, but got:\n%s" % text)
示例#44
0
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)
示例#45
0
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)
示例#46
0
def test_git_muddle_patch():
    """Test the workings of the muddle_patch program against git

    Relies upon test_git_checkout_build() having been called.
    """
    root_dir = normalise_dir(os.getcwd())

    banner('Making changes in build1')
    with Directory('test_build1'):
        with Directory('src/checkout1'):
            touch('empty.c')  # empty
            touch('program1.c', '// This is very dull C file 1\n')
            touch('program2.c', '// This is very dull C file 2\n')
            touch('Makefile.muddle',
                  '# This is our makefile reduced to a single line\n')
            git('add empty.c program1.c program2.c Makefile.muddle')
            git('commit -m "Add program1|2.c, empty.c, shrink our Makefile"')
            muddle(['push'])  # muddle remembers the repository for us
            git('rm program2.c')
            touch('Makefile.muddle',
                  '# This is our makefile\n# Now with two lines\n')
            git('add Makefile.muddle')
            git('commit -m "Delete program2.c, change our Makefile"')
            muddle(['push'])  # muddle remembers the repository for us

        with Directory('src/twolevel/checkout2'):
            touch('program.c', '// This is very dull C file\n')
            git('add program.c')
            git('commit -m "Add program.c"')
            muddle(['push'])  # muddle remembers the repository for us

        with Directory('src/multilevel/inner/checkout3'):
            touch('program.c', '// This is very dull C file\n')
            git('add program.c')
            git('commit -m "Add program.c"')
            muddle(['push'])  # muddle remembers the repository for us

    banner(
        'Generating patches between build1 (altered, near) and build3 (unaltered, far)'
    )
    # test_build2 doesn't have a stamp file...
    with Directory('test_build1'):
        shell('%s write - ../test_build3/versions/checkout_test.stamp'
              ' ../patch_dir' % MUDDLE_PATCH_COMMAND)

    shell('ls patch_dir')

    banner('Applying patches to build3')
    with Directory('test_build3'):
        shell('%s read ../patch_dir' % MUDDLE_PATCH_COMMAND)

    with Directory('test_build1/src/checkout1'):
        git('rev-parse HEAD')
        git('rev-parse master')

    with Directory('test_build3/src/checkout1'):
        git('rev-parse HEAD')
        git('rev-parse master')
        banner(
            '"git am" leaves our HEAD detached, so we should then do something like:'
        )
        git('branch post-am-branch')  # to stop our HEAD being detached
        git('checkout master')  # assuming we were on master, of course
        git('merge post-am-branch')  # and we should now be where we want...
        git('rev-parse HEAD')
        git('rev-parse master')

    with Directory('test_build3/src/checkout1'):
        check_specific_files_in_this_dir(
            ['Makefile.muddle', 'empty.c', 'program1.c', '.git'])

    with Directory('test_build3/src/twolevel/checkout2'):
        check_specific_files_in_this_dir(
            ['Makefile.muddle', 'program.c', '.git'])

    with Directory('test_build3/src/multilevel/inner/checkout3'):
        check_specific_files_in_this_dir(
            ['Makefile.muddle', 'program.c', '.git'])