Exemple #1
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)
Exemple #2
0
def test_options():
    """Test we can read back options from a stamp file.
    """
    fname = 'test_options.stamp'
    touch(fname, OPTIONS_TEST)
    v = VersionStamp.from_file(fname)

    if len(v.problems) != 4:
        raise GiveUp('Expected 4 problems reading %s, got %d' %
                     (fname, len(v.problems)))

    # Make the problem order deterministic
    v.problems.sort()

    check_problem(
        v.problems[0],
        "Cannot convert value to integer, for 'option~BadFred = int:ThreadNeedle'"
    )
    check_problem(
        v.problems[1],
        "No datatype (no colon in value), for 'option~Aha~There = No colons here'"
    )
    check_problem(
        v.problems[2],
        "Unrecognised datatype 'what' (not bool, int or str), for 'option~AhaTwo = what:pardon'"
    )
    check_problem(
        v.problems[3],
        "Value is not True or False, for 'option~BadJim = bool:Immensity'")

    co_label = Label(LabelType.Checkout, 'co_name', None, LabelTag.CheckedOut)
    co_dir, co_leaf, repo = v.checkouts[co_label]
    options = v.options[co_label]

    expected_repo = 'file:///Users/tibs/sw/m3/tests/transient/repo/second_co'
    if co_dir is not None or co_leaf != 'co_name' or \
       str(repo) != expected_repo:
        raise GiveUp('Error in reading checkout back\n'
                     '  co_dir %s, expected None\n'
                     '  co_leaf %s, expected co_name\n'
                     '  repo     %s\n'
                     '  expected %s' % (co_dir, co_leaf, repo, expected_repo))

    if len(options) != 3 or \
            options['Jim'] != False or \
            options['Bill'] != 'Some sort of string' or \
            options['Fred'] != 99:
        raise GiveUp(
            'Error in reading checkout options back\n'
            "  expected {'Jim': False, 'Bill': 'Some sort of string', 'Fred': 99}\n"
            '  got      %s' % options)
Exemple #3
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))
Exemple #4
0
def get_vcs_docs(vcs):
    """Given a VCS short name, return the docs for how muddle handles it
    """
    try:
        return vcs_docs[vcs]
    except KeyError:
        raise GiveUp("No VCS handler registered for VCS type %s" % vcs)
Exemple #5
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))
Exemple #6
0
def check_release_file_starts(filename, name, version, archive, compression,
                              repo, desc, versions_repo):
    with open(filename) as fd:
        lines = fd.readlines()
    newlines = []
    for line in lines:
        if line[0] == '#':
            continue
        while line and line[-1] in ('\n', '\r'):
            line = line[:-1]
        if line:
            newlines.append(line)

    expected = [
        '[STAMP]',
        'version = 2',
        '[RELEASE]',
        'name = %s' % name,
        'version = %s' % version,
        'archive = %s' % archive,
        'compression = %s' % compression,
        '[ROOT]',
        'repository = %s' % repo,
        'description = %s' % desc,
        'versions_repo = %s' % versions_repo,
    ]
    if newlines[:11] != expected:
        print '--- Expected:'
        pprint.pprint(expected)
        print '--- Got:'
        pprint.pprint(newlines[:11])
        raise GiveUp('Unexpected content in release stamp file %s' % filename)
Exemple #7
0
def test_test_release(d, repo):
    banner('TEST TEST RELEASE')
    banner('Check out build tree, and stamp it as a release', 2)
    with NewCountedDirectory('build-test') as test_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', 'v1.0'])

        rfile = os.path.join(test_build.where, 'versions',
                             'simple_v1.0.release')
        check_release_file_starts(rfile, 'simple', 'v1.0', 'tar', 'gzip', r, d,
                                  v)

        UNSET = '(unset)'
        muddle_env = read_env_as_dict('first_pkg{x86}')
        if not (muddle_env['MUDDLE_RELEASE_NAME'] == UNSET
                and muddle_env['MUDDLE_RELEASE_VERSION'] == UNSET
                and muddle_env['MUDDLE_RELEASE_HASH'] == UNSET):
            print 'MUDDLE_RELEASE_NAME=%s' % muddle_env['MUDDLE_RELEASE_NAME']
            print 'MUDDLE_RELEASE_VERSION=%s' % muddle_env[
                'MUDDLE_RELEASE_VERSION']
            print 'MUDDLE_RELEASE_HASH=%s' % muddle_env['MUDDLE_RELEASE_HASH']
            raise GiveUp(
                'Expected the MUDDLE_RELEASE_ values to be all (unset)')

        banner(
            'Try "muddle release -test" using that stamp, in the same directory',
            2)
        muddle(['release', '-test', rfile])
        check_release_directory(test_build)
Exemple #8
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))
    def ssh_remote_cmd(self, remote_cmd, dirs=None, dry_run=False):
        """SSH to our location, and run the command over the directories.

        * 'remote_cmd' is the words that make up the command (as a list).
        * 'dirs' is the list of directories we want to pass to the command.
          If this is None, or an empty list, then we won't do that...
        """
        parts = ['ssh']
        if self.port:
            parts.append('-p %s' % self.port)
        parts.append(self.user_at_host)
        parts += remote_cmd
        cmd = ' '.join(parts)
        if dry_run:
            print "Would run: %s " % cmd
            if dirs:
                print "and pass it the following directories:"
                print "\n".join(dirs)
        elif dirs:
            print "> %s" % cmd
            p = subprocess.Popen(parts,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT)
            stdoutdata, stderrdata = p.communicate("\n".join(dirs) + '\n')
            if p.returncode:
                print >> sys.stderr, "Error invoking the remote script (rc=%d):" % p.returncode
                print >> sys.stderr, stdoutdata
                raise GiveUp("Error invoking the remote script, rc=%d" %
                             p.returncode)
            print "Script exited successfully, output was:\n%s\n<<<END OUTPUT>>>\n" % stdoutdata
        else:
            run0(cmd)
Exemple #10
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)
Exemple #11
0
 def _git_describe_long(self,
                        co_leaf,
                        orig_revision,
                        force=False,
                        verbose=True):
     """
     This returns a "pretty" name for the revision, but only if there
     are annotated tags in its history.
     """
     retcode, revision = utils.run2('git describe --long',
                                    show_command=False)
     if retcode:
         if revision:
             text = utils.indent(revision.strip(), '    ')
             if force:
                 if verbose:
                     print "'git describe --long' had problems with checkout" \
                           " '%s'"%co_leaf
                     print "    %s" % text
                     print "using original revision %s" % orig_revision
                 return orig_revision
         else:
             text = '    (it failed with return code %d)' % retcode
         raise GiveUp("%s\n%s" % (utils.wrap(
             "%s: 'git describe --long'"
             " could not determine a revision id for checkout:" % co_leaf),
                                  text))
     return revision.strip()
Exemple #12
0
    def push(self, repo, options, upstream=None, verbose=True):
        """
        Will be called in the actual checkout's directory.

        XXX Should we grumble if the 'effective' branch is not the same as
        XXX the branch that is currently checked out?
        """
        self._shallow_not_allowed(options)

        if self._is_detached_HEAD():
            raise GiveUp(
                'This checkout is in "detached HEAD" state, it is not\n'
                'on any branch, and thus "muddle push" is not alllowed.\n'
                'If you really want to push, first choose a branch,\n'
                'e.g., "git checkout -b <new-branch-name>"')

        # Push this branch to the branch of the same name, whether it exists
        # yet or not
        effective_branch = 'HEAD'

        if not upstream:
            # If we're not given an upstream repository name, assume we're
            # dealing with an "ordinary" push, to our origin
            upstream = 'origin'

        # For an upstream, we won't necessarily have the remote in our
        # configuration (unless we already did an upstream pull from the same
        # repository...)
        self._setup_remote(upstream, repo, verbose=verbose)

        utils.shell(["git", "push", upstream, effective_branch],
                    show_command=verbose)
Exemple #13
0
    def __init__(self, name, category, version=None):
        """Initialise a new License.

        The 'name' is the name of this license, as it is normally recognised.

        'category' is meant to be a broad categorisation of the type of the
        license. Currently that is one of:

            * 'gpl' - some sort of GPL license, which propagate the need to
              distribute source code to other "adjacent" entities
            * 'open-source' - an open source license, anything that is not 'gpl'.
              Source code may, but need not be, distributed.
            * 'prop-source' - a proprietary source license, not an open source
              license. This might, for instance, be used for /etc files, which
              are distributed as "source code" (i.e., text), but are not
              in fact licensed under an open source license.
            * 'binary' - a binary license, indicating that the source code is
              not to be distributed, but binary (the contents of the "install"
              directory) may be.
            * 'private' - a marker that the checkout should not be distributed
              at all.

        'version' may be a version string. If it is None, then it will not be
        shown in the str() or repr() for a license.
        """
        self.name = name
        if category not in ALL_LICENSE_CATEGORIES:
            raise GiveUp("Attempt to create License '%s' with unrecognised"
                         " category '%s'" % (name, category))
        self.category = category
        self.version = version
Exemple #14
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)
Exemple #15
0
    def apply_instructions(self, builder, label, prepare, deploy_path):

        for asm in self.assemblies:
            lbl = Label(utils.LabelType.Package,
                        '*',
                        asm.from_label.role,
                        '*',
                        domain=asm.from_label.domain)

            if not asm.obeyInstructions:
                continue

            instr_list = builder.load_instructions(lbl)
            for (lbl, fn, instrs) in instr_list:
                print "%s deployment: Applying instructions for role %s, label %s .. " % (
                    self.what, lbl.role, lbl)
                for instr in instrs:
                    # Obey this instruction.
                    iname = instr.outer_elem_name()
                    print 'Instruction:', iname
                    if iname in self.app_dict:
                        if prepare:
                            self.app_dict[iname].prepare(
                                builder, instr, lbl.role, deploy_path)
                        else:
                            self.app_dict[iname].apply(builder, instr,
                                                       lbl.role, deploy_path)
                    else:
                        raise GiveUp(
                            "%s deployments don't know about instruction %s" %
                            (self.what, iname) +
                            " found in label %s (filename %s)" % (lbl, fn))
Exemple #16
0
def check_problem(got, starts):
    """We can't be bothered to check ALL of the string...
    """
    if not got.startswith(starts):
        raise GiveUp('Problem report does not start with what we expect\n'
                     'Got:    %s\n'
                     'Wanted: %s ...' % (got, starts))
Exemple #17
0
def check_text_lines_v_lines(actual_lines,
                             wanted_lines,
                             fold_whitespace=False):
    """Check two pieces of text are the same.

    'wanted_lines' is the lines of text we want, presented as a list,
    without any newlines.

    If 'fold_whitespace' is true, first "fold" any sequences of whitespace
    in 'wanted_lines' to a single space each. This makes it easier to compare
    lines with data laid out using spacing.

    Prints out the differences (if any) and then raises a GiveUp if there
    *were* differences
    """

    if fold_whitespace:
        compare_lines = []
        for line in actual_lines:
            columns = line.split()
            line = ' '.join(columns)
            compare_lines.append(line)
    else:
        compare_lines = actual_lines

    diffs = unified_diff(wanted_lines,
                         compare_lines,
                         fromfile='Missing lines',
                         tofile='Extra lines',
                         lineterm='')
    difflines = list(diffs)
    if difflines:
        lines = ['Text did not match'] + list(difflines)
        raise GiveUp('\n'.join(lines))
Exemple #18
0
    def _calculate_revision(self,
                            co_leaf,
                            orig_revision,
                            force=False,
                            before=None,
                            verbose=True):
        """
        This returns a bare SHA1 object name for the current HEAD

        NB: if 'before' is specified, 'force' is ignored.
        """
        if before:
            print "git rev-list -n 1 --before='%s' HEAD" % before
            retcode, revision = utils.run2(
                "git rev-list -n 1 --before='%s' HEAD" % before,
                show_command=False)
            print retcode, revision
            if retcode:
                if revision:
                    text = utils.indent(revision.strip(), '    ')
                else:
                    text = '    (it failed with return code %d)' % retcode
                raise GiveUp("%s\n%s" % (utils.wrap(
                    "%s:"
                    " \"git rev-list -n 1 --before='%s' HEAD\"'"
                    " could not determine a revision id for checkout:" %
                    (co_leaf, before)), text))
        else:
            retcode, revision = utils.run2('git rev-parse HEAD',
                                           show_command=False)
            if retcode:
                if revision:
                    text = utils.indent(revision.strip(), '    ')
                    if force:
                        if verbose:
                            print "'git rev-parse HEAD' had problems with checkout" \
                                  " '%s'"%co_leaf
                            print "    %s" % text
                            print "using original revision %s" % orig_revision
                        return orig_revision
                else:
                    text = '    (it failed with return code %d)' % retcode
                raise GiveUp("%s\n%s" % (utils.wrap(
                    "%s: 'git rev-parse HEAD'"
                    " could not determine a revision id for checkout:" %
                    co_leaf), text))
        return revision.strip()
Exemple #19
0
    def __init__(self, name, role, pkgs_to_install, os_version=None):
        """Our arguments are:

        * 'name' - the name of this builder
        * 'role' - the role to which it belongs
        * 'pkgs_to_install' - a sequence specifying which packages are to be
          installed.

        Each item in the sequence 'pkgs_to_install' can be:

        * the name of an OS package to install - for instance, 'libxml2-dev'

          (this is backwards compatible with how this class worked in the past)

        * a Choice allowing a particular package to be selected according to
          the operating system.

          See "muddle doc Choice" for details on the Choice class.

          Note that a choice resulting in None (i.e., where the default value
          is None, and the default is selected) will not do anything.

          If 'os_version' is given, then it will be used as the version name,
          otherwise the result of calling utils.get_os_version_name() will be
          used.

        We also allow a single string, or a single Choice, treated as if they
        were wrapped in a list.
        """
        super(AptGetBuilder, self).__init__(name, role)

        actual_packages = []

        if os_version is None:
            os_verson = get_os_version_name()

        if isinstance(pkgs_to_install, basestring):
            # Just a single package
            actual_packages.append(pkgs_to_install)
        elif isinstance(pkgs_to_install, Choice):
            # Just a single Choice
            # Make a choice according to the OS info
            choice = pkgs_to_install.choose_to_match_os(os_version)
            if choice is not None:
                actual_packages.append(choice)
        else:
            for pkg in pkgs_to_install:
                if isinstance(pkg, basestring):
                    actual_packages.append(pkg)
                elif isinstance(pkg, Choice):
                    # Make a choice according to the OS info
                    choice = pkg.choose_to_match_os(os_version)
                    if choice is not None:
                        actual_packages.append(choice)
                else:
                    raise GiveUp('%r is not a string or a Choice' % pkg)

        self.pkgs_to_install = actual_packages
Exemple #20
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))
Exemple #21
0
def broken_muddle(cmd_list, error=None, endswith=None):
    try:
        text = captured_muddle(cmd_list)
        raise GiveUp('Command unexpectedly worked, returned %r' % text)
    except CalledProcessError as e:
        stripped = e.output.strip()
        if error:
            check_text(stripped, error)
        else:
            if not stripped.endswith(endswith):
                raise GiveUp(
                    'Wrong error for "muddle %s"\n'
                    'Got:\n'
                    '  %s\n'
                    'Expected it to end:\n  %s' %
                    (' '.join(cmd_list), '\n  '.join(stripped.splitlines()),
                     '\n  '.join(endswith.splitlines())))
        print 'Successfully failed'
        print
Exemple #22
0
 def _git_rev_parse_HEAD(self):
     """
     This returns a bare SHA1 object name for the current HEAD
     """
     retcode, revision = utils.run2('git rev-parse HEAD',
                                    show_command=False)
     if retcode:
         raise GiveUp("'git rev-parse HEAD' failed with return code %d" %
                      retcode)
     return revision.strip()
Exemple #23
0
def expand_revision(revision):
    """Given something that names a revision, return its full SHA1.

    Raises GiveUp if the revision appears non-existent or ambiguous
    """
    rv, out = utils.run2('git rev-parse %s' % revision, show_command=False)
    if rv:
        raise GiveUp('Revision "%s" is either non-existant or ambiguous' %
                     revision)
    return out.strip()
Exemple #24
0
def is_detached_head():
    retcode, out = run2('git symbolic-ref -q HEAD')
    if retcode == 0:
        # HEAD is a symbolic reference - so not detached
        return False
    elif retcode == 1:
        # HEAD is not a symbolic reference, but a detached HEAD
        return True
    else:
        raise GiveUp(
            'Error running "git symbolic-ref -q HEAD" to detect detached HEAD')
Exemple #25
0
    def _calculate_revision(self, co_leaf, orig_revision):
        """
        This returns a bare SHA1 object name for orig_revision

        NB: if 'before' is specified, 'force' is ignored.
        """
        retcode, revision, ignore = utils.run3('git rev-parse %s' %
                                               orig_revision)
        if retcode:
            if revision:
                text = utils.indent(revision.strip(), '    ')
                raise GiveUp("%s\n%s" % (utils.wrap(
                    "%s: 'git rev-parse HEAD'"
                    " could not determine a revision id for checkout:" %
                    co_leaf), text))
            else:
                raise GiveUp("%s\n" % (utils.wrap(
                    "%s: 'git rev-parse HEAD'"
                    " could not determine a revision id for checkout:" %
                    co_leaf)))
        return revision.strip()
Exemple #26
0
 def revision_to_checkout(self,
                          repo,
                          co_leaf,
                          options,
                          force=False,
                          before=None,
                          verbose=True):
     """
     Will be called in the actual checkout's directory.
     """
     raise GiveUp("VCS '%s' cannot calculate a checkout revision" %
                  self.long_name)
Exemple #27
0
def check_nosuch_files(paths, verbose=True):
    """Given a list of paths, check they do not exist.
    """
    if verbose:
        flushing_print('++ Checking files do not exist\n')
    for name in paths:
        if os.path.exists(name):
            raise GiveUp('File %s exists' % name)
        else:
            if verbose:
                sys.sydout.write('  -- %s\n' % name)
    if verbose:
        flushing_print('++ All named files do not exist\n')
Exemple #28
0
def check_cmd(command, expected='', unsure=False):
    """Check we get the expected output from 'muddle -n <command>'

    * If 'expected' is given, then it is a string of the expected labels
      separated by spaces
    * If 'unsure' is true, then 'expected' is ignored, and we expect
      the result of the command to be:

        'Not sure what you want to <command>'

      and an error code.
    """
    retcode, result = run2('{muddle} -n {cmd}'.format(muddle=MUDDLE_BINARY,
                                                      cmd=command))
    result = result.strip()
    lines = result.split('\n  ')

    if unsure:
        command_words = command.split(' ')
        wanted = 'Not sure what you want to {cmd}'.format(cmd=command_words[0])
        line0 = lines[0].strip()
        if retcode:
            if line0 == wanted:
                return
            else:
                raise GiveUp('Wanted "{0}" but got "{1} and'
                             ' retcode {2}"'.format(wanted, line0, retcode))
        else:
            raise GiveUp('Expecting failure and "{0}",'
                         ' got "{1}"'.format(wanted, line0))
    elif retcode:
        raise GiveUp('Command failed with retcode {0},'
                     ' got unexpected {1}'.format(retcode, result))

    lines = lines[1:]  # Drop the "explanation"
    #map(string.strip, lines)
    got = ' '.join(lines)
    if got != expected:
        raise GiveUp('Expected "{0}", got "{1}"'.format(expected, got))
Exemple #29
0
    def goto_branch(self, branch, verbose=False):
        """
        Make the named branch the current branch.

        Will be called in the actual checkout's directory.

        It is an error if the branch does not exist, in which case a GiveUp
        exception will be raised.
        """
        retcode, out = utils.run2(['git', 'checkout', branch],
                                  show_command=verbose)
        if retcode:
            raise GiveUp('Error going to branch "%s": %s' % (branch, out))
Exemple #30
0
def check_exception(testing,
                    fn,
                    args,
                    exception=GiveUp,
                    startswith=None,
                    endswith=None):
    """Check we get the right sort of exception.
    """
    if not startswith and not endswith:
        raise ValueError('ERROR TESTING: need startswith or endswith')

    print testing
    ok = False
    try:
        fn(*args)
    except exception as e:
        if startswith:
            if str(e).startswith(startswith):
                ok = True
            else:
                raise GiveUp('Unexpected %s exception: %s\n'
                             '  (does not start with %r)' %
                             (e.__class__.__name__, e, startswith))
        if endswith:
            if str(e).endswith(endswith):
                ok = True
            else:
                raise GiveUp('Unexpected %s exception: %s\n'
                             '  (does not end with %r)' %
                             (e.__class__.__name__, e, endswith))
    if ok:
        print 'Fails OK'
    else:
        if startswith:
            raise GiveUp('Did not get an exception, so not starting %r' %
                         startswith)
        else:
            raise GiveUp('Did not get an exception, so not ending %r' %
                         endswith)