예제 #1
0
    def report(self, bare=False, inspect_remotes=False):
        """
        :param bool bare: Bare report only
        :param bool inspect_remotes: If True, report on which remote branches are cleanable
        :return GitRunReport: General report on current checkout state
        """
        if not self.is_git_checkout:
            if self.remote_info:
                return GitRunReport(problem="not cloned yet")
            return GitRunReport.not_git()

        result = GitRunReport()

        if not self.config.remotes:
            result.add(problem="no remotes")

        if bare:
            return result

        if self.age is not None and self.age > FRESHNESS_THRESHOLD:
            result.add(note="last fetch %s ago" %
                       represented_duration(self.age))

        orphan_branches = self.orphan_branches
        if self.branches.current in orphan_branches:
            # Current is no more on its remote (should possibly checkout another branch and cleanup, or push)
            orphan_branches = orphan_branches[:]
            orphan_branches.remove(self.branches.current)
            result.add(note="current branch '%s' is orphaned" %
                       self.branches.current)

        if len(orphan_branches) == 1:
            result.add(note="local branch '%s' can be pruned" %
                       orphan_branches[0])
        elif orphan_branches:
            result.add(note="%s can be pruned" %
                       colored.plural(orphan_branches, "local branch"))

        result.add(self.branches.report)

        if inspect_remotes and self.remote_cleanable_branches:
            if len(self.remote_cleanable_branches) == 1:
                cleanable = "'%s'" % next(iter(self.remote_cleanable_branches))
            else:
                cleanable = colored.plural(self.remote_cleanable_branches,
                                           "remote branch")
            result.add(note="%s can be cleaned" % cleanable)

        return result
예제 #2
0
 def freshness(self):
     """Short freshness overview"""
     result = []
     if self.report._problem:
         result.append(colored.problem(" ".join(self.report._problem)))
     if self.modified:
         result.append(
             colored.plural(self.modified, "diff", colored.problem))
     if self.untracked:
         result.append(colored.warn("%s untracked" % len(self.untracked)))
     if self.report._note:
         result.append(colored.note(" ".join(self.report._note)))
     if not self.report._problem and not self.report._note and self._parent.age is not None:
         message = "up to date"
         if self._parent.age > FRESHNESS_THRESHOLD:
             message += "*"
         result.append(colored.pop(message))
     return ", ".join(result)
예제 #3
0
def handle_ignore(action, what, target):
    """
    Show/add/remove/clear ignores on current project
    :param str action: One of VALID_IGNORE_ACTIONS
    :param str what: What to add or remove
    :param ProjectDir target: Target dir
    """
    if not isinstance(target, ProjectDir):
        abort(
            "--ignore applies to collections of checkouts, not particular checkouts"
        )
    if not target.predominant:
        abort(
            "--ignore applies to internal bitbucket stash repos, this folder doesn't seem related to one"
        )
    if target.predominant.type != 'stash':
        abort("--ignore applies to bitbucket stash only, not '%s'" %
              target.predominant.type)

    if not action:
        action = 'show'

    action = action.lower()
    if action not in VALID_IGNORE_ACTIONS:
        abort(
            "--ignore unknown action '%s', try for example: '--ignore show', or '--ignore add:hackday.*'"
        )
    if action in ('show', 'clear') and what:
        abort("--ignore %s does not take arguments" % action)

    if action == 'clear':
        target.ignores.clear()

    elif action == 'add':
        added, invalid = target.ignores.add(what)
        if added:
            print("Added %s" % colored.plural(added, "pattern"))
        if invalid:
            print("%s: [%s], %s" % (
                colored.note("Skipped"),
                '], ['.join(colored.problem(s) for s in invalid),
                colored.note("invalid regexes"),
            ))

    elif action == 'remove':
        removed, invalid = target.ignores.remove(what)
        if removed:
            print("Removed %s" % colored.plural(removed, "pattern"))
        if invalid:
            print("%s: [%s], %s" % (
                colored.note("Skipped"),
                '], ['.join(colored.problem(s) for s in invalid),
                colored.note("not in ignore list"),
            ))

    values = target.ignores.values
    if not values:
        print(colored.note("No ignores defined"))
    else:
        print("%s:\n  %s" % (colored.plural(
            values, "ignore", colored.NOTE), "\n  ".join(values)))
예제 #4
0
def test_plural():
    assert colored.plural(None, 'commit') == 'None commits'
    assert colored.plural([], 'commit') == '0 commits'
    assert colored.plural('', 'commit') == '0 commits'
    assert colored.plural(1, 'commit') == '1 commit'
    assert colored.plural('2', 'commit') == '2 commits'

    assert colored.plural(15, 'great dane') == '15 great danes'

    assert colored.plural(7, 'branch') == '7 branches'

    assert colored.plural(1, 'commit behind',
                          on_first=True) == '1 commit behind'
    assert colored.plural('a b c'.split(), 'commit behind',
                          on_first=True) == '3 commits behind'

    colored.activate_colors(True)
    assert colored.plural(1, 'commit', colored.PROBLEM) == '1 commit'
    assert colored.plural(1, 'commit', colored.problem) == '1 commit'
    colored.activate_colors(False)
예제 #5
0
def handle_single_clean(target, what):
    """
    :param GitCheckout target: Single checkout to clean
    :param str what: Operation
    """
    report = target.git.fetch()
    if report.has_problems:
        if what != "reset":
            what = "clean"
        print(
            target.header(
                GitRunReport(report).add(problem="<can't %s" % what)))
        abort()

    if what == "reset":
        return clean_reset(target)

    if what == "show":
        return clean_show(target)

    total_cleaned = 0
    print(target.header())

    if what in "remote all":
        if not target.git.remote_cleanable_branches:
            print("  No remote branches can be cleaned")
        else:
            total = len(target.git.remote_cleanable_branches)
            cleaned = 0
            for branch in target.git.remote_cleanable_branches:
                remote, _, name = branch.partition("/")
                if not remote and name:
                    raise Exception("Unknown branch spec '%s'" % branch)
                if run_git(target, False, "branch", "--delete", "--remotes",
                           branch):
                    cleaned += run_git(target, False, "push", "--delete",
                                       remote, name)

            total_cleaned += cleaned
            if cleaned == total:
                print("%s cleaned" % colored.plural(cleaned, "remote branch"))
            else:
                print("%s/%s remote branches cleaned" % (cleaned, total))

            target.git.reset_cached_properties()
            if what == "all":
                # Fetch to update remote branches (and correctly detect new dangling local)
                target.git.fetch()

    if what in "local all":
        if not target.git.local_cleanable_branches:
            print("  No local branches can be cleaned")
        else:
            total = len(target.git.local_cleanable_branches)
            cleaned = 0
            for branch in target.git.local_cleanable_branches:
                if branch == target.git.branches.current:
                    fallback = target.git.fallback_branch()
                    if not fallback:
                        print(
                            "Skipping branch '%s', can't determine fallback branch"
                            % target.git.branches.current)
                        continue
                    run_git(target, True, "checkout", fallback)
                    run_git(target, True, "pull")
                cleaned += run_git(target, False, "branch", "--delete", branch)

            total_cleaned += cleaned
            if cleaned == total:
                print(
                    colored.highlight("%s cleaned" %
                                      colored.plural(cleaned, "local branch")))
            else:
                print(
                    colored.warn("%s/%s local branches cleaned" %
                                 (cleaned, total)))

            target.git.reset_cached_properties()

    if total_cleaned:
        print(target.header())