blob: acbf18bc04e18bc670b6e793884ca2aee8991d18 [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
20from command import Command
21
22class Forall(Command):
23 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-----------
33pwd is the project's working directory.
34
35REPO_PROJECT is set to the unique name of the project.
36
Jeff Baileybe0e8ac2009-01-21 19:05:15 -050037REPO_PATH is the path relative the the root of the client.
38
39REPO_REMOTE is the name of the remote system from the manifest.
40
41REPO_LREV is the name of the revision from the manifest, translated
42to a local tracking branch. If you need to pass the manifest
43revision to a locally executed git command, use REPO_LREV.
44
45REPO_RREV is the name of the revision from the manifest, exactly
46as written in the manifest.
47
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070048shell positional arguments ($1, $2, .., $#) are set to any arguments
49following <command>.
50
51stdin, stdout, stderr are inherited from the terminal and are
52not redirected.
53"""
54
55 def _Options(self, p):
56 def cmd(option, opt_str, value, parser):
57 setattr(parser.values, option.dest, list(parser.rargs))
58 while parser.rargs:
59 del parser.rargs[0]
60 p.add_option('-c', '--command',
61 help='Command (and arguments) to execute',
62 dest='command',
63 action='callback',
64 callback=cmd)
65
66 def Execute(self, opt, args):
67 if not opt.command:
68 self.Usage()
69
70 cmd = [opt.command[0]]
71
72 shell = True
73 if re.compile(r'^[a-z0-9A-Z_/\.-]+$').match(cmd[0]):
74 shell = False
75
76 if shell:
77 cmd.append(cmd[0])
78 cmd.extend(opt.command[1:])
79
80 rc = 0
81 for project in self.GetProjects(args):
82 env = dict(os.environ.iteritems())
83 env['REPO_PROJECT'] = project.name
Jeff Baileybe0e8ac2009-01-21 19:05:15 -050084 env['REPO_PATH'] = project.relpath
85 env['REPO_REMOTE'] = project.remote.name
86 env['REPO_LREV'] = project\
87 .GetRemote(project.remote.name)\
88 .ToLocal(project.revision)
89 env['REPO_RREV'] = project.revision
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070090
91 p = subprocess.Popen(cmd,
92 cwd = project.worktree,
93 shell = shell,
94 env = env)
95 r = p.wait()
96 if r != 0 and r != rc:
97 rc = r
98 if rc != 0:
99 sys.exit(rc)