Exemplo n.º 1
0
def setup_new_build(root_repo, name):
    with NewDirectory(name):
        banner('Bootstrapping checkout build')
        muddle(['bootstrap', 'git+%s' % root_repo, 'test_build'])
        cat('src/builds/01.py')

        banner('Setting up src/')
        with Directory('src'):
            with Directory('builds'):
                touch('01.py', CHECKOUT_BUILD_LEVELS)
                # Then remove the .pyc file, because Python probably won't realise
                # that this new 01.py is later than the previous version
                os.remove('01.pyc')
                git('add 01.py')
                git('commit -m "New build"')
                git('push %s/builds HEAD' % root_repo)

            with NewDirectory('checkout1'):
                touch('Makefile.muddle', MUDDLE_MAKEFILE)
                git('init')
                git('add Makefile.muddle')
                git('commit -m "Add muddle makefile"')
                # Assert that this checkout *has* been checked out
                # (this also does a "muddle reparent" for us, setting
                # up our remote origin for pushing)
                muddle(['import'])
                # And thus we can now ask muddle to push for us
                # (although a plain "git push" would also work)
                muddle(['push'])

            with NewDirectory('twolevel'):
                with NewDirectory('checkout2'):
                    touch('Makefile.muddle', MUDDLE_MAKEFILE)
                    git('init')
                    git('add Makefile.muddle')
                    git('commit -m "Add muddle makefile"')
                    muddle(['import'])
                    # As was said in 'checkout1', we can "git push" if
                    # we prefer, once we've done import - although we do
                    # need to be specific about *what* we're pushing, this
                    # first time round
                    git('push origin master')

            with NewDirectory('multilevel'):
                with NewDirectory('inner'):
                    with NewDirectory('checkout3'):
                        touch('Makefile.muddle', MUDDLE_MAKEFILE)
                        git('init')
                        git('add Makefile.muddle')
                        git('commit -m "Add muddle makefile"')
                        # Or we can do a more complicated sequence of things
                        # Just assert checkout via its tagged label
                        muddle(['assert', 'checkout:alice/checked_out'])
                        # then reparent by hand
                        muddle(['reparent'])
                        # and now we can git push
                        git('push origin master')
Exemplo n.º 2
0
def change_something_else_and_push(root_dir, d):
    repo = os.path.join(root_dir, 'repo')
    with Directory('domains'):
        with Directory('sub1'):
            with Directory('src'):
                with Directory('co0'):
                    append('sub1.c', '\n// A harmless change\n')
                    git('commit sub1.c -m "A harmless change"')
                    # We'd better be able to push with muddle!
                    muddle(['push'])
Exemplo n.º 3
0
def amend_sub1_build_desc_and_push(root_dir, d):
    repo = os.path.join(root_dir, 'repo')
    with Directory('domains'):
        with Directory('sub1'):
            with Directory('src'):
                with Directory('builds'):
                    append('01.py', '\n# A harmless change\n')
                    git('commit 01.py -m "A harmless change"')
                    # We'd better push with git, since we've hacked the build description
                    git('push origin HEAD')
Exemplo n.º 4
0
def test_stamp_is_current_working_set(first_stamp):
    """Check we are stamping the current working set
    """
    with NewCountedDirectory('build3') as d2:
        banner('TESTING STAMP CURRENT WORKING SET')
        muddle(['unstamp', first_stamp])
        # So, we've selected specific revisions for all of our checkouts
        # and thus they are all in "detached HEAD" state
        revisions = capture_revisions()

        # XXX To be considered XXX
        # Here, we are deliberately making a change that we do not push to the
        # remote repository. Thus our stamp file will contain a revision id
        # that no-one else can make sense of. This may be a Bad Thing.
        # Indeed, if we try to do this with a bzr repository, our own code
        # in 'muddle query checkout-id' would use 'bzr missing' and notice that
        # the revision was not present at the far end, and give up with a
        # complaint at that point.

        with Directory('src'):
            with Directory('first_co'):
                append('Makefile.muddle', '\n# A comment\n')
                git('commit Makefile.muddle -m "Add a comment"')

        # Don't forget that ".strip()" to remove the trailing newline!
        first_co_rev2 = captured_muddle(['query', 'checkout-id',
                                         'first_co']).strip()

        if first_co_rev2 == revisions['first_co']:
            raise GiveUp('The revision of first_co did not change')

        revisions['first_co'] = first_co_rev2

        muddle(['stamp', 'save', 'amended.stamp'])

        stamp = VersionStamp.from_file('amended.stamp')
        if len(stamp.checkouts) != len(revisions):
            raise GiveUp('Stamp file has %d checkouts, build tree %d' %
                         (len(stamp.checkouts), len(revisions)))

        for co in stamp.checkouts:
            if co.domain:
                dom_plus_name = '(%s)%s' % (co.domain, co.name)
            else:
                dom_plus_name = co.name
            repo = stamp.checkouts[co][
                -1]  # ah, named tuples would be good here
            #print dom_plus_name
            #print '  S:',repo.revision
            #print '  D:',revisions[dom_plus_name]
            if repo.revision != revisions[dom_plus_name]:
                raise GiveUp(
                    'Checkout %s is revision %s in stamp file,'
                    ' %s on disk' %
                    (dom_plus_name, repo.revision, revisions[dom_plus_name]))
Exemplo n.º 5
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'])
Exemplo n.º 6
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'])
Exemplo n.º 7
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',
        ])
Exemplo n.º 8
0
def make_old_build_tree():
    """Make a build tree that deploys a CPIO file, and use/test it
    """
    with NewDirectory('build.old') as d:
        muddle(['bootstrap', 'git+file:///nowhere', 'cpio-test-build'])

        with Directory('src'):
            with Directory('builds'):
                touch('01.py', DEPLOYMENT_BUILD_DESC)
                # Then remove the .pyc file, because Python probably won't realise
                # that this new 01.py is later than the previous version
                os.remove('01.pyc')

            with NewDirectory('first_co'):
                git('init')
                touch('Makefile.muddle',
                      MUDDLE_MAKEFILE1.format(progname='program1'))
                touch('program1.c', MAIN_C_SRC.format(progname='program1'))
                touch('instructions.xml', INSTRUCTIONS)
                git('add Makefile.muddle program1.c instructions.xml')
                git('commit -m "A commit"')
                muddle(['import'])

            with NewDirectory('second_co'):
                git('init')
                touch(
                    'Makefile.muddle',
                    MUDDLE_MAKEFILE2.format(progname1='program1',
                                            progname2='program2'))
                touch('program2.c', MAIN_C_SRC.format(progname='program2'))
                # A version of program1 that announces itself as program2
                touch('program1.c', MAIN_C_SRC.format(progname='program2'))
                git('add Makefile.muddle program2.c')
                git('commit -m "A commit"')
                muddle(['import'])

        muddle([])

        with Directory('deploy'):
            with Directory('everything'):
                check_cpio_archive('firmware.cpio')

                # Check we got the correct version of program1
                extract_file('firmware.cpio', '/bin/program1')
                text = get_stdout('bin/program1')
                if text != 'Program program2\n':
                    raise GiveUp(
                        'Expected the program1 from role2, but it output %s' %
                        text)
                print 'That looks like the correct program1'
Exemplo n.º 9
0
def show_version():
    """Show something akin to a version of this muddle.

    Simply run git to do it for us. Of course, this will fail if we don't
    have git...
    """
    this_dir = os.path.split(__file__)[0]
    muddle_dir = os.path.split(this_dir)[0]
    cmd_tag = ['git', 'describe', '--dirty=-modified', '--long', '--tags']
    cmd_all = ['git', 'describe', '--dirty=-modified', '--long', '--all']
    branch  = ['git', 'symbolic-ref', '-q', 'HEAD']
    version = "<unknown>"
    with Directory(muddle_dir, show_pushd=False):
        # First try looking for a version using tags, which should normally
        # work.
        version = our_cmd(cmd_tag, error_ok=True)
        # If that failed, try with --all
        if not version:
            version = our_cmd(cmd_tag, error_ok=False)

        # Are we on a branch?
        branch = our_cmd(branch)
        if branch:
            if branch.startswith('refs/heads/'):
                branch = branch[11:]
            if branch == 'master':
                branch = None

        if branch:
            print '%s on branch %s in %s'%(version, branch, muddle_dir)
        else:
            print '%s in %s'%(version, muddle_dir)
Exemplo n.º 10
0
    def checkout(self, repo, co_leaf, options, verbose=True):
        """
        Clone a given checkout.

        Will be called in the parent directory of the checkout.

        Expected to create a directory called <co_leaf> therein.
        """
        if repo.branch:
            args = ["-b", repo.branch]
        else:
            # Explicitly use master if no branch specified - don't default
            args = ["-b", "master"]

        if options.get('shallow_checkout'):
            args += ["--depth", "1"]

        utils.shell(["git", "clone"] + args +
                    [repo.url, str(co_leaf)],
                    show_command=verbose)

        if repo.revision:
            with Directory(co_leaf):
                # Are we already at the correct revision?
                actual_revision = self._git_rev_parse_HEAD()
                if actual_revision != expand_revision(repo.revision):
                    # XXX Arguably, should use '--quiet', to suppress the warning
                    # XXX that we are ending up in 'detached HEAD' state, since
                    # XXX that is rather what we asked for...
                    # XXX Or maybe we want to leave the message, as the warning
                    # XXX it is meant to be
                    utils.shell(["git", "checkout", repo.revision])
Exemplo n.º 11
0
    def get_current_branch(self,
                           builder,
                           co_label,
                           verbose=False,
                           show_pushd=False):
        """
        Return the name of the current branch.

        Will be called in the actual checkout's directory.

        Return the name of the current branch (e.g., "master" or "Fred"),
        or None if there is no current branch.

        If 'show_pushd' is false, then we won't report as we "pushd" into the
        checkout directory.

        Raises a GiveUp exception if the VCS does not support this operation,
        or if something goes wrong.
        """
        try:
            with Directory(builder.db.get_checkout_path(co_label),
                           show_pushd=show_pushd):
                return self.vcs.get_current_branch()
        except (GiveUp, Unsupported) as err:
            raise GiveUp(
                'Failure getting current branch for %s in %s:\n%s' %
                (co_label, builder.db.get_checkout_location(co_label), err))
Exemplo n.º 12
0
    def goto_revision(self,
                      builder,
                      co_label,
                      revision,
                      branch=None,
                      verbose=False,
                      show_pushd=False):
        """
        Go to the specified revision.

        If branch is given, this may alter the behaviour.

        Will be called in the actual checkout's directory.

        If 'show_pushd' is false, then we won't report as we "pushd" into the
        checkout directory.
        """
        repo = builder.db.get_checkout_repo(co_label)
        try:
            with Directory(builder.db.get_checkout_path(co_label),
                           show_pushd=show_pushd):
                return self.vcs.goto_revision(revision, branch, repo, verbose)
        except (GiveUp, Unsupported) as err:
            if branch:
                raise GiveUp(
                    'Failure changing to revision %s, branch %s, for %s in %s:\n%s'
                    % (revision, branch, co_label,
                       builder.db.get_checkout_location(co_label), err))
            else:
                raise GiveUp(
                    'Failure changing to revision %s for %s in %s:\n%s' %
                    (revision, co_label,
                     builder.db.get_checkout_location(co_label), err))
Exemplo n.º 13
0
    def branch_exists(self,
                      builder,
                      co_label,
                      branch,
                      verbose=False,
                      show_pushd=False):
        """
        Returns True if a branch of that name exists.

        This allowed to be conservative - e.g., in git the existence of a
        remote branch with the given name can be counted as True.

        Will be called in the actual checkout's directory.

        If 'show_pushd' is false, then we won't report as we "pushd" into the
        checkout directory.
        """
        try:
            with Directory(builder.db.get_checkout_path(co_label),
                           show_pushd=show_pushd):
                return self.vcs.branch_exists(branch)
        except (GiveUp, Unsupported) as err:
            raise GiveUp(
                'Failure checking existence of branch %s for %s in %s:\n%s' %
                (branch, co_label, builder.db.get_checkout_location(co_label),
                 err))
Exemplo n.º 14
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'])
Exemplo n.º 15
0
def setup_new_build(root_repo, name):
    with NewDirectory('test_build1'):
        banner('Bootstrapping checkout build')
        muddle(['bootstrap', 'bzr+%s' % root_repo, 'test_build'])
        cat('src/builds/01.py')

        banner('Setting up src/')
        with Directory('src'):
            with Directory('builds'):
                touch('01.py', CHECKOUT_BUILD_LEVELS)
                # Then remove the .pyc file, because Python probably won't realise
                # that this new 01.py is later than the previous version
                os.remove('01.pyc')
                bzr('add 01.py')
                bzr('commit -m "New build"')
                # The obvious thing to do is to push with muddle
                muddle(['push'])

            with NewDirectory('checkout1'):
                touch('Makefile.muddle', MUDDLE_MAKEFILE)
                bzr('init')
                bzr('add Makefile.muddle')
                bzr('commit -m "Add muddle makefile"')
                muddle(['import', 'checkout1'])
                # Or we can push by hand with bzr
                bzr('push %s/checkout1' % root_repo)

            with NewDirectory('twolevel'):
                with NewDirectory('checkout2'):
                    touch('Makefile.muddle', MUDDLE_MAKEFILE)
                    bzr('init')
                    bzr('add Makefile.muddle')
                    bzr('commit -m "Add muddle makefile"')
                    muddle(['import', 'checkout2'])
                    muddle(['push'])

            with NewDirectory('multilevel'):
                with NewDirectory('inner'):
                    with NewDirectory('checkout3'):
                        touch('Makefile.muddle', MUDDLE_MAKEFILE)
                        bzr('init')
                        bzr('add Makefile.muddle')
                        bzr('commit -m "Add muddle makefile"')
                        # If we push directly with BZR
                        bzr('push %s/multilevel/inner/checkout3' % root_repo)
                        muddle(['import', 'alice'])
Exemplo n.º 16
0
def test_stamping_branches(repo):
    """Test we cope with branches.
    """

    banner('TESTING STAMPING BRANCHES')
    with NewCountedDirectory('build6') as d:
        muddle([
            'init', 'git+file://{repo}/main'.format(repo=repo), 'builds/01.py'
        ])
        muddle(['checkout', '_all'])

        with Directory('src'):
            with Directory('first_co'):
                git('checkout -b branch1')
                muddle(['push'])

        muddle(['stamp', 'save', '01.stamp'])

    with NewCountedDirectory('build7'):
        muddle(['unstamp', d.join('01.stamp')])

        # We should have got the branch for first_co, even though it's not
        # the branch in the build description
        # Check we're working with the expected branches
        text = captured_muddle(['query', 'checkout-branches'])
        lines = text.splitlines()
        lines = lines[3:]  # ignore the header lines
        check_text_lines_v_lines(lines, [
            "builds master <none> <not following>",
            "first_co branch1 <none> <not following>",
            "main_co master <none> <not following>",
            "second_co <not supported> ... ...",
            "(subdomain1)builds master <none> <not following>",
            "(subdomain1)first_co master <none> <not following>",
            "(subdomain1)main_co master <none> <not following>",
            "(subdomain1)second_co master <none> <not following>",
            "(subdomain1(subdomain3))builds master <none> <not following>",
            "(subdomain1(subdomain3))first_co master <none> <not following>",
            "(subdomain1(subdomain3))main_co master <none> <not following>",
            "(subdomain1(subdomain3))second_co master <none> <not following>",
            "(subdomain2)builds master <none> <not following>",
            "(subdomain2)first_co master <none> <not following>",
            "(subdomain2)main_co master <none> <not following>",
            "(subdomain2)second_co master <none> <not following>"
        ],
                                 fold_whitespace=True)
Exemplo n.º 17
0
    def checkout(self, builder, co_label, verbose=True):
        """
        Check this checkout out of version control.

        The actual operation we perform is commonly called "clone" in actual
        version control systems. We retain the name "checkout" because it
        instantiates a muddle checkout.
        """
        # We want to be in the checkout's parent directory
        parent_dir, co_leaf = os.path.split(
            builder.db.get_checkout_path(co_label))

        repo = builder.db.get_checkout_repo(co_label)
        if not repo.pull:
            raise GiveUp('Failure checking out %s in %s:\n'
                         '  %s does not allow "pull"' %
                         (co_label, parent_dir, repo))

        # Be careful - if the parent is 'src/', then it may well exist by now
        if not os.path.exists(parent_dir):
            os.makedirs(parent_dir)

        specific_branch = self.branch_to_follow(builder, co_label)
        if specific_branch:
            # The build description told us to follow it, onto this branch
            # - so let's remember it on the Repository
            repo = repo.copy_with_changed_branch(specific_branch)

        options = builder.db.get_checkout_vcs_options(co_label)
        try:
            # A complete hack - checkout is kinda meaningless for weld, but
            # we do want to make sure that the git repo is set up and correct.
            if repo.vcs == "weld":
                with Directory(builder.db.root_path):
                    self.vcs.ensure_version(builder, repo, co_leaf, options,
                                            verbose)
            else:
                with Directory(parent_dir):
                    self.vcs.checkout(repo, co_leaf, options, verbose)
        except MuddleBug as err:
            raise MuddleBug('Error checking out %s in %s:\n%s' %
                            (co_label, parent_dir, err))
        except GiveUp as err:
            raise GiveUp('Failure checking out %s in %s:\n%s' %
                         (co_label, parent_dir, err))
Exemplo n.º 18
0
    def check_dot_muddle(is_subdomain):
        with Directory('.muddle') as m:
            check_files([
                m.join('Description'),
                m.join('RootRepository'),
                m.join('VersionsRepository')
            ])

            if is_subdomain:
                check_files([m.join('am_subdomain')])

            with Directory(m.join('tags', 'checkout')) as c:
                check_files([
                    c.join('builds', 'checked_out'),
                    c.join('first_co', 'checked_out'),
                    c.join('main_co', 'checked_out'),
                    c.join('second_co', 'checked_out')
                ])
Exemplo n.º 19
0
def test_unstamp_update_2(repo, first_stamp):
    """Test the "unstamp -update" operation a bit more
    """
    banner('TESTING UNSTAMP -UPDATE -- TEST 2')
    with NewCountedDirectory('build5') as d:
        muddle([
            'init', 'git+file://{repo}/main'.format(repo=repo), 'builds/01.py'
        ])
        muddle(['checkout', '_all'])
        old_revisions = capture_revisions()

        # Make some amdendments and check them in
        with Directory('src'):
            with Directory('first_co'):
                append('Makefile.muddle', '\n# A comment\n')
                git('commit Makefile.muddle -m "Add a comment"')
                muddle(['push'])
            with Directory('second_co'):
                append('Makefile.muddle', '\n# A comment\n')
                bzr('commit Makefile.muddle -m "Add a comment"')
                muddle(['push'])

        with Directory('domains'):
            with Directory('subdomain1'):
                with Directory('src'):
                    with Directory('builds'):
                        append('01.py', '\n# A comment\n')
                        git('commit 01.py -m "Add a comment"')
                        muddle(['push'])

        new_revisions = capture_revisions()

        # Keep this state for later on
        muddle(['stamp', 'save', 'new_state.stamp'])

        # Revert to the original
        muddle(['unstamp', '-update', first_stamp])
        current_revisions = capture_revisions()
        if revisions_differ(current_revisions, old_revisions):
            raise GiveUp('Update back to original failed')

        # And back (forwards) again
        muddle(['unstamp', '-update', 'new_state.stamp'])
        current_revisions = capture_revisions()
        if revisions_differ(current_revisions, new_revisions):
            raise GiveUp('Update forward again failed')

        # One of the points of using "muddle pull" internally in the
        # "muddle unstamp -update" command is that we want our "just pulled"
        # list to be available. So check that.
        just_pulled = read_just_pulled()
        if just_pulled != set([
                'checkout:first_co/checked_out',
                'checkout:second_co/checked_out',
                'checkout:(subdomain1)builds/checked_out'
        ]):
            print 'Read _just_pulled as:'
            print just_pulled
            raise GiveUp('Just pulled list does not match')
Exemplo n.º 20
0
def make_old_build_tree():
    """Make a build tree that does a romfs deployment, and use/test it
    """
    with NewDirectory('build.old') as d:
        muddle(['bootstrap', 'git+file:///nowhere', 'cpio-test-build'])

        with Directory('src'):
            with Directory('builds'):
                touch('01.py', DEPLOYMENT_BUILD_DESC_12)
                # Then remove the .pyc file, because Python probably won't realise
                # that this new 01.py is later than the previous version
                os.remove('01.pyc')

            with NewDirectory('first_co'):
                git('init')
                touch('Makefile.muddle',
                      MUDDLE_MAKEFILE1.format(progname='program1'))
                touch('program1.c', MAIN_C_SRC.format(progname='program1'))
                touch('instructions.xml', INSTRUCTIONS)
                os.makedirs('etc/init.d')
                touch('etc/init.d/rcS', '# A pretend rcS file\n')
                git('add Makefile.muddle program1.c instructions.xml')
                git('commit -m "A commit"')
                muddle(['import'])

            with NewDirectory('second_co'):
                git('init')
                touch(
                    'Makefile.muddle',
                    MUDDLE_MAKEFILE2.format(progname1='program1',
                                            progname2='program2'))
                touch('program2.c', MAIN_C_SRC.format(progname='program2'))
                # A version of program1 that announces itself as program2
                touch('program1.c', MAIN_C_SRC.format(progname='program2'))
                git('add Makefile.muddle program2.c')
                git('commit -m "A commit"')
                muddle(['import'])

        muddle([])

        with Directory('deploy'):
            with Directory('everything'):
                check_specific_files_in_this_dir(['root.romfs'])
Exemplo n.º 21
0
    def build_label(self, builder, label):
        """
        Build the relevant label. We'll assume that the
        checkout actually exists.
        """
        tag = label.tag

        self.ensure_dirs(builder, label)

        # XXX We have no way of remembering a checkout in a different domain
        # XXX (from the label we're building) so for the moment we won't even
        # XXX try...
        tmp = Label(utils.LabelType.Checkout, self.co, domain=label.domain)
        co_path = builder.db.get_checkout_path(tmp)
        with Directory(co_path):
            self._amend_env(co_path)

            makefile_name = deduce_makefile_name(self.makefile_name,
                                                 self.per_role_makefiles,
                                                 label.role)

            make_cmd = self._make_command(builder, makefile_name)

            if (tag == utils.LabelTag.PreConfig):
                # Preconfigure - nothing need be done
                pass
            elif (tag == utils.LabelTag.Configured):
                # We should probably do the configure thing ..
                if (self.has_make_config):
                    utils.run0(make_cmd + ["config"])
            elif (tag == utils.LabelTag.Built):
                utils.run0(make_cmd)
            elif (tag == utils.LabelTag.Installed):
                utils.run0(make_cmd + ["install"])
            elif (tag == utils.LabelTag.PostInstalled):
                if (self.rewriteAutoconf):
                    #print "> Rewrite autoconf for label %s"%(label)
                    obj_path = builder.package_obj_path(label)
                    #print ">obj_path = %s"%(obj_path)
                    if (self.execRelPath is None):
                        sendExecPrefix = None
                    else:
                        sendExecPrefix = os.path.join(obj_path,
                                                      self.execRelPath)

                    rewrite.fix_up_pkgconfig_and_la(builder,
                                                    obj_path,
                                                    execPrefix=sendExecPrefix)
            elif (tag == utils.LabelTag.Clean):
                utils.run0(make_cmd + ["clean"])
            elif (tag == utils.LabelTag.DistClean):
                utils.run0(make_cmd + ["distclean"])
            else:
                raise utils.MuddleBug("Invalid tag specified for "
                                      "MakePackage building %s" % (label))
Exemplo n.º 22
0
    def push(self, builder, co_label, upstream=None, repo=None, verbose=True):
        """
        Push changes in the local repository to the remote repository.

        If 'upstream' and 'repo' are given, then they specify the upstream
        repository we should push to, instead of using the 'normal'
        repository from the build description.

        Note that in a centralised VCS, like subversion, this is typically
        called "commit", since there is no local repository.

        This operaton does not do a 'commit'.
        """
        if not (upstream and repo):
            repo = builder.db.get_checkout_repo(co_label)

        if not repo.push:
            raise GiveUp(
                'Failure pushing %s in %s:\n'
                '  %s does not allow "push"' %
                (co_label, builder.db.get_checkout_location(co_label), repo))

        # XXX ---- experimental
        expected_branch = self.branch_to_follow(builder, co_label)
        if expected_branch is None:
            expected_branch = repo.branch
        if expected_branch is not None:
            actual_branch = self.get_current_branch(builder, co_label)
            if expected_branch != actual_branch:
                raise GiveUp(
                    'Checkout %s in directory %s\n'
                    'is on branch %s, but should be on branch %s.\n'
                    'Use "muddle query checkout-branches" for more information.\n'
                    'Refusing to push. Use %s directly if that is what you'
                    ' really meant' %
                    (co_label.name, builder.db.get_checkout_location(co_label),
                     actual_branch, expected_branch, self.vcs.short_name))
        # XXX ----

        options = builder.db.get_checkout_vcs_options(co_label)
        try:
            with Directory(builder.db.get_checkout_path(co_label)):
                self.vcs.push(repo,
                              options,
                              upstream=upstream,
                              verbose=verbose)
        except MuddleBug as err:
            raise MuddleBug(
                'Error pushing %s in %s:\n%s' %
                (co_label, builder.db.get_checkout_location(co_label), err))
        except (GiveUp, Unsupported) as err:
            raise GiveUp(
                'Failure pushing %s in %s:\n%s' %
                (co_label, builder.db.get_checkout_location(co_label), err))
Exemplo n.º 23
0
    def build_label(self, builder, label):
        """
        Actually install the dev package.
        """
        self.ensure_dirs(builder, label)

        tag = label.tag

        if (tag == utils.LabelTag.PreConfig):
            # Nothing to do
            pass
        elif (tag == utils.LabelTag.Configured):
            pass
        elif (tag == utils.LabelTag.Built):
            pass
        elif (tag == utils.LabelTag.Installed):
            # Extract into /obj
            inv = builder
            extract_into_obj(inv, self.co_name, label, self.pkg_file)
            if (self.nonDevPkgFile is not None):
                extract_into_obj(inv, self.nonDevCoName, label,
                                 self.nonDevPkgFile)

            # Now we rewrite all the absolute links to be relative to the install
            # directory.
            rewrite_links(inv, label)

        elif (tag == utils.LabelTag.PostInstalled):
            if self.post_install_makefile is not None:
                inv = builder
                tmp = Label(utils.LabelType.Checkout,
                            self.co_name,
                            domain=label.domain)
                co_path = inv.checkout_path(tmp)
                with Directory(co_path):
                    utils.run0([
                        "make", "-f", self.post_install_makefile,
                        "%s-postinstall" % (label.name)
                    ])

            # .. and now we rewrite any pkgconfig etc. files left lying
            # about.
            obj_path = builder.package_obj_path(label)
            print "> Rewrite .pc and .la files in %s" % (obj_path)
            rewrite.fix_up_pkgconfig_and_la(builder, obj_path)

        elif (tag == utils.LabelTag.Clean or tag == utils.LabelTag.DistClean):
            # Just remove the object directory.
            inv = builder
            utils.recursively_remove(inv.package_obj_path(label))
        else:
            raise utils.MuddleBug("Invalid tag specified for deb pkg %s" %
                                  (label))
Exemplo n.º 24
0
def check_checkout_files(d):
    """Check we have all the files we should have after checkout

    'd' is the current Directory.
    """
    def check_dot_muddle(is_subdomain):
        with Directory('.muddle') as m:
            check_files([
                m.join('Description'),
                m.join('RootRepository'),
                m.join('VersionsRepository')
            ])

            if is_subdomain:
                check_files([m.join('am_subdomain')])

            with Directory(m.join('tags', 'checkout')) as c:
                check_files([
                    c.join('builds', 'checked_out'),
                    c.join('first_co', 'checked_out'),
                    c.join('main_co', 'checked_out'),
                    c.join('second_co', 'checked_out')
                ])

    def check_src_files(main_c_file='main0.c'):
        check_files([
            s.join('builds', '01.py'),
            s.join('main_co', 'Makefile.muddle'),
            s.join('main_co', main_c_file),
            s.join('first_co', 'Makefile.muddle'),
            s.join('first_co', 'first.c'),
            s.join('second_co', 'Makefile.muddle'),
            s.join('second_co', 'second.c')
        ])

    check_dot_muddle(is_subdomain=False)
    with Directory('src') as s:
        check_src_files('main0.c')

    with Directory(d.join('domains', 'subdomain1', 'src')) as s:
        check_src_files('subdomain1.c')
    with Directory(d.join('domains', 'subdomain1')):
        check_dot_muddle(is_subdomain=True)

    with Directory(
            d.join('domains', 'subdomain1', 'domains', 'subdomain3',
                   'src')) as s:
        check_src_files('subdomain3.c')
    with Directory(d.join('domains', 'subdomain1', 'domains', 'subdomain3')):
        check_dot_muddle(is_subdomain=True)

    with Directory(d.join('domains', 'subdomain2', 'src')) as s:
        check_src_files('subdomain2.c')
    with Directory(d.join('domains', 'subdomain2')):
        check_dot_muddle(is_subdomain=True)
Exemplo n.º 25
0
    def revision_to_checkout(self,
                             builder,
                             co_label,
                             force=False,
                             before=None,
                             verbose=False,
                             show_pushd=True):
        """
        Determine a revision id for this checkout, usable to check it out again.

        The revision id we want is that we could use to check out an identical
        checkout.

        If the local working set/repository/whatever appears to have been
        altered from the remove repository, or otherwise does not yield a
        satisfactory revision id (this is something only the subclass can
        tell), then the method should raise GiveUp, with as clear an
        explanation of the problem as possible.

        If 'force' is true, then if the revision cannot be determined, return
        the orginal revision that was specified when the checkout was checked
        out.

            (Individual version control classes may opt to ignore the 'force'
            argument, either because it is not useful in their context, or
            because they can tell that the checkout is seriously
            astray/broken.)

        If 'before' is given, it should be a string describing a date/time, and
        the revision id chosen will be the last revision at or before that
        date/time.

        .. note:: This depends upon what the VCS concerned actually supports.
           This feature is experimental.

        NB: if 'before' is specified, 'force' is ignored.

        If 'show_pushd' is false, then we won't report as we "pushd" into the
        checkout directory.

        NB: If the VCS class does not override this method, then the default
        implementation will raise a GiveUp unless 'force' is true, in which
        case it will return the string '0'.
        """
        co_dir = builder.db.get_checkout_path(co_label)
        parent_dir, co_leaf = os.path.split(co_dir)
        repo = builder.db.get_checkout_repo(co_label)
        options = builder.db.get_checkout_vcs_options(co_label)
        with Directory(co_dir, show_pushd=show_pushd):
            return self.vcs.revision_to_checkout(repo, co_leaf, options, force,
                                                 before, verbose)
Exemplo n.º 26
0
def test_issue_249_single_digit_version_number(d, repo):
    banner('TEST ISSUE 249')
    banner('Check out build tree, and stamp it as release version 1', 2)
    with NewCountedDirectory('build.version-number') as build:
        r = 'git+file://{repo}/main'.format(repo=repo)
        d = 'builds/01.py'
        v = '{root}/versions'.format(root=r)
        muddle(['init', r, d])
        muddle(['checkout', '_all'])
        muddle(['stamp', 'release', 'simple', '1'])
        with Directory('versions'):
            check_specific_files_in_this_dir(['.git', 'simple_1.release'])
            check_release_file_starts('simple_1.release', 'simple', '1', 'tar',
                                      'gzip', r, d, v)
Exemplo n.º 27
0
def add_some_instructions(d):
    """Add some instruction file by hand.

    We should do this properly, via Makefiles copying instructions with
    ``$(MUDDLE_INSTRUCT)``, but this is simpler.
    """
    with Directory('.muddle'):
        with NewDirectory('instructions'):
            with NewDirectory('first_pkg'):
                touch('_default.xml', INSTRUCTIONS)
            with NewDirectory('second_pkg'):
                touch('_default.xml', INSTRUCTIONS)
                touch('x86.xml', INSTRUCTIONS)
                touch('arm.xml', INSTRUCTIONS)
                touch('fred.xml', INSTRUCTIONS)  # How did that get here?
Exemplo n.º 28
0
    def pull(self, builder, co_label, upstream=None, repo=None, verbose=True):
        """
        Retrieve changes from the remote repository, and apply them to
        the local working copy, but not if a merge operation would be
        required, in which case an exception shall be raised.

        If 'upstream' and 'repo' are given, then they specify the upstream
        repository we should pull from, instead of using the 'normal'
        repository from the build description.

        Returns True if it changes its checkout (changes the files visible
        to the user), False otherwise.
        """
        if not (upstream and repo):
            repo = builder.db.get_checkout_repo(co_label)

        if not repo.pull:
            raise GiveUp(
                'Failure pulling %s in %s:\n'
                '  %s does not allow "pull"' %
                (co_label, builder.db.get_checkout_location(co_label), repo))

        specific_branch = self.branch_to_follow(builder, co_label)
        if specific_branch:
            # The build description told us to follow it, onto this branch
            # - so let's remember it on the Repository
            repo = repo.copy_with_changed_branch(specific_branch)
            print 'Specific branch %s in %s' % (specific_branch, co_label)

        options = builder.db.get_checkout_vcs_options(co_label)
        try:
            with Directory(builder.db.get_checkout_path(co_label)):
                return self.vcs.pull(repo,
                                     options,
                                     upstream=upstream,
                                     verbose=verbose)
        except MuddleBug as err:
            raise MuddleBug(
                'Error pulling %s in %s:\n%s' %
                (co_label, builder.db.get_checkout_location(co_label), err))
        except Unsupported as err:
            raise Unsupported(
                'Not pulling %s in %s:\n%s' %
                (co_label, builder.db.get_checkout_location(co_label), err))
        except GiveUp as err:
            raise GiveUp(
                'Failure pulling %s in %s:\n%s' %
                (co_label, builder.db.get_checkout_location(co_label), err))
Exemplo n.º 29
0
    def status(self, builder, co_label, verbose=False, quick=False):
        """
        Report on the status of the checkout, in a VCS-appropriate manner

        If there is nothing to be done for this repository, returns None.

        Otherwise, returns a string comprising a report on the status
        of the repository, in a VCS appropriate manner.

        If 'verbose', then report each checkout label as it is checked.

        The reliability and accuracy of this varies by VCS, but the idea
        is that a checkout is 'safe' if:

        * there are no files in the local checkout that are not also in the
          (local) repository, unless explicitly marked to be ignored
        * there are no files that need committing to the local repository

        In general, if a checkout is 'safe' then it should be OK to 'merge'
        the remote repository into it.
        """
        if verbose:
            print '>>', co_label
        repo = builder.db.get_checkout_repo(co_label)
        options = builder.db.get_checkout_vcs_options(co_label)
        try:
            # If we try to go to a directory that doesn't exist, then
            # Directory will raise GiveUp with an explanatory message
            with Directory(builder.db.get_checkout_path(co_label),
                           show_pushd=False):
                status_text = self.vcs.status(repo, options, quick=quick)
                if status_text:
                    full_text = '%s status for %s in %s:\n%s' % (
                        self.vcs.short_name, co_label,
                        builder.db.get_checkout_location(co_label),
                        status_text)
                    return full_text
                else:
                    return None
        except MuddleBug as err:
            raise MuddleBug(
                'Error finding status for %s in %s:\n%s' %
                (co_label, builder.db.get_checkout_location(co_label), err))
        except GiveUp as err:
            raise GiveUp(
                'Failure finding status for %s in %s:\n%s' %
                (co_label, builder.db.get_checkout_location(co_label), err))
Exemplo n.º 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))

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