OLD | NEW |
1 # Copyright 2013 The LUCI Authors. All rights reserved. | 1 # Copyright 2013 The LUCI Authors. All rights reserved. |
2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
4 | 4 |
5 import contextlib | 5 import contextlib |
6 | 6 |
7 from recipe_engine import recipe_api | 7 from recipe_engine import recipe_api |
8 | 8 |
9 | 9 |
10 # Inherit from RecipeApiPlain because the only thing which is a step is | 10 # Inherit from RecipeApiPlain because the only thing which is a step is |
11 # run_from_dict() | 11 # run_from_dict() |
12 class StepApi(recipe_api.RecipeApiPlain): | 12 class StepApi(recipe_api.RecipeApiPlain): |
13 def __init__(self, **kwargs): | 13 def __init__(self, **kwargs): |
14 super(StepApi, self).__init__(**kwargs) | 14 super(StepApi, self).__init__(**kwargs) |
15 self._step_names = {} | 15 self._step_names = {} |
| 16 self._seen_steps = set() |
16 | 17 |
17 EXCEPTION = 'EXCEPTION' | 18 EXCEPTION = 'EXCEPTION' |
18 FAILURE = 'FAILURE' | 19 FAILURE = 'FAILURE' |
19 SUCCESS = 'SUCCESS' | 20 SUCCESS = 'SUCCESS' |
20 WARNING = 'WARNING' | 21 WARNING = 'WARNING' |
21 | 22 |
22 @property | 23 @property |
23 def StepFailure(self): | 24 def StepFailure(self): |
24 """ See recipe_api.py for docs. """ | 25 """ See recipe_api.py for docs. """ |
25 return recipe_api.StepFailure | 26 return recipe_api.StepFailure |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 if cmd is not None: | 129 if cmd is not None: |
129 command = list(wrapper) | 130 command = list(wrapper) |
130 command += cmd | 131 command += cmd |
131 kwargs['cmd'] = command | 132 kwargs['cmd'] = command |
132 | 133 |
133 kwargs['timeout'] = timeout | 134 kwargs['timeout'] = timeout |
134 kwargs['ok_ret'] = ok_ret | 135 kwargs['ok_ret'] = ok_ret |
135 | 136 |
136 # Obtain information from composite step parent. | 137 # Obtain information from composite step parent. |
137 compositor = recipe_api._STEP_CONTEXT | 138 compositor = recipe_api._STEP_CONTEXT |
138 name = compositor.get_with_context('name', name) | 139 |
| 140 # Calculate our full step name. If a step already has that name, add an |
| 141 # index to the end of it. |
| 142 # |
| 143 # Note that another step could exist with that index already added to it |
| 144 # by the user. If this happens, we'll continue appending indexes until we |
| 145 # have a unique step name. |
| 146 while True: |
| 147 full_name = compositor.get_with_context('name', name) |
| 148 if full_name not in self._seen_steps: |
| 149 break |
| 150 |
| 151 step_count = self._step_names.setdefault(full_name, 1) + 1 |
| 152 self._step_names[full_name] = step_count |
| 153 name = "%s (%d)" % (name, step_count) |
| 154 self._seen_steps.add(full_name) |
| 155 |
139 if 'cwd' not in kwargs: | 156 if 'cwd' not in kwargs: |
140 kwargs['cwd'] = compositor.get('cwd') | 157 kwargs['cwd'] = compositor.get('cwd') |
141 kwargs['env'] = compositor.get_with_context('env', kwargs.get('env', {})) | 158 kwargs['env'] = compositor.get_with_context('env', kwargs.get('env', {})) |
142 kwargs['infra_step'] = compositor.get_with_context( | 159 kwargs['infra_step'] = compositor.get_with_context( |
143 'infra_step', bool(infra_step)) | 160 'infra_step', bool(infra_step)) |
144 kwargs['step_nest_level'] = compositor.get_with_context('nest_level', 0) | 161 kwargs['step_nest_level'] = compositor.get_with_context('nest_level', 0) |
145 | 162 kwargs['name'] = full_name |
146 # Disambiguate repeated names | |
147 step_count = self._step_names.setdefault(name, 0) + 1 | |
148 self._step_names[name] = step_count | |
149 if step_count > 1: | |
150 name = "%s (%d)" % (name, step_count) | |
151 kwargs['name'] = name | |
152 | 163 |
153 schema = self.make_config() | 164 schema = self.make_config() |
154 schema.set_val(kwargs) | 165 schema.set_val(kwargs) |
155 return self.run_from_dict(self._engine.create_step(schema)) | 166 return self.run_from_dict(self._engine.create_step(schema)) |
156 | 167 |
157 # TODO(martiniss) delete, and make generator_script use **kwargs on step() | 168 # TODO(martiniss) delete, and make generator_script use **kwargs on step() |
158 @recipe_api.composite_step | 169 @recipe_api.composite_step |
159 def run_from_dict(self, dct): | 170 def run_from_dict(self, dct): |
160 return self._engine.run_step(dct) | 171 return self._engine.run_step(dct) |
OLD | NEW |