# Copyright (C) 2012 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import optparse from command import PagedCommand from color import Coloring from git_refs import R_M, R_HEADS class _Coloring(Coloring): def __init__(self, config): Coloring.__init__(self, config, "status") class Info(PagedCommand): COMMON = True helpSummary = "Get info on the manifest branch, current branch or unmerged branches" helpUsage = "%prog [-dl] [-o [-c]] [...]" def _Options(self, p): p.add_option('-d', '--diff', dest='all', action='store_true', help="show full info and commit diff including remote branches") p.add_option('-o', '--overview', dest='overview', action='store_true', help='show overview of all local commits') p.add_option('-c', '--current-branch', dest="current_branch", action="store_true", help="consider only checked out branches") p.add_option('--no-current-branch', dest='current_branch', action='store_false', help='consider all local branches') # Turn this into a warning & remove this someday. p.add_option('-b', dest='current_branch', action='store_true', help=optparse.SUPPRESS_HELP) p.add_option('-l', '--local-only', dest="local", action="store_true", help="disable all remote operations") def Execute(self, opt, args): self.out = _Coloring(self.client.globalConfig) self.heading = self.out.printer('heading', attr='bold') self.headtext = self.out.nofmt_printer('headtext', fg='yellow') self.redtext = self.out.printer('redtext', fg='red') self.sha = self.out.printer("sha", fg='yellow') self.text = self.out.nofmt_printer('text') self.dimtext = self.out.printer('dimtext', attr='dim') self.opt = opt if not opt.this_manifest_only: self.manifest = self.manifest.outer_client manifestConfig = self.manifest.manifestProject.config mergeBranch = manifestConfig.GetBranch("default").merge manifestGroups = self.manifest.GetGroupsStr() self.heading("Manifest branch: ") if self.manifest.default.revisionExpr: self.headtext(self.manifest.default.revisionExpr) self.out.nl() self.heading("Manifest merge branch: ") self.headtext(mergeBranch) self.out.nl() self.heading("Manifest groups: ") self.headtext(manifestGroups) self.out.nl() self.printSeparator() if not opt.overview: self._printDiffInfo(opt, args) else: self._printCommitOverview(opt, args) def printSeparator(self): self.text("----------------------------") self.out.nl() def _printDiffInfo(self, opt, args): # We let exceptions bubble up to main as they'll be well structured. projs = self.GetProjects(args, all_manifests=not opt.this_manifest_only) for p in projs: self.heading("Project: ") self.headtext(p.name) self.out.nl() self.heading("Mount path: ") self.headtext(p.worktree) self.out.nl() self.heading("Current revision: ") self.headtext(p.GetRevisionId()) self.out.nl() currentBranch = p.CurrentBranch if currentBranch: self.heading('Current branch: ') self.headtext(currentBranch) self.out.nl() self.heading("Manifest revision: ") self.headtext(p.revisionExpr) self.out.nl() localBranches = list(p.GetBranches().keys()) self.heading("Local Branches: ") self.redtext(str(len(localBranches))) if localBranches: self.text(" [") self.text(", ".join(localBranches)) self.text("]") self.out.nl() if self.opt.all: self.findRemoteLocalDiff(p) self.printSeparator() def findRemoteLocalDiff(self, project): # Fetch all the latest commits. if not self.opt.local: project.Sync_NetworkHalf(quiet=True, current_branch_only=True) branch = self.manifest.manifestProject.config.GetBranch('default').merge if branch.startswith(R_HEADS): branch = branch[len(R_HEADS):] logTarget = R_M + branch bareTmp = project.bare_git._bare project.bare_git._bare = False localCommits = project.bare_git.rev_list( '--abbrev=8', '--abbrev-commit', '--pretty=oneline', logTarget + "..", '--') originCommits = project.bare_git.rev_list( '--abbrev=8', '--abbrev-commit', '--pretty=oneline', ".." + logTarget, '--') project.bare_git._bare = bareTmp self.heading("Local Commits: ") self.redtext(str(len(localCommits))) self.dimtext(" (on current branch)") self.out.nl() for c in localCommits: split = c.split() self.sha(split[0] + " ") self.text(" ".join(split[1:])) self.out.nl() self.printSeparator() self.heading("Remote Commits: ") self.redtext(str(len(originCommits))) self.out.nl() for c in originCommits: split = c.split() self.sha(split[0] + " ") self.text(" ".join(split[1:])) self.out.nl() def _printCommitOverview(self, opt, args): all_branches = [] for project in self.GetProjects(args, all_manifests=not opt.this_manifest_only): br = [project.GetUploadableBranch(x) for x in project.GetBranches()] br = [x for x in br if x] if self.opt.current_branch: br = [x for x in br if x.name == project.CurrentBranch] all_branches.extend(br) if not all_branches: return self.out.nl() self.heading('Projects Overview') project = None for branch in all_branches: if project != branch.project: project = branch.project self.out.nl() self.headtext(project.RelPath(local=opt.this_manifest_only)) self.out.nl() commits = branch.commits date = branch.date self.text('%s %-33s (%2d commit%s, %s)' % ( branch.name == project.CurrentBranch and '*' or ' ', branch.name, len(commits), len(commits) != 1 and 's' or '', date)) self.out.nl() for commit in commits: split = commit.split() self.text('{0:38}{1} '.format('', '-')) self.sha(split[0] + " ") self.text(" ".join(split[1:])) self.out.nl()