Skip to content

Commit 5426cb0

Browse files
author
Vladimir Kotal
authored
add driveon option to sync.py (#2511)
fixes #2510
1 parent 85e42cf commit 5426cb0

File tree

6 files changed

+149
-98
lines changed

6 files changed

+149
-98
lines changed

opengrok-tools/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ Portions Copyright (c) 2017-2018, Chris Fraire <[email protected]>.
289289
<argument>-m</argument>
290290
<argument>flake8</argument>
291291
<argument>-v</argument>
292-
<argument>--exclude=test_command.py,test_commands.py</argument>
293292
<argument>${project.build.sourceDirectory}</argument>
293+
<argument>${project.build.testSourceDirectory}</argument>
294294
<argument>setup.py</argument>
295295
</arguments>
296296
</configuration>

opengrok-tools/src/main/python/opengrok_tools/sync.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ def main():
9090
help='config file in JSON format')
9191
parser.add_argument('-U', '--uri', default='http://localhost:8080/source',
9292
help='URI of the webapp with context path')
93+
parser.add_argument('-f', '--driveon', action='store_true', default=False,
94+
help='continue command sequence processing even '
95+
'if one of the commands requests break')
9396
try:
9497
args = parser.parse_args()
9598
except ValueError as e:
@@ -177,7 +180,8 @@ def main():
177180
cmds_base = []
178181
for d in dirs_to_process:
179182
cmd_base = CommandSequenceBase(d, commands, args.loglevel,
180-
config.get("cleanup"))
183+
config.get("cleanup"),
184+
args.driveon)
181185
cmds_base.append(cmd_base)
182186

183187
# Map the commands into pool of workers so they can be processed.

opengrok-tools/src/main/python/opengrok_tools/utils/commandsequence.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@ class CommandSequenceBase:
3636
so that it can be passed through Pool.map().
3737
"""
3838

39-
def __init__(self, name, commands, loglevel=logging.INFO, cleanup=None):
39+
def __init__(self, name, commands, loglevel=logging.INFO, cleanup=None,
40+
driveon=False):
4041
self.name = name
4142
self.commands = commands
4243
self.failed = False
4344
self.retcodes = {}
4445
self.outputs = {}
4546
self.cleanup = cleanup
4647
self.loglevel = loglevel
48+
self.driveon = driveon
4749

4850
def __str__(self):
4951
return str(self.name)
@@ -67,7 +69,7 @@ class CommandSequence(CommandSequenceBase):
6769

6870
def __init__(self, base):
6971
super().__init__(base.name, base.commands, loglevel=base.loglevel,
70-
cleanup=base.cleanup)
72+
cleanup=base.cleanup, driveon=base.driveon)
7173

7274
self.logger = logging.getLogger(__name__)
7375
self.logger.setLevel(base.loglevel)
@@ -120,7 +122,8 @@ def run(self):
120122
Run the sequence of commands and capture their output and return code.
121123
First command that returns code other than 0 terminates the sequence.
122124
If the command has return code 2, the sequence will be terminated
123-
however it will not be treated as error.
125+
however it will not be treated as error (unless the 'driveon' parameter
126+
is True).
124127
125128
If a command contains PROJECT_SUBST pattern, it will be replaced
126129
by project name, otherwise project name will be appended to the
@@ -136,19 +139,29 @@ def run(self):
136139
else:
137140
retcode = self.run_command(command)
138141

139-
# If a command fails, terminate the sequence of commands.
142+
# If a command exits with non-zero return code,
143+
# terminate the sequence of commands.
140144
if retcode != 0:
141145
if retcode == 2:
142-
self.logger.debug("command '{}' for project {} "
143-
"requested break".
144-
format(self.name, command))
145-
self.run_cleanup()
146+
if not self.driveon:
147+
self.logger.debug("command '{}' for project {} "
148+
"requested break".
149+
format(self.name, command))
150+
self.run_cleanup()
151+
else:
152+
self.logger.debug("command '{}' for project {} "
153+
"requested break however "
154+
"the 'driveon' option is set "
155+
"so driving on.".
156+
format(self.name, command))
157+
continue
146158
else:
147159
self.logger.error("command '{}' for project {} failed "
148160
"with code {}, breaking".
149161
format(command, self.name, retcode))
150162
self.failed = True
151163
self.run_cleanup()
164+
152165
break
153166

154167
def run_cleanup(self):

opengrok-tools/src/test/python/test_command.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def test_subst_append_exclsubst_nosubst():
6666
def test_execute_nonexistent():
6767
cmd = Command(['/baaah', '/etc/passwd'])
6868
cmd.execute()
69-
assert cmd.getretcode() == None
69+
assert cmd.getretcode() is None
7070
assert cmd.getstate() == Command.ERRORED
7171

7272

@@ -88,7 +88,8 @@ def test_work_dir():
8888
assert os.getcwd() == orig_cwd
8989

9090

91-
@pytest.mark.skipif(not os.path.exists('/usr/bin/env'), reason="requires posix")
91+
@pytest.mark.skipif(not os.path.exists('/usr/bin/env'),
92+
reason="requires posix")
9293
def test_env():
9394
cmd = Command(['/usr/bin/env'],
9495
env_vars={'FOO': 'BAR', 'A': 'B'})
@@ -141,7 +142,7 @@ def test_command_timeout():
141142
elapsed_time = time.time() - start_time
142143
assert elapsed_time < timeout
143144
assert cmd.getstate() == Command.TIMEDOUT
144-
assert cmd.getretcode() == None
145+
assert cmd.getretcode() is None
145146

146147

147148
@pytest.mark.skipif(not os.path.exists('/bin/sleep'),
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/usr/bin/env python3
2+
3+
#
4+
# CDDL HEADER START
5+
#
6+
# The contents of this file are subject to the terms of the
7+
# Common Development and Distribution License (the "License").
8+
# You may not use this file except in compliance with the License.
9+
#
10+
# See LICENSE.txt included in this distribution for the specific
11+
# language governing permissions and limitations under the License.
12+
#
13+
# When distributing Covered Code, include this CDDL HEADER in each
14+
# file and include the License file at LICENSE.txt.
15+
# If applicable, add the following below this CDDL HEADER, with the
16+
# fields enclosed by brackets "[]" replaced with your own identifying
17+
# information: Portions Copyright [yyyy] [name of copyright owner]
18+
#
19+
# CDDL HEADER END
20+
#
21+
22+
#
23+
# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
24+
#
25+
26+
import os
27+
28+
import pytest
29+
30+
from opengrok_tools.utils.commandsequence import CommandSequence, \
31+
CommandSequenceBase
32+
33+
34+
def test_str():
35+
cmds = CommandSequence(CommandSequenceBase("opengrok-master",
36+
[{"command": ['foo']},
37+
{"command": ["bar"]}]))
38+
assert str(cmds) == "opengrok-master"
39+
40+
41+
@pytest.mark.skipif(not os.path.exists('/bin/sh')
42+
or not os.path.exists('/bin/echo'),
43+
reason="requires Unix")
44+
def test_run_retcodes():
45+
cmd_list = [{"command": ["/bin/echo"]},
46+
{"command": ["/bin/sh", "-c",
47+
"echo " + CommandSequence.PROJECT_SUBST + "; exit 0"]},
48+
{"command": ["/bin/sh", "-c",
49+
"echo " + CommandSequence.PROJECT_SUBST + "; exit 1"]}]
50+
cmds = CommandSequence(CommandSequenceBase("opengrok-master", cmd_list))
51+
cmds.run()
52+
assert cmds.retcodes == {
53+
'/bin/echo opengrok-master': 0,
54+
'/bin/sh -c echo opengrok-master; exit 0': 0,
55+
'/bin/sh -c echo opengrok-master; exit 1': 1
56+
}
57+
58+
59+
@pytest.mark.skipif(not os.path.exists('/bin/sh')
60+
or not os.path.exists('/bin/echo'),
61+
reason="requires Unix")
62+
def test_terminate_after_non_zero_code():
63+
cmd_list = [{"command": ["/bin/sh", "-c",
64+
"echo " + CommandSequence.PROJECT_SUBST + "; exit 255"]},
65+
{"command": ["/bin/echo"]}]
66+
cmds = CommandSequence(CommandSequenceBase("opengrok-master", cmd_list))
67+
cmds.run()
68+
assert cmds.retcodes == {
69+
'/bin/sh -c echo opengrok-master; exit 255': 255
70+
}
71+
72+
73+
@pytest.mark.skipif(not os.path.exists('/bin/sh')
74+
or not os.path.exists('/bin/echo'),
75+
reason="requires Unix")
76+
def test_exit_2_handling():
77+
cmd_list = [{"command": ["/bin/sh", "-c",
78+
"echo " + CommandSequence.PROJECT_SUBST + "; exit 2"]},
79+
{"command": ["/bin/echo"]}]
80+
cmds = CommandSequence(CommandSequenceBase("opengrok-master", cmd_list))
81+
cmds.run()
82+
assert cmds.retcodes == {
83+
'/bin/sh -c echo opengrok-master; exit 2': 2
84+
}
85+
assert not cmds.failed
86+
87+
88+
@pytest.mark.skipif(not os.path.exists('/bin/sh')
89+
or not os.path.exists('/bin/echo'),
90+
reason="requires Unix")
91+
def test_driveon_flag():
92+
cmd_list = [{"command": ["/bin/sh", "-c",
93+
"echo " + CommandSequence.PROJECT_SUBST + "; exit 2"]},
94+
{"command": ["/bin/echo"]},
95+
{"command": ["/bin/sh", "-c",
96+
"echo " + CommandSequence.PROJECT_SUBST +
97+
"; exit 1"]},
98+
{"command": ["/bin/sh", "-c",
99+
"echo " + CommandSequence.PROJECT_SUBST]}]
100+
cmds = CommandSequence(CommandSequenceBase("opengrok-master",
101+
cmd_list, driveon=True))
102+
cmds.run()
103+
assert cmds.retcodes == {
104+
'/bin/sh -c echo opengrok-master; exit 2': 2,
105+
'/bin/echo opengrok-master': 0,
106+
'/bin/sh -c echo opengrok-master; exit 1': 1
107+
}
108+
assert cmds.failed
109+
110+
111+
@pytest.mark.skipif(not os.path.exists('/bin/echo'),
112+
reason="requires Unix")
113+
def test_project_subst():
114+
cmd_list = [{"command": ["/bin/echo", CommandSequence.PROJECT_SUBST]}]
115+
cmds = CommandSequence(CommandSequenceBase("test-subst", cmd_list))
116+
cmds.run()
117+
118+
assert cmds.outputs['/bin/echo test-subst'] == ['test-subst\n']

opengrok-tools/src/test/python/test_commands.py

Lines changed: 0 additions & 85 deletions
This file was deleted.

0 commit comments

Comments
 (0)