forall.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #
  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. import re
  16. import os
  17. import sys
  18. import subprocess
  19. from command import Command
  20. class Forall(Command):
  21. common = False
  22. helpSummary = "Run a shell command in each project"
  23. helpUsage = """
  24. %prog [<project>...] -c <command> [<arg>...]
  25. """
  26. helpDescription = """
  27. Executes the same shell command in each project.
  28. Environment
  29. -----------
  30. pwd is the project's working directory.
  31. REPO_PROJECT is set to the unique name of the project.
  32. shell positional arguments ($1, $2, .., $#) are set to any arguments
  33. following <command>.
  34. stdin, stdout, stderr are inherited from the terminal and are
  35. not redirected.
  36. """
  37. def _Options(self, p):
  38. def cmd(option, opt_str, value, parser):
  39. setattr(parser.values, option.dest, list(parser.rargs))
  40. while parser.rargs:
  41. del parser.rargs[0]
  42. p.add_option('-c', '--command',
  43. help='Command (and arguments) to execute',
  44. dest='command',
  45. action='callback',
  46. callback=cmd)
  47. def Execute(self, opt, args):
  48. if not opt.command:
  49. self.Usage()
  50. cmd = [opt.command[0]]
  51. shell = True
  52. if re.compile(r'^[a-z0-9A-Z_/\.-]+$').match(cmd[0]):
  53. shell = False
  54. if shell:
  55. cmd.append(cmd[0])
  56. cmd.extend(opt.command[1:])
  57. rc = 0
  58. for project in self.GetProjects(args):
  59. env = dict(os.environ.iteritems())
  60. env['REPO_PROJECT'] = project.name
  61. p = subprocess.Popen(cmd,
  62. cwd = project.worktree,
  63. shell = shell,
  64. env = env)
  65. r = p.wait()
  66. if r != 0 and r != rc:
  67. rc = r
  68. if rc != 0:
  69. sys.exit(rc)