|
7 | 7 | */ |
8 | 8 | // tslint:disable:no-implicit-dependencies |
9 | 9 | import { logging } from '@angular-devkit/core'; |
| 10 | +import { spawnSync } from 'child_process'; |
10 | 11 | import * as glob from 'glob'; |
11 | 12 | import * as Istanbul from 'istanbul'; |
12 | 13 | import 'jasmine'; |
@@ -37,6 +38,21 @@ declare const global: { |
37 | 38 | }; |
38 | 39 |
|
39 | 40 |
|
| 41 | +function _exec(command: string, args: string[], opts: { cwd?: string }, logger: logging.Logger) { |
| 42 | + const { status, error, stdout } = spawnSync(command, args, { |
| 43 | + stdio: ['ignore', 'pipe', 'inherit'], |
| 44 | + ...opts, |
| 45 | + }); |
| 46 | + |
| 47 | + if (status != 0) { |
| 48 | + logger.error(`Command failed: ${command} ${args.map(x => JSON.stringify(x)).join(', ')}`); |
| 49 | + throw error; |
| 50 | + } |
| 51 | + |
| 52 | + return stdout.toString('utf-8'); |
| 53 | +} |
| 54 | + |
| 55 | + |
40 | 56 | // Add the Istanbul (not Constantinople) reporter. |
41 | 57 | const istanbulCollector = new Istanbul.Collector({}); |
42 | 58 | const istanbulReporter = new Istanbul.Reporter(undefined, 'coverage/'); |
@@ -202,15 +218,39 @@ export default function (args: ParsedArgs, logger: logging.Logger) { |
202 | 218 | let tests = allTests.filter(x => !excludeRe.test(x)); |
203 | 219 |
|
204 | 220 | if (!args.full) { |
205 | | - // Remove the tests from packages that haven't changed. |
206 | | - tests = tests |
207 | | - .filter(p => Object.keys(packages).some(name => { |
208 | | - const relativeRoot = relative(projectBaseDir, packages[name].root); |
| 221 | + // Find the point where this branch merged with master. |
| 222 | + const branch = _exec('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {}, logger).trim(); |
| 223 | + const masterRevList = _exec('git', ['rev-list', 'master'], {}, logger).trim().split('\n'); |
| 224 | + const branchRevList = _exec('git', ['rev-list', branch], {}, logger).trim().split('\n'); |
| 225 | + const sha = branchRevList.find(s => masterRevList.includes(s)); |
| 226 | + |
| 227 | + if (sha) { |
| 228 | + const diffFiles = _exec( |
| 229 | + 'git', |
| 230 | + ['diff', sha, 'HEAD', '--name-only'], |
| 231 | + {}, |
| 232 | + logger, |
| 233 | + ).trim().split('\n'); |
| 234 | + const diffPackages = new Set(); |
| 235 | + for (const pkgName of Object.keys(packages)) { |
| 236 | + const relativeRoot = relative(projectBaseDir, packages[pkgName].root); |
| 237 | + if (diffFiles.some(x => x.startsWith(relativeRoot))) { |
| 238 | + diffPackages.add(pkgName); |
| 239 | + // Add all reverse dependents too. |
| 240 | + packages[pkgName].reverseDependencies.forEach(d => diffPackages.add(d)); |
| 241 | + } |
| 242 | + } |
209 | 243 |
|
210 | | - return p.startsWith(relativeRoot) && packages[name].dirty; |
211 | | - })); |
| 244 | + // Remove the tests from packages that haven't changed. |
| 245 | + tests = tests |
| 246 | + .filter(p => Object.keys(packages).some(name => { |
| 247 | + const relativeRoot = relative(projectBaseDir, packages[name].root); |
212 | 248 |
|
213 | | - logger.info(`Found ${tests.length} spec files, out of ${allTests.length}.`); |
| 249 | + return p.startsWith(relativeRoot) && diffPackages.has(name); |
| 250 | + })); |
| 251 | + |
| 252 | + logger.info(`Found ${tests.length} spec files, out of ${allTests.length}.`); |
| 253 | + } |
214 | 254 | } |
215 | 255 |
|
216 | 256 | if (args.shard !== undefined) { |
|
0 commit comments