| # |
| # Copyright (C) 2008 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 os |
| import optparse |
| import sys |
| |
| import manifest_loader |
| |
| from error import NoSuchProjectError |
| |
| class Command(object): |
| """Base class for any command line action in repo. |
| """ |
| |
| common = False |
| _optparse = None |
| |
| def WantPager(self, opt): |
| return False |
| |
| @property |
| def OptionParser(self): |
| if self._optparse is None: |
| try: |
| me = 'repo %s' % self.NAME |
| usage = self.helpUsage.strip().replace('%prog', me) |
| except AttributeError: |
| usage = 'repo %s' % self.NAME |
| self._optparse = optparse.OptionParser(usage = usage) |
| self._Options(self._optparse) |
| return self._optparse |
| |
| def _Options(self, p): |
| """Initialize the option parser. |
| """ |
| |
| def Usage(self): |
| """Display usage and terminate. |
| """ |
| self.OptionParser.print_usage() |
| sys.exit(1) |
| |
| def Execute(self, opt, args): |
| """Perform the action, after option parsing is complete. |
| """ |
| raise NotImplementedError |
| |
| @property |
| def manifest(self): |
| return self.GetManifest() |
| |
| def GetManifest(self, reparse=False, type=None): |
| return manifest_loader.GetManifest(self.repodir, |
| reparse=reparse, |
| type=type) |
| |
| def GetProjects(self, args, missing_ok=False): |
| """A list of projects that match the arguments. |
| """ |
| all = self.manifest.projects |
| |
| mp = self.manifest.manifestProject |
| if mp.relpath == '.': |
| all = dict(all) |
| all[mp.name] = mp |
| |
| result = [] |
| |
| if not args: |
| for project in all.values(): |
| if missing_ok or project.Exists: |
| result.append(project) |
| else: |
| by_path = None |
| |
| for arg in args: |
| project = all.get(arg) |
| |
| if not project: |
| path = os.path.abspath(arg) |
| |
| if not by_path: |
| by_path = dict() |
| for p in all.values(): |
| by_path[p.worktree] = p |
| |
| try: |
| project = by_path[path] |
| except KeyError: |
| while path \ |
| and path != '/' \ |
| and path != self.manifest.topdir: |
| try: |
| project = by_path[path] |
| break |
| except KeyError: |
| path = os.path.dirname(path) |
| |
| if not project: |
| raise NoSuchProjectError(arg) |
| if not missing_ok and not project.Exists: |
| raise NoSuchProjectError(arg) |
| |
| result.append(project) |
| |
| def _getpath(x): |
| return x.relpath |
| result.sort(key=_getpath) |
| return result |
| |
| class InteractiveCommand(Command): |
| """Command which requires user interaction on the tty and |
| must not run within a pager, even if the user asks to. |
| """ |
| def WantPager(self, opt): |
| return False |
| |
| class PagedCommand(Command): |
| """Command which defaults to output in a pager, as its |
| display tends to be larger than one screen full. |
| """ |
| def WantPager(self, opt): |
| return True |
| |
| class MirrorSafeCommand(object): |
| """Command permits itself to run within a mirror, |
| and does not require a working directory. |
| """ |