示例#1
0
    def status(self, repo, options, quick=False):
        """
        Will be called in the actual checkout's directory.

        Return status text or None if there is no interesting status.
        """

        #just return an error message, don't check anything
        if quick:
            return "muddle status -quick is not supported on svn checkouts"

        text = utils.get_cmd_data("svn status --show-updates --verbose")

        lines = text.split('\n')
        stuff = []
        seven_spaces = ' '*7
        for line in lines:
            # The first 7 characters and the 9th give us our status
            if line.startswith(seven_spaces) and line[8] == ' ':
                continue
            elif line == '':    # typically, a blank final line
                continue
            else:
                stuff.append(line)

        # Was it just reporting that nothing happened in this particular
        # revision?
        if len(stuff) == 1 and stuff[0].startswith('Status against revision'):
            stuff = []

        if stuff:
            stuff.append('')        # add back a cosmetic blank line
            return '\n'.join(stuff)
        else:
            return None
示例#2
0
    def pull(self, repo, options, upstream=None, verbose=True):
        """
        Will be called in the actual checkout's directory.

        This runs Subversion's "update", but only if no merging will be
        needed. That is, first it runs "svn status", and if any lines
        contain a "C" (for Conflict) in columns 0, 1 or 6, then it will not
        perform the update.

          ("svn help status" would call those columns 1, 2 and 7)
        """
        if repo.branch:
            raise utils.GiveUp("Subversion does not support branch"
                               " in 'pull' (branch='%s')"%repo.branch)
        text = utils.get_cmd_data("svn status")
        for line in text:
            if 'C' in (line[0], line[1], line[6]):
                raise utils.GiveUp("%s: 'svn status' says there is a Conflict,"
                                    " refusing to pull:\n%s\nUse 'muddle merge'"
                                    " if you want to merge"%(utils.indent(text,'    ')))

        starting_revno = self._just_revno()

        utils.shell(["svn", "update"] + self._r_option(repo.revision), show_command=verbose)

        # We could try parsing the output of 'svn update' instead, but this is
        # simpler to do...
        ending_revno = self._just_revno()
        # Did we update anything?
        return starting_revno != ending_revno
示例#3
0
    def revision_to_checkout(self, repo, co_leaf, options, force=False, before=None, verbose=False):
        """
        Determine a revision id for this checkout, usable to check it out again.

        Uses 'svnversion', which I believe is installed as standard with 'svn'

        For the moment, at lease, the 'force' argument is ignored (so the
        working copy must be be equivalent to the repository).
        """
        if before:
            raise utils.GiveUp('%s: "before" argument not currently supported'%co_leaf)

        revision = utils.get_cmd_data('svnversion', show_command=verbose)
        revision = revision.strip()
        if all([x.isdigit() for x in revision]):
            return revision
        else:
            raise utils.GiveUp("%s: 'svnversion' reports checkout has revision"
                    " '%s'"%(co_leaf, revision))
def _do_cmdline(args):
    original_dir = os.getcwd()
    original_env = os.environ.copy()
    dry_run = False
    verbose = False

    # TODO: allow switches after args.
    while args:
        word = args[0]
        if word in ("-h", "--help", "-?"):
            print __doc__
            return
        elif word in ("--dry-run", "-n"):
            dry_run = True
        elif word in ("-v", "--verbose"):
            verbose = True
        elif word[0] == "-":
            raise GiveUp, "Unexpected command line option %s" % word
        else:
            break
        args = args[1:]

    if len(args) != 0:
        raise GiveUp, "Unexpected non-option arguments given"

    builder = find_and_load(original_dir, muddle_binary=None)
    # Don't bother determining muddle_binary: our invocation of find_and_load
    # doesn't make use of it. (Tibs writes: it's only needed for when
    # running makefiles, for when they use $(MUDDLE).)

    if not builder:
        raise GiveUp("Cannot find a build tree.")

    rootrepo = builder.db.RootRepository_pathfile.get()

    rules = builder.all_checkout_rules()
    rr = []
    for r in rules:
        co_dir = builder.db.get_checkout_path(r.target)
        if isinstance(r.action.vcs, muddled.vcs.git.Git):
            if verbose:
                print "In %s:" % co_dir
            os.chdir(co_dir)
            raw = get_cmd_data("git show-ref --heads", verbose=verbose)
            raw_heads = raw[1].rstrip("\n").split("\n")
            pat = re.compile("[0-9a-f]+ refs/heads/(.+)")
            heads = set()
            for h in raw_heads:
                m = pat.match(h)
                if m is None:
                    raise GiveUp("Unparseable output from git: %s" % h)
                heads.add(m.group(1))

            g = r.action.vcs
            # print "heads is %s"%heads.__str__()
            if g.branch is not None:
                if g.branch in heads:
                    if verbose:
                        print "%s: ok (has %s)" % (co_dir, g.branch)
                else:
                    bfrom = "master"
                    # desired branch not found; if we have a master then try to fixup:
                    if bfrom in heads:
                        # if verbose:
                        print "===\nFixing %s: %s --> %s" % (co_dir, bfrom, g.branch)
                        (rc, lines, igno) = get_cmd_data("git status --porcelain -uall", verbose=verbose)
                        lines = lines.rstrip("\n")
                        if lines != "":
                            if not verbose:
                                print "> git status --porcelain -uall"
                            print ">>%s<<" % lines
                            print (
                                "Uncommitted changes or untracked files found in %s, deal with these before continuing"
                                % co_dir
                            )
                            raise GiveUp
                        maybe_run_cmd("git fetch origin %s" % (g.branch), dry_run, verbose)
                        maybe_run_cmd("git fetch origin %s:%s" % (g.branch, g.branch), dry_run, verbose)
                        maybe_run_cmd("git checkout %s" % g.branch, dry_run, verbose)
                        maybe_run_cmd("git config branch.%s.remote origin" % g.branch, dry_run, verbose)
                        maybe_run_cmd("git config branch.%s.merge %s" % (g.branch, g.branch), dry_run, verbose)
                        try:
                            maybe_run_cmd("git branch -d %s" % bfrom, dry_run, verbose)
                        except GiveUp:
                            print "\n* * * HEALTH WARNING * * *"
                            print "Unmerged changes were found committed to the '%s' branch in %s" % (bfrom, co_dir)
                            print "YOU MUST MERGE THESE INTO '%s' YOURSELF OR LOSE THEM!" % g.branch
                            # print "This script will not revisit this checkout."
                            print "The relevant changes are:"
                            run0("git log --oneline --topo-order --graph --decorate=short %s..%s" % (g.branch, bfrom))
                            raise
                    else:
                        raise GiveUp(
                            "Error: %s wants a branch named '%s', does not have one, and does not have a '%s' either - I don't know how to fix this"
                            % (co_dir, g.branch, bfrom)
                        )
            else:
                # want master, don't care about others
                if verbose:
                    print "%s heads are: %s" % (co_dir, heads)
                if not "master" in heads:
                    raise GiveUp(
                        "Error: %s wants a 'master' branch but does not have one, I don't know how to fix this" % co_dir
                    )
        else:
            if verbose:
                print "Ignoring %s (not powered by git)" % co_dir
示例#5
0
def get_stdout(cmd, verbose=True):
    """Run a command in the shell, and grab its (standard) output.
    """
    return get_cmd_data(cmd, show_command=verbose)
示例#6
0
文件: git.py 项目: crazyscot/muddle
    def status(self, repo, options, quick=False):
        """
        Will be called in the actual checkout's directory.

        Return status text or None if there is no interesting status.
        """
        retcode, text = utils.run2("git status --porcelain",
                                   show_command=False)
        if retcode == 129:
            print "Warning: Your git does not support --porcelain; you should upgrade it."
            retcode, text = utils.run2("git status", show_command=False)

        detached_head = self._is_detached_HEAD()

        if detached_head:
            # That's all the user really needs to know
            note = '\n# Note that this checkout has a detached HEAD'
            if text:
                text = '%s\n#%s' % (text, note)
            else:
                text = note

        if text:
            return text

        # git status will tell us if there uncommitted changes, etc., but not if
        # we are ahead of or behind (the local idea of) the remote repository,
        # or it will, but not with --porcelain

        if detached_head:
            head_name = 'HEAD'
        else:
            # First, find out what our HEAD actually is
            retcode, text = utils.run2(
                "git rev-parse --symbolic-full-name HEAD", show_command=False)
            head_name = text.strip()

        # Now we can look up its SHA1, locally
        retcode, head_revision = utils.run2("git rev-parse %s" % head_name,
                                            show_command=False)
        local_head_ref = head_revision.strip()

        if quick:
            branch_name = utils.get_cmd_data("git rev-parse --abbrev-ref HEAD")
            text = utils.get_cmd_data("git show-ref origin/%s" % branch_name)
            ref, what = text.split()
            if ref != local_head_ref:
                return '\n'.join((
                    'After checking local HEAD against our local record of the remote HEAD',
                    '# The local repository does not match the remote:', '#',
                    '#  HEAD   is %s' % head_name,
                    '#  Local  is %s' % local_head_ref,
                    '#  last known origin/%s is %s' % (branch_name, ref), '#',
                    '# You probably need to push or pull.',
                    '# Use "muddle status" without "-quick" to get a better idea'
                ))
            else:
                return None

        # So look up the remote equivalents...
        retcode, text = utils.run2("git ls-remote", show_command=False)
        lines = text.split('\n')
        if retcode:
            # Oh dear - something nasty happened
            # We know we get this if, for instance, the remote repository does
            # not actually exist
            newlines = []
            newlines.append(
                'Whilst trying to check local HEAD against remote HEAD')
            for line in lines:
                newlines.append('# %s' % line)
            return '\n'.join(newlines)
        else:
            for line in lines[1:]:  # The first line is the remote repository
                if not line:
                    continue
                ref, what = line.split('\t')
                if what == head_name:
                    if ref != local_head_ref:
                        return '\n'.join((
                            'After checking local HEAD against remote HEAD',
                            '# The local repository does not match the remote:',
                            '#', '#  HEAD   is %s' % head_name,
                            '#  Local  is %s' % local_head_ref,
                            '#  Remote is %s' % ref, '#',
                            '# You probably need to pull with "muddle pull".'))

        # Should we check to see if we found HEAD?

        return None
示例#7
0
 def get_file_content(self, url, verbose=True):
     """
     Retrieve a file's content via Subversion.
     """
     text = utils.get_cmd_data('svn cat %s'%url, show_command=verbose)
     return text
示例#8
0
 def _just_revno(self):
     """
     This returns the revision number for the working tree
     """
     revision = utils.get_cmd_data('svnversion')
     return revision.strip()
示例#9
0
文件: git.py 项目: Flameeyes/muddle
    def status(self, repo, options, quick=False):
        """
        Will be called in the actual checkout's directory.

        Return status text or None if there is no interesting status.
        """
        retcode, text = utils.run2("git status --porcelain", show_command=False)
        if retcode == 129:
            print "Warning: Your git does not support --porcelain; you should upgrade it."
            retcode, text = utils.run2("git status", show_command=False)

        detached_head = self._is_detached_HEAD()

        if detached_head:
            # That's all the user really needs to know
            note = '\n# Note that this checkout has a detached HEAD'
            if text:
                text = '%s\n#%s'%(text, note)
            else:
                text = note

        if text:
            return text

        # git status will tell us if there uncommitted changes, etc., but not if
        # we are ahead of or behind (the local idea of) the remote repository,
        # or it will, but not with --porcelain


        if detached_head:
            head_name = 'HEAD'
        else:
            # First, find out what our HEAD actually is
            retcode, text = utils.run2("git rev-parse --symbolic-full-name HEAD",
                                       show_command=False)
            head_name = text.strip()

        # Now we can look up its SHA1, locally
        retcode, head_revision = utils.run2("git rev-parse %s"%head_name,
                                            show_command=False)
        local_head_ref = head_revision.strip()

        if quick:
            branch_name = utils.get_cmd_data("git rev-parse --abbrev-ref HEAD")
            text = utils.get_cmd_data("git show-ref origin/%s"%branch_name)
            ref, what = text.split()
            if ref != local_head_ref:
                return '\n'.join(
                    ('After checking local HEAD against our local record of the remote HEAD',
                     '# The local repository does not match the remote:',
                     '#',
                     '#  HEAD   is %s'%head_name,
                     '#  Local  is %s'%local_head_ref,
                     '#  last known origin/%s is %s'%(branch_name, ref),
                     '#',
                     '# You probably need to push or pull.',
                     '# Use "muddle status" without "-quick" to get a better idea'))
            else:
                return None

        # So look up the remote equivalents...
        retcode, text = utils.run2("git ls-remote", show_command=False)
        lines = text.split('\n')
        if retcode:
            # Oh dear - something nasty happened
            # We know we get this if, for instance, the remote repository does
            # not actually exist
            newlines = []
            newlines.append('Whilst trying to check local HEAD against remote HEAD')
            for line in lines:
                newlines.append('# %s'%line)
            return '\n'.join(newlines)
        else:
            for line in lines[1:]:          # The first line is the remote repository
                if not line:
                    continue
                ref, what = line.split('\t')
                if what == head_name:
                    if ref != local_head_ref:
                        return '\n'.join(('After checking local HEAD against remote HEAD',
                                          '# The local repository does not match the remote:',
                                          '#',
                                          '#  HEAD   is %s'%head_name,
                                          '#  Local  is %s'%local_head_ref,
                                          '#  Remote is %s'%ref,
                                          '#',
                                          '# You probably need to pull with "muddle pull".'))

        # Should we check to see if we found HEAD?

        return None
示例#10
0
def get_stdout(cmd, verbose=True):
    """Run a command in the shell, and grab its (standard) output.
    """
    return get_cmd_data(cmd, show_command=verbose)