blob: e17f0ab92f507280c3d970ddbf1fbd54287b93b9 [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
Conley Owensd21720d2012-04-16 11:02:21 -070018import platform
Colin Cross5acde752012-03-28 20:15:45 -070019import re
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070020import sys
21
22from error import NoSuchProjectError
Colin Cross5acde752012-03-28 20:15:45 -070023from error import InvalidProjectGroupsError
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070024
25class Command(object):
26 """Base class for any command line action in repo.
27 """
28
29 common = False
30 manifest = None
31 _optparse = None
32
Shawn O. Pearcedb45da12009-04-18 13:49:13 -070033 def WantPager(self, opt):
34 return False
35
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070036 @property
37 def OptionParser(self):
38 if self._optparse is None:
39 try:
40 me = 'repo %s' % self.NAME
41 usage = self.helpUsage.strip().replace('%prog', me)
42 except AttributeError:
43 usage = 'repo %s' % self.NAME
44 self._optparse = optparse.OptionParser(usage = usage)
45 self._Options(self._optparse)
46 return self._optparse
47
48 def _Options(self, p):
49 """Initialize the option parser.
50 """
51
52 def Usage(self):
53 """Display usage and terminate.
54 """
55 self.OptionParser.print_usage()
56 sys.exit(1)
57
58 def Execute(self, opt, args):
59 """Perform the action, after option parsing is complete.
60 """
61 raise NotImplementedError
Conley Owens971de8e2012-04-16 10:36:08 -070062
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070063 def GetProjects(self, args, missing_ok=False):
64 """A list of projects that match the arguments.
65 """
David Pursehouse8a68ff92012-09-24 12:15:13 +090066 all_projects = self.manifest.projects
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070067 result = []
68
Colin Cross5acde752012-03-28 20:15:45 -070069 mp = self.manifest.manifestProject
70
71 groups = mp.config.GetString('manifest.groups')
Colin Crossc39864f2012-04-23 13:41:58 -070072 if not groups:
Conley Owensbb1b5f52012-08-13 13:11:18 -070073 groups = 'all,-notdefault,platform-' + platform.system().lower()
Conley Owens971de8e2012-04-16 10:36:08 -070074 groups = [x for x in re.split('[,\s]+', groups) if x]
Colin Cross5acde752012-03-28 20:15:45 -070075
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070076 if not args:
David Pursehouse8a68ff92012-09-24 12:15:13 +090077 for project in all_projects.values():
Colin Cross5acde752012-03-28 20:15:45 -070078 if ((missing_ok or project.Exists) and
79 project.MatchesGroups(groups)):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070080 result.append(project)
81 else:
82 by_path = None
83
84 for arg in args:
David Pursehouse8a68ff92012-09-24 12:15:13 +090085 project = all_projects.get(arg)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070086
87 if not project:
Anthony Newnamdf14a702011-01-09 17:31:57 -080088 path = os.path.abspath(arg).replace('\\', '/')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070089
90 if not by_path:
91 by_path = dict()
David Pursehouse8a68ff92012-09-24 12:15:13 +090092 for p in all_projects.values():
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070093 by_path[p.worktree] = p
94
95 if os.path.exists(path):
Anthony Newnamdf14a702011-01-09 17:31:57 -080096 oldpath = None
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070097 while path \
Anthony Newnamdf14a702011-01-09 17:31:57 -080098 and path != oldpath \
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070099 and path != self.manifest.topdir:
100 try:
101 project = by_path[path]
102 break
103 except KeyError:
Anthony Newnamdf14a702011-01-09 17:31:57 -0800104 oldpath = path
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700105 path = os.path.dirname(path)
106 else:
107 try:
108 project = by_path[path]
109 except KeyError:
110 pass
111
112 if not project:
113 raise NoSuchProjectError(arg)
114 if not missing_ok and not project.Exists:
115 raise NoSuchProjectError(arg)
Colin Cross5acde752012-03-28 20:15:45 -0700116 if not project.MatchesGroups(groups):
117 raise InvalidProjectGroupsError(arg)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700118
119 result.append(project)
120
121 def _getpath(x):
122 return x.relpath
123 result.sort(key=_getpath)
124 return result
125
126class InteractiveCommand(Command):
127 """Command which requires user interaction on the tty and
128 must not run within a pager, even if the user asks to.
129 """
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700130 def WantPager(self, opt):
131 return False
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700132
133class PagedCommand(Command):
134 """Command which defaults to output in a pager, as its
135 display tends to be larger than one screen full.
136 """
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700137 def WantPager(self, opt):
138 return True
Shawn O. Pearcec95583b2009-03-03 17:47:06 -0800139
140class MirrorSafeCommand(object):
141 """Command permits itself to run within a mirror,
142 and does not require a working directory.
143 """