aboutsummaryrefslogtreecommitdiff
path: root/pw_env_setup/py/pw_env_setup/batch_visitor.py
diff options
context:
space:
mode:
Diffstat (limited to 'pw_env_setup/py/pw_env_setup/batch_visitor.py')
-rw-r--r--pw_env_setup/py/pw_env_setup/batch_visitor.py122
1 files changed, 122 insertions, 0 deletions
diff --git a/pw_env_setup/py/pw_env_setup/batch_visitor.py b/pw_env_setup/py/pw_env_setup/batch_visitor.py
new file mode 100644
index 000000000..e7c535381
--- /dev/null
+++ b/pw_env_setup/py/pw_env_setup/batch_visitor.py
@@ -0,0 +1,122 @@
+# Copyright 2021 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+"""Serializes an Environment into a batch file."""
+
+# Disable super() warnings since this file must be Python 2 compatible.
+# pylint: disable=super-with-arguments
+
+# goto label written to the end of Windows batch files for exiting a script.
+_SCRIPT_END_LABEL = '_pw_end'
+
+
+class BatchVisitor(object): # pylint: disable=useless-object-inheritance
+ """Serializes an Environment into a batch file."""
+ def __init__(self, *args, **kwargs):
+ pathsep = kwargs.pop('pathsep', ':')
+ super(BatchVisitor, self).__init__(*args, **kwargs)
+ self._replacements = ()
+ self._outs = None
+ self._pathsep = pathsep
+
+ def serialize(self, env, outs):
+ try:
+ self._replacements = tuple(
+ (key, env.get(key) if value is None else value)
+ for key, value in env.replacements)
+ self._outs = outs
+ self._outs.write('@echo off\n')
+
+ env.accept(self)
+
+ outs.write(':{}\n'.format(_SCRIPT_END_LABEL))
+
+ finally:
+ self._replacements = ()
+ self._outs = None
+
+ def _apply_replacements(self, action):
+ value = action.value
+ for var, replacement in self._replacements:
+ if var != action.name:
+ value = value.replace(replacement, '%{}%'.format(var))
+ return value
+
+ def visit_set(self, set): # pylint: disable=redefined-builtin
+ value = self._apply_replacements(set)
+ self._outs.write('set {name}={value}\n'.format(name=set.name,
+ value=value))
+
+ def visit_clear(self, clear):
+ self._outs.write('set {name}=\n'.format(name=clear.name))
+
+ def visit_remove(self, remove):
+ pass # Not supported on Windows.
+
+ def _join(self, *args):
+ if len(args) == 1 and isinstance(args[0], (list, tuple)):
+ args = args[0]
+ return self._pathsep.join(args)
+
+ def visit_prepend(self, prepend):
+ value = self._apply_replacements(prepend)
+ value = self._join(value, '%{}%'.format(prepend.name))
+ self._outs.write('set {name}={value}\n'.format(name=prepend.name,
+ value=value))
+
+ def visit_append(self, append):
+ value = self._apply_replacements(append)
+ value = self._join('%{}%'.format(append.name), value)
+ self._outs.write('set {name}={value}\n'.format(name=append.name,
+ value=value))
+
+ def visit_echo(self, echo):
+ if echo.newline:
+ if not echo.value:
+ self._outs.write('echo.\n')
+ else:
+ self._outs.write('echo {}\n'.format(echo.value))
+ else:
+ self._outs.write('<nul set /p="{}"\n'.format(echo.value))
+
+ def visit_comment(self, comment):
+ for line in comment.value.splitlines():
+ self._outs.write(':: {}\n'.format(line))
+
+ def visit_command(self, command):
+ # TODO(mohrr) use shlex.quote here?
+ self._outs.write('{}\n'.format(' '.join(command.command)))
+ if not command.exit_on_error:
+ return
+
+ # Assume failing command produced relevant output.
+ self._outs.write(
+ 'if %ERRORLEVEL% neq 0 goto {}\n'.format(_SCRIPT_END_LABEL))
+
+ def visit_doctor(self, doctor):
+ self._outs.write('if "%PW_ACTIVATE_SKIP_CHECKS%"=="" (\n')
+ self.visit_command(doctor)
+ self._outs.write(') else (\n')
+ self._outs.write('echo Skipping environment check because '
+ 'PW_ACTIVATE_SKIP_CHECKS is set\n')
+ self._outs.write(')\n')
+
+ def visit_blank_line(self, blank_line):
+ del blank_line
+ self._outs.write('\n')
+
+ def visit_function(self, function):
+ pass # Not supported on Windows.
+
+ def visit_hash(self, hash): # pylint: disable=redefined-builtin
+ pass # Not relevant on Windows.