| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """A tool to archive croc code coverage to the Chromium buildbot webserver. | 6 """A tool to archive croc code coverage to the Chromium buildbot webserver. |
| 7 | 7 |
| 8 When this is run, the current directory (cwd) should be the outer build | 8 When this is run, the current directory (cwd) should be the outer build |
| 9 directory (e.g., chrome-release/build/). | 9 directory (e.g., chrome-release/build/). |
| 10 | 10 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 | 23 |
| 24 from common import chromium_utils | 24 from common import chromium_utils |
| 25 | 25 |
| 26 from slave import slave_utils | 26 from slave import slave_utils |
| 27 import config | 27 import config |
| 28 | 28 |
| 29 | 29 |
| 30 class ArchiveCoverage(object): | 30 class ArchiveCoverage(object): |
| 31 """Class to copy coverage HTML to the buildbot webserver.""" | 31 """Class to copy coverage HTML to the buildbot webserver.""" |
| 32 | 32 |
| 33 def __init__(self, options): | 33 def __init__(self, options, coverage_folder_name): |
| 34 """Constructor. | 34 """Constructor. |
| 35 | 35 |
| 36 Args: | 36 Args: |
| 37 options: Command-line option object from optparse. | 37 options: Command-line option object from optparse. |
| 38 """ | 38 """ |
| 39 # Do platform-specific config | 39 # Do platform-specific config |
| 40 if sys.platform in ('win32', 'cygwin'): | 40 if sys.platform in ('win32', 'cygwin'): |
| 41 self.is_posix = False | 41 self.is_posix = False |
| 42 self.from_dir = os.path.join(options.build_dir, options.target, | 42 self.from_dir = os.path.join(options.build_dir, options.target, |
| 43 'coverage_croc_html') | 43 'coverage_croc_html') |
| 44 | 44 |
| 45 elif sys.platform.startswith('darwin'): | 45 elif sys.platform.startswith('darwin'): |
| 46 self.is_posix = True | 46 self.is_posix = True |
| 47 self.from_dir = os.path.join(os.path.dirname(options.build_dir), | 47 self.from_dir = os.path.join(os.path.dirname(options.build_dir), |
| 48 'xcodebuild', options.target, | 48 'xcodebuild', options.target, |
| 49 'coverage_croc_html') | 49 'coverage_croc_html') |
| 50 | 50 |
| 51 elif sys.platform.startswith('linux'): | 51 elif sys.platform.startswith('linux'): |
| 52 self.is_posix = True | 52 self.is_posix = True |
| 53 self.from_dir = os.path.join(os.path.dirname(options.build_dir), | 53 self.from_dir = os.path.join(os.path.dirname(options.build_dir), |
| 54 'out', options.target, # make, not scons | 54 'out', options.target, # make, not scons |
| 55 coverage_folder_name, |
| 55 'coverage_croc_html') | 56 'coverage_croc_html') |
| 56 | 57 |
| 57 else: | 58 else: |
| 58 print 'Unknown/unsupported platform.' | 59 print 'Unknown/unsupported platform.' |
| 59 sys.exit(1) | 60 sys.exit(1) |
| 60 | 61 |
| 61 self.from_dir = os.path.normpath(self.from_dir) | 62 self.from_dir = os.path.normpath(self.from_dir) |
| 62 print 'copy from: %s' % self.from_dir | 63 print 'copy from: %s' % self.from_dir |
| 63 | 64 |
| 65 if not os.path.exists(self.from_dir): |
| 66 print '%s directory does not exist' % self.from_dir |
| 67 sys.exit(1) |
| 68 |
| 64 # Extract the build name of this slave (e.g., 'chrome-release') from its | 69 # Extract the build name of this slave (e.g., 'chrome-release') from its |
| 65 # configuration file. | 70 # configuration file. |
| 66 chrome_dir = os.path.abspath(options.build_dir) | 71 chrome_dir = os.path.abspath(options.build_dir) |
| 67 print 'chrome_dir: %s' % chrome_dir | 72 print 'chrome_dir: %s' % chrome_dir |
| 68 build_name = slave_utils.SlaveBuildName(chrome_dir) | 73 build_name = slave_utils.SlaveBuildName(chrome_dir) |
| 69 print 'build name: %s' % build_name | 74 print 'build name: %s' % build_name |
| 70 | 75 |
| 71 # The 'last change:' line MUST appear for the buildbot output-parser to | 76 # The 'last change:' line MUST appear for the buildbot output-parser to |
| 72 # construct the 'view coverage' link. (See | 77 # construct the 'view coverage' link. (See |
| 73 # scripts/master/log_parser/archive_command.py) | 78 # scripts/master/log_parser/archive_command.py) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 92 else: | 97 else: |
| 93 self.perf_subdir = build_name | 98 self.perf_subdir = build_name |
| 94 if options.build_number: | 99 if options.build_number: |
| 95 self.perf_subdir = os.path.join(self.perf_subdir, options.build_number) | 100 self.perf_subdir = os.path.join(self.perf_subdir, options.build_number) |
| 96 print 'build number: %s' % options.build_number | 101 print 'build number: %s' % options.build_number |
| 97 print 'perf subdir: %s' % self.perf_subdir | 102 print 'perf subdir: %s' % self.perf_subdir |
| 98 | 103 |
| 99 # TODO(jrg) use os.path.join here? | 104 # TODO(jrg) use os.path.join here? |
| 100 self.archive_path = '%scoverage/%s/%s' % ( | 105 self.archive_path = '%scoverage/%s/%s' % ( |
| 101 archive_config.www_dir_base, self.perf_subdir, self.last_change) | 106 archive_config.www_dir_base, self.perf_subdir, self.last_change) |
| 107 # If this is for collecting coverage for unittests, then create |
| 108 # a separate path. |
| 109 if coverage_folder_name == 'unittests_coverage': |
| 110 self.archive_path = os.path.join(self.archive_path, coverage_folder_name) |
| 102 self.archive_path = os.path.normpath(self.archive_path) | 111 self.archive_path = os.path.normpath(self.archive_path) |
| 103 print 'archive path: %s' % self.archive_path | 112 print 'archive path: %s' % self.archive_path |
| 104 | 113 |
| 105 def _MakeSourceWorldReadable(self): | 114 def _MakeSourceWorldReadable(self): |
| 106 """Makes the source tree world-readable.""" | 115 """Makes the source tree world-readable.""" |
| 107 for (dirpath, dirnames, filenames) in os.walk(self.from_dir): | 116 for (dirpath, dirnames, filenames) in os.walk(self.from_dir): |
| 108 for node in dirnames + filenames: | 117 for node in dirnames + filenames: |
| 109 chromium_utils.MakeWorldReadable(os.path.join(dirpath, node)) | 118 chromium_utils.MakeWorldReadable(os.path.join(dirpath, node)) |
| 110 | 119 |
| 111 def Run(self): | 120 def Run(self): |
| 112 """Does the actual upload. | 121 """Does the actual upload. |
| 113 | 122 |
| 114 Returns: | 123 Returns: |
| 115 0 if successful, or non-zero error code if error. | 124 0 if successful, or non-zero error code if error. |
| 116 """ | 125 """ |
| 117 if self.is_posix: | 126 if os.path.exists(self.from_dir) and self.is_posix: |
| 118 self._MakeSourceWorldReadable() | 127 self._MakeSourceWorldReadable() |
| 119 | 128 |
| 120 cmd = ['ssh', self.archive_host, 'mkdir', '-p', self.archive_path] | 129 cmd = ['ssh', self.archive_host, 'mkdir', '-p', self.archive_path] |
| 121 print 'Running: ' + ' '.join(cmd) | 130 print 'Running: ' + ' '.join(cmd) |
| 122 retval = subprocess.call(cmd) | 131 retval = subprocess.call(cmd) |
| 123 if retval: | 132 if retval: |
| 124 return retval | 133 return retval |
| 125 | 134 |
| 126 cmd = ['bash', '-c', 'scp -r -p %s/* %s:%s' % | 135 cmd = ['bash', '-c', 'scp -r -p %s/* %s:%s' % |
| 127 (self.from_dir, self.archive_host, self.archive_path)] | 136 (self.from_dir, self.archive_host, self.archive_path)] |
| (...skipping 27 matching lines...) Expand all Loading... |
| 155 metavar='DIR', | 164 metavar='DIR', |
| 156 help='destination subdirectory under' | 165 help='destination subdirectory under' |
| 157 'coverage') | 166 'coverage') |
| 158 option_parser.add_option('--build-number', | 167 option_parser.add_option('--build-number', |
| 159 help='destination subdirectory under perf-subdir') | 168 help='destination subdirectory under perf-subdir') |
| 160 option_parser.add_option('--internal', action='store_true', | 169 option_parser.add_option('--internal', action='store_true', |
| 161 help='specifies if we should use Internal config') | 170 help='specifies if we should use Internal config') |
| 162 options, args = option_parser.parse_args() | 171 options, args = option_parser.parse_args() |
| 163 if args: | 172 if args: |
| 164 option_parser.error('Args not supported: %s' % args) | 173 option_parser.error('Args not supported: %s' % args) |
| 165 ac = ArchiveCoverage(options) | 174 ac = ArchiveCoverage(options, 'total_coverage') |
| 166 sys.exit(ac.Run()) | 175 ac.Run() |
| 167 | 176 |
| 177 auc = ArchiveCoverage(options, 'unittests_coverage') |
| 178 auc.Run() |
| 179 return 0 |
| 168 | 180 |
| 169 if '__main__' == __name__: | 181 if '__main__' == __name__: |
| 170 Main() | 182 sys.exit(Main()) |
| OLD | NEW |