blob: c3cad5ea57cad3edd37059aa3f1966f8ac8dc2fa [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001#
2# Copyright (C) 2008 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import os
17import optparse
18import sys
19
20from error import NoSuchProjectError
21
22class Command(object):
23 """Base class for any command line action in repo.
24 """
25
26 common = False
27 manifest = None
28 _optparse = None
29
30 @property
31 def OptionParser(self):
32 if self._optparse is None:
33 try:
34 me = 'repo %s' % self.NAME
35 usage = self.helpUsage.strip().replace('%prog', me)
36 except AttributeError:
37 usage = 'repo %s' % self.NAME
38 self._optparse = optparse.OptionParser(usage = usage)
39 self._Options(self._optparse)
40 return self._optparse
41
42 def _Options(self, p):
43 """Initialize the option parser.
44 """
45
46 def Usage(self):
47 """Display usage and terminate.
48 """
49 self.OptionParser.print_usage()
50 sys.exit(1)
51
52 def Execute(self, opt, args):
53 """Perform the action, after option parsing is complete.
54 """
55 raise NotImplementedError
56
57 def GetProjects(self, args, missing_ok=False):
58 """A list of projects that match the arguments.
59 """
60 all = self.manifest.projects
61 result = []
62
63 if not args:
64 for project in all.values():
65 if missing_ok or project.Exists:
66 result.append(project)
67 else:
68 by_path = None
69
70 for arg in args:
71 project = all.get(arg)
72
73 if not project:
74 path = os.path.abspath(arg)
75
76 if not by_path:
77 by_path = dict()
78 for p in all.values():
79 by_path[p.worktree] = p
80
81 if os.path.exists(path):
82 while path \
83 and path != '/' \
84 and path != self.manifest.topdir:
85 try:
86 project = by_path[path]
87 break
88 except KeyError:
89 path = os.path.dirname(path)
90 else:
91 try:
92 project = by_path[path]
93 except KeyError:
94 pass
95
96 if not project:
97 raise NoSuchProjectError(arg)
98 if not missing_ok and not project.Exists:
99 raise NoSuchProjectError(arg)
100
101 result.append(project)
102
103 def _getpath(x):
104 return x.relpath
105 result.sort(key=_getpath)
106 return result
107
108class InteractiveCommand(Command):
109 """Command which requires user interaction on the tty and
110 must not run within a pager, even if the user asks to.
111 """
112
113class PagedCommand(Command):
114 """Command which defaults to output in a pager, as its
115 display tends to be larger than one screen full.
116 """
Shawn O. Pearcec95583b2009-03-03 17:47:06 -0800117
118class MirrorSafeCommand(object):
119 """Command permits itself to run within a mirror,
120 and does not require a working directory.
121 """