Chromium Code Reviews| Index: scripts/common/annotator.py |
| diff --git a/scripts/common/annotator.py b/scripts/common/annotator.py |
| index 1c8ccf52024400872725c39cfcaeff574e6a08d2..1caa9419cca23aa5dd99504b719b080db2dfaac0 100755 |
| --- a/scripts/common/annotator.py |
| +++ b/scripts/common/annotator.py |
| @@ -464,21 +464,25 @@ def triggerBuilds(step, trigger_specs): |
| def run_step(stream, name, cmd, |
|
luqui
2015/03/23 23:26:32
This function has no business being in this file.
luqui
2015/03/27 22:46:58
Not actually true, it's called by run_steps, which
|
| + step_annotation, |
| cwd=None, env=None, |
| - allow_subannotations=False, |
| + subannotator=None, |
| trigger_specs=None, |
| **kwargs): |
| """Runs a single step. |
| Context: |
| stream: StructuredAnnotationStream to use to emit step |
| + step_annotation: optional StructuredAnnotationStep to use instead |
| + of creating one |
| Step parameters: |
| name: name of the step, will appear in buildbots waterfall |
| cmd: command to run, list of one or more strings |
| cwd: absolute path to working directory for the command |
| env: dict with overrides for environment variables |
| - allow_subannotations: if True, lets the step emit its own annotations |
| + subannotator: a callback_implementor class used to parse subannotations |
| + that the command emits; if None, subannotations will be suppressed. |
| trigger_specs: a list of trigger specifications, which are dict with keys: |
| properties: a dict of properties. |
| Buildbot requires buildername property. |
| @@ -503,13 +507,10 @@ def run_step(stream, name, cmd, |
| 'cmd': cmd, |
| 'cwd': cwd, |
| 'env': env, |
| - 'allow_subannotations': allow_subannotations, |
| + 'allow_subannotations': subannotator is not None, |
| }) |
| step_env = _merge_envs(os.environ, env) |
| - step_annotation = stream.step(name) |
| - step_annotation.step_started() |
| - |
| print_step(step_dict, step_env, stream) |
| returncode = 0 |
| if cmd: |
| @@ -539,19 +540,22 @@ def run_step(stream, name, cmd, |
| handle.close() |
| outlock = threading.Lock() |
| - def filter_lines(lock, allow_subannotations, inhandle, outhandle): |
| + def filter_lines(inhandle, outhandle): |
| while True: |
| line = inhandle.readline() |
| if not line: |
| break |
| - lock.acquire() |
| - try: |
| - if not allow_subannotations and line.startswith('@@@'): |
| - outhandle.write('!') |
| - outhandle.write(line) |
| + with outlock: |
| + if line.startswith('@@@'): |
| + if subannotator: |
| + # The subannotator might write to the handle, thus the lock. |
| + MatchAnnotation(line.strip(), subannotator) |
| + else: |
| + outhandle.write('!') |
| + outhandle.write(line) |
| + else: |
| + outhandle.write(line) |
| outhandle.flush() |
| - finally: |
| - lock.release() |
| # Pump piped stdio through filter_lines. IO going to files on disk is |
| # not filtered. |
| @@ -562,7 +566,7 @@ def run_step(stream, name, cmd, |
| outhandle = getattr(sys, key) |
| threads.append(threading.Thread( |
| target=filter_lines, |
| - args=(outlock, allow_subannotations, inhandle, outhandle))) |
| + args=(inhandle, outhandle))) |
| for th in threads: |
| th.start() |
| @@ -580,7 +584,7 @@ def run_step(stream, name, cmd, |
| if trigger_specs: |
| triggerBuilds(step_annotation, trigger_specs) |
| - return step_annotation, returncode |
| + return returncode |
| def update_build_failure(failure, retcode, **_kwargs): |
| """Potentially moves failure from False to True, depending on returncode of |
| @@ -611,7 +615,8 @@ def run_steps(steps, build_failure): |
| if build_failure and not step.get('always_run', False): |
| ret = None |
| else: |
| - prev_annotation, ret = run_step(stream, **step) |
| + prev_annotation = stream.step(step['name']) |
| + ret = run_step(stream, **step) |
| stream = prev_annotation.annotation_stream |
| if ret > 0: |
| stream.step_cursor(stream.current_step) |