blob: 2ee0a43aea3a6d9ee65ce148d0c1c7958078e9c7 [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
Colin Cross5acde752012-03-28 20:15:45 -070018import re
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070019import sys
20
21from error import NoSuchProjectError
Colin Cross5acde752012-03-28 20:15:45 -070022from error import InvalidProjectGroupsError
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070023
24class Command(object):
25 """Base class for any command line action in repo.
26 """
27
28 common = False
29 manifest = None
30 _optparse = None
31
Shawn O. Pearcedb45da12009-04-18 13:49:13 -070032 def WantPager(self, opt):
33 return False
34
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070035 @property
36 def OptionParser(self):
37 if self._optparse is None:
38 try:
39 me = 'repo %s' % self.NAME
40 usage = self.helpUsage.strip().replace('%prog', me)
41 except AttributeError:
42 usage = 'repo %s' % self.NAME
43 self._optparse = optparse.OptionParser(usage = usage)
44 self._Options(self._optparse)
45 return self._optparse
46
47 def _Options(self, p):
48 """Initialize the option parser.
49 """
50
51 def Usage(self):
52 """Display usage and terminate.
53 """
54 self.OptionParser.print_usage()
55 sys.exit(1)
56
57 def Execute(self, opt, args):
58 """Perform the action, after option parsing is complete.
59 """
60 raise NotImplementedError
Conley Owens971de8e2012-04-16 10:36:08 -070061
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070062 def GetProjects(self, args, missing_ok=False):
63 """A list of projects that match the arguments.
64 """
65 all = self.manifest.projects
66 result = []
67
Colin Cross5acde752012-03-28 20:15:45 -070068 mp = self.manifest.manifestProject
69
70 groups = mp.config.GetString('manifest.groups')
Conley Owens971de8e2012-04-16 10:36:08 -070071 if groups is None:
72 groups = 'default'
73 groups = [x for x in re.split('[,\s]+', groups) if x]
Colin Cross5acde752012-03-28 20:15:45 -070074
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070075 if not args:
76 for project in all.values():
Colin Cross5acde752012-03-28 20:15:45 -070077 if ((missing_ok or project.Exists) and
78 project.MatchesGroups(groups)):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070079 result.append(project)
80 else:
81 by_path = None
82
83 for arg in args:
84 project = all.get(arg)
85
86 if not project:
Anthony Newnamdf14a702011-01-09 17:31:57 -080087 path = os.path.abspath(arg).replace('\\', '/')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070088
89 if not by_path:
90 by_path = dict()
91 for p in all.values():
92 by_path[p.worktree] = p
93
94 if os.path.exists(path):
Anthony Newnamdf14a702011-01-09 17:31:57 -080095 oldpath = None
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070096 while path \
Anthony Newnamdf14a702011-01-09 17:31:57 -080097 and path != oldpath \
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070098 and path != self.manifest.topdir:
99 try:
100 project = by_path[path]
101 break
102 except KeyError:
Anthony Newnamdf14a702011-01-09 17:31:57 -0800103 oldpath = path
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700104 path = os.path.dirname(path)
105 else:
106 try:
107 project = by_path[path]
108 except KeyError:
109 pass
110
111 if not project:
112 raise NoSuchProjectError(arg)
113 if not missing_ok and not project.Exists:
114 raise NoSuchProjectError(arg)
Colin Cross5acde752012-03-28 20:15:45 -0700115 if not project.MatchesGroups(groups):
116 raise InvalidProjectGroupsError(arg)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700117
118 result.append(project)
119
120 def _getpath(x):
121 return x.relpath
122 result.sort(key=_getpath)
123 return result
124
125class InteractiveCommand(Command):
126 """Command which requires user interaction on the tty and
127 must not run within a pager, even if the user asks to.
128 """
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700129 def WantPager(self, opt):
130 return False
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700131
132class PagedCommand(Command):
133 """Command which defaults to output in a pager, as its
134 display tends to be larger than one screen full.
135 """
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700136 def WantPager(self, opt):
137 return True
Shawn O. Pearcec95583b2009-03-03 17:47:06 -0800138
139class MirrorSafeCommand(object):
140 """Command permits itself to run within a mirror,
141 and does not require a working directory.
142 """