blob: 8a5a41ad4d4199a716a93f239f06ee2ebdd30bb4 [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 re
17import os
18import sys
19import subprocess
Shawn O. Pearce44469462009-03-03 17:51:01 -080020from command import Command, MirrorSafeCommand
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070021
Shawn O. Pearce44469462009-03-03 17:51:01 -080022class Forall(Command, MirrorSafeCommand):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070023 common = False
24 helpSummary = "Run a shell command in each project"
25 helpUsage = """
26%prog [<project>...] -c <command> [<arg>...]
27"""
28 helpDescription = """
29Executes the same shell command in each project.
30
31Environment
32-----------
Shawn O. Pearceff84fea2009-04-13 12:11:59 -070033
Shawn O. Pearce44469462009-03-03 17:51:01 -080034pwd is the project's working directory. If the current client is
35a mirror client, then pwd is the Git repository.
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070036
37REPO_PROJECT is set to the unique name of the project.
38
Jeff Baileybe0e8ac2009-01-21 19:05:15 -050039REPO_PATH is the path relative the the root of the client.
40
41REPO_REMOTE is the name of the remote system from the manifest.
42
43REPO_LREV is the name of the revision from the manifest, translated
44to a local tracking branch. If you need to pass the manifest
45revision to a locally executed git command, use REPO_LREV.
46
47REPO_RREV is the name of the revision from the manifest, exactly
48as written in the manifest.
49
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070050shell positional arguments ($1, $2, .., $#) are set to any arguments
51following <command>.
52
53stdin, stdout, stderr are inherited from the terminal and are
54not redirected.
55"""
56
57 def _Options(self, p):
58 def cmd(option, opt_str, value, parser):
59 setattr(parser.values, option.dest, list(parser.rargs))
60 while parser.rargs:
61 del parser.rargs[0]
62 p.add_option('-c', '--command',
63 help='Command (and arguments) to execute',
64 dest='command',
65 action='callback',
66 callback=cmd)
67
68 def Execute(self, opt, args):
69 if not opt.command:
70 self.Usage()
71
72 cmd = [opt.command[0]]
73
74 shell = True
75 if re.compile(r'^[a-z0-9A-Z_/\.-]+$').match(cmd[0]):
76 shell = False
77
78 if shell:
79 cmd.append(cmd[0])
80 cmd.extend(opt.command[1:])
81
Shawn O. Pearce44469462009-03-03 17:51:01 -080082 mirror = self.manifest.IsMirror
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070083 rc = 0
84 for project in self.GetProjects(args):
85 env = dict(os.environ.iteritems())
Shawn O. Pearce1775dbe2009-03-17 08:03:04 -070086 def setenv(name, val):
87 if val is None:
88 val = ''
89 env[name] = val
90
91 setenv('REPO_PROJECT', project.name)
92 setenv('REPO_PATH', project.relpath)
93 setenv('REPO_REMOTE', project.remote.name)
94 setenv('REPO_LREV', project\
Jeff Baileybe0e8ac2009-01-21 19:05:15 -050095 .GetRemote(project.remote.name)\
Shawn O. Pearce1775dbe2009-03-17 08:03:04 -070096 .ToLocal(project.revision))
97 setenv('REPO_RREV', project.revision)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070098
Shawn O. Pearce44469462009-03-03 17:51:01 -080099 if mirror:
Shawn O. Pearce1775dbe2009-03-17 08:03:04 -0700100 setenv('GIT_DIR', project.gitdir)
Shawn O. Pearce44469462009-03-03 17:51:01 -0800101 cwd = project.gitdir
102 else:
103 cwd = project.worktree
104
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700105 p = subprocess.Popen(cmd,
Shawn O. Pearce44469462009-03-03 17:51:01 -0800106 cwd = cwd,
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700107 shell = shell,
108 env = env)
109 r = p.wait()
110 if r != 0 and r != rc:
111 rc = r
112 if rc != 0:
113 sys.exit(rc)