binutils: don't discard eh_frames during ld -r

We don't have enough information to decide whether or not to discard them
until relative addresses are worked out, i.e. at the final link.

# This shell script emits a C file. -*- C -*-
#   Copyright 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
# MA 02110-1301, USA.

fragment <<EOF

#include "ldmain.h"
#include "ldctor.h"
#include "elf/riscv.h"
#include "elfxx-riscv.h"

static void
riscv_before_allocation (void)
{
  gld${EMULATION_NAME}_before_allocation ();

  if (link_info.discard == discard_sec_merge)
    link_info.discard = discard_l;

  /* We always need at least some relaxation to handle code alignment.  */
  if (RELAXATION_DISABLED_BY_USER)
    TARGET_ENABLE_RELAXATION;
  else
    ENABLE_RELAXATION;

  link_info.relax_pass = 2;
}

static void
riscv_after_allocation (void)
{
  int need_layout = 0;

  /* Don't attempt to discard unused .eh_frame sections until the final link,
     as we can't reliably tell if they're used until after relaxation.  */
  if (!link_info.relocatable)
    {
      need_layout = bfd_elf_discard_info (link_info.output_bfd, &link_info);
      if (need_layout < 0)
	{
	  einfo ("%X%P: .eh_frame/.stab edit: %E\n");
	  return;
	}
    }

  gld${EMULATION_NAME}_map_segments (need_layout);
}

EOF

LDEMUL_BEFORE_ALLOCATION=riscv_before_allocation
LDEMUL_AFTER_ALLOCATION=riscv_after_allocation

# This shell script emits a C file. -*- C -*-
#   Copyright 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
# MA 02110-1301, USA.

fragment <<EOF

#include "ldmain.h"
#include "ldctor.h"
#include "elf/riscv.h"
#include "elfxx-riscv.h"

static void
riscv_before_allocation (void)
{
  gld${EMULATION_NAME}_before_allocation ();

  if (link_info.discard == discard_sec_merge)
    link_info.discard = discard_l;

  /* We always need at least some relaxation to handle code alignment.  */
  if (RELAXATION_DISABLED_BY_USER)
    TARGET_ENABLE_RELAXATION;
  else
    ENABLE_RELAXATION;

  link_info.relax_pass = 2;
}

EOF

LDEMUL_BEFORE_ALLOCATION=riscv_before_allocation


removed deprecated GAZEBO_WORLDS_PKG export

#!/bin/bash

# DO NOT REMOVE THIS BLOCK UNLESS YOU DON'T WANT TO USE CUSTOM SCRIPTS
@[if DEVELSPACE]@
export ROSWSS_SCRIPTS="@(PROJECT_SOURCE_DIR)/scripts:$ROSWSS_SCRIPTS"
@[else]@
export ROSWSS_SCRIPTS="@(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION)/scripts:$ROSWSS_SCRIPTS"
@[end if]@

# SET HERE YOUR WORKSPACE PREFIX
export ROSWSS_PREFIX="thor"
export ROSWSS_ROOT_RELATIVE_PATH="../.."
export ROSWSS_INSTALL_DIR="rosinstall"

# SETUP YOUR ENVIRONMENT HERE (all fields are optional)
export ONBOARD_LAUNCH_PKG="thor_mang_onboard_launch"
export UI_LAUNCH_PKG="thor_mang_ui_launch"
export GAZEBO_LAUNCH_PKG="thor_mang_gazebo"
export GAZEBO_DEFAULT_LAUNCH_FILE="johnny5.launch"
export AUTOSTART_LAUNCH_PKG="thor_mang_robot_bringup"
export ROBOT_MASTER_HOSTNAME="motion"
export ROBOT_HOSTNAMES="motion perception"
export ROBOT_USER="thor"

# THOR PCs/LAUNCHES
# Syntax:
#   add_remote_pc "<script_name>" "<host_name>" "<screen_name>" "<command>"
add_remote_pc "motion" "motion" "motion_start" "~/thor/src/thor/thor_mang_robot_bringup/scripts/motion.sh"
add_remote_pc "perception" "perception" "perception_start" "~/thor/src/thor/thor_mang_robot_bringup/scripts/perception.sh"
add_remote_pc "onboard" "motion" "onboard_start" "~/thor/src/thor/thor_mang_robot_bringup/scripts/onboard.sh"
add_remote_pc "robot_basics" "motion" "robot_basics_start" "~/thor/src/thor/thor_mang_robot_bringup/scripts/robot_basics.sh"

#!/bin/bash

# DO NOT REMOVE THIS BLOCK UNLESS YOU DON'T WANT TO USE CUSTOM SCRIPTS
@[if DEVELSPACE]@
export ROSWSS_SCRIPTS="@(PROJECT_SOURCE_DIR)/scripts:$ROSWSS_SCRIPTS"
@[else]@
export ROSWSS_SCRIPTS="@(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION)/scripts:$ROSWSS_SCRIPTS"
@[end if]@

# SET HERE YOUR WORKSPACE PREFIX
export ROSWSS_PREFIX="thor"
export ROSWSS_ROOT_RELATIVE_PATH="../.."
export ROSWSS_INSTALL_DIR="rosinstall"

# SETUP YOUR ENVIRONMENT HERE (all fields are optional)
export ONBOARD_LAUNCH_PKG="thor_mang_onboard_launch"
export UI_LAUNCH_PKG="thor_mang_ui_launch"
export GAZEBO_LAUNCH_PKG="thor_mang_gazebo"
export GAZEBO_DEFAULT_LAUNCH_FILE="johnny5.launch"
export GAZEBO_WORLDS_PKG="thor_mang_gazebo"
export AUTOSTART_LAUNCH_PKG="thor_mang_robot_bringup"
export ROBOT_MASTER_HOSTNAME="motion"
export ROBOT_HOSTNAMES="motion perception"
export ROBOT_USER="thor"

# THOR PCs/LAUNCHES
# Syntax:
#   add_remote_pc "<script_name>" "<host_name>" "<screen_name>" "<command>"
add_remote_pc "motion" "motion" "motion_start" "~/thor/src/thor/thor_mang_robot_bringup/scripts/motion.sh"
add_remote_pc "perception" "perception" "perception_start" "~/thor/src/thor/thor_mang_robot_bringup/scripts/perception.sh"
add_remote_pc "onboard" "motion" "onboard_start" "~/thor/src/thor/thor_mang_robot_bringup/scripts/onboard.sh"
add_remote_pc "robot_basics" "motion" "robot_basics_start" "~/thor/src/thor/thor_mang_robot_bringup/scripts/robot_basics.sh"


Installed xacro relocatable fix.

Installed xacro relocatable fix.

@[if DEVELSPACE]@
set(_xacro_py
  @(CMAKE_CURRENT_SOURCE_DIR)/scripts/xacro
)
@[else]@
set(_xacro_py
  ${xacro_DIR}/../../../@(CATKIN_PACKAGE_BIN_DESTINATION)/xacro
)
@[end if]@

macro(xacro_add_xacro_file input output)
  # Call out to xacro to get dependencies
  execute_process(COMMAND ${_xacro_py} --deps ${input}
    ERROR_VARIABLE _xacro_err_ignore
    OUTPUT_VARIABLE _xacro_deps_result
    OUTPUT_STRIP_TRAILING_WHITESPACE)

  separate_arguments(_xacro_deps_result)

  add_custom_command(OUTPUT ${output}
    COMMAND ${_xacro_py}
    ARGS ${input} > ${output}
    DEPENDS ${input} ${_xacro_deps_result})
endmacro(xacro_add_xacro_file)

@[if DEVELSPACE]@
set(_xacro_py
  @(CMAKE_CURRENT_SOURCE_DIR)/scripts/xacro
)
@[else]@
set(_xacro_py
  @(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_BIN_DESTINATION)/xacro
)
@[end if]@

macro(xacro_add_xacro_file input output)
  # Call out to xacro to get dependencies
  execute_process(COMMAND ${_xacro_py} --deps ${input}
    ERROR_VARIABLE _xacro_err_ignore
    OUTPUT_VARIABLE _xacro_deps_result
    OUTPUT_STRIP_TRAILING_WHITESPACE)

  separate_arguments(_xacro_deps_result)

  add_custom_command(OUTPUT ${output}
    COMMAND ${_xacro_py}
    ARGS ${input} > ${output}
    DEPENDS ${input} ${_xacro_deps_result})
endmacro(xacro_add_xacro_file)


Fix exception printing for scriptables by forcing a deep copy of the exception object within JS so that all its fields are extracted before serialization since the serialization code has trouble with some of the builtin fields.

/*  Sirikata
 *  scriptable.em
 *
 *  Copyright (c) 2011, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

system.require('std/core/bind.js');

if (typeof(std) === "undefined") std = {};
if (typeof(std.script) === "undefined") std.script = {};

(
function() {

    var ns = std.script;

    /** A Scriptable is an object which listens for messages from
     *  other objects, executes their contents, and replies with the
     *  results.
     */
    ns.Scriptable = function() {
        var scriptRequestPattern = new util.Pattern("request", "script");
        var scriptRequestHandler = std.core.bind(this._handleScriptRequest, this);
        scriptRequestHandler <- scriptRequestPattern;
    };

    var deepCopy = function(val) {
        if (typeof(val) === "object") {
            var ret = {};
            var props = Object.getOwnPropertyNames(val);
            for(var f in props)
                ret[props[f]] = deepCopy(val[props[f]]);
            return ret;
        }
        else
            return val;
    };
    ns.Scriptable.prototype._handleScriptRequest = function(msg, sender) {
        if (!this._printer || sender != this._printer) {
            this._printer = sender;
            system.onPrint( std.core.bind(this._handlePrint, this) );
        }

        if (this._printerTimeout)
            this._printerTimeout.reset();
        this._printerTimeout = system.timeout(60, std.core.bind(this._handlePrinterTimeout, this));

        var cmd = msg.script;
        var result = undefined, excep = undefined;
        try {
            result = system.eval(cmd);
        } catch (ex) {
            // Currently, we need to do a deep copy because some
            // fields seem to be some sort of weird built in type (or
            // accessor) which the C++ V8 API doesn't seem to
            // expose. Copying forces the data to be evaluated into
            // real values. So far we've only seen this with
            // exceptions thrown by the V8 runtime (ones generated by
            // our C++ code are fine)
            excep = deepCopy(ex);
        }
        var retmsg = {
            reply : 'script',
            value : result,
            exception : excep
        };
        retmsg -> sender;
    };

    ns.Scriptable.prototype._handlePrint = function() {
        var print_msg = {
            request: 'print',
            print: (arguments.length == 1 ? arguments[0] : arguments)
        };
        print_msg -> this._printer;
    };

    ns.Scriptable.prototype._handlePrinterTimeout = function() {
        system.onPrint(undefined);
        this._timerPrintout = null;
    };

})();

/*  Sirikata
 *  scriptable.em
 *
 *  Copyright (c) 2011, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

system.require('std/core/bind.js');

if (typeof(std) === "undefined") std = {};
if (typeof(std.script) === "undefined") std.script = {};

(
function() {

    var ns = std.script;

    /** A Scriptable is an object which listens for messages from
     *  other objects, executes their contents, and replies with the
     *  results.
     */
    ns.Scriptable = function() {
        var scriptRequestPattern = new util.Pattern("request", "script");
        var scriptRequestHandler = std.core.bind(this._handleScriptRequest, this);
        scriptRequestHandler <- scriptRequestPattern;
    };

    ns.Scriptable.prototype._handleScriptRequest = function(msg, sender) {
        if (!this._printer || sender != this._printer) {
            this._printer = sender;
            system.onPrint( std.core.bind(this._handlePrint, this) );
        }

        if (this._printerTimeout)
            this._printerTimeout.reset();
        this._printerTimeout = system.timeout(60, std.core.bind(this._handlePrinterTimeout, this));

        var cmd = msg.script;
        var result = undefined, excep = undefined;
        try {
            result = system.eval(cmd);
        } catch (ex) {
            excep = ex;
        }
        var retmsg = {
            reply : 'script',
            value : result,
            exception : excep
        };
        retmsg -> sender;
    };

    ns.Scriptable.prototype._handlePrint = function() {
        var print_msg = {
            request: 'print',
            print: (arguments.length == 1 ? arguments[0] : arguments)
        };
        print_msg -> this._printer;
    };

    ns.Scriptable.prototype._handlePrinterTimeout = function() {
        system.onPrint(undefined);
        this._timerPrintout = null;
    };

})();


different languages, different comments

different languages, different comments

// generated from ros1_bridge/resource/generated_factories.cpp.em

@###############################################
@#
@# Factory for creating publisher / subscribers
@# based on message names
@#
@# EmPy template for generating generated_factories.cpp
@#
@###############################################
@# Start of Template
@#
@# Context:
@#  - ros1_msgs (list of ros1_bridge.Message)
@#    ROS 1 messages
@#  - ros2_msgs (list of ros1_bridge.Message)
@#    ROS 2 messages
@#  - mappings (list of ros1_bridge.Mapping)
@#    Mapping between messages as well as their fields
@###############################################
@
@{
from ros1_bridge import camel_case_to_lower_case_underscore
}@
#include <ros1_bridge/factory.hpp>

// include ROS 1 builtin messages
#include <ros/duration.h>
#include <ros/time.h>

// include ROS 2 builtin messages
#include <builtin_interfaces/msg/duration.hpp>
#include <builtin_interfaces/msg/time.hpp>

// include ROS 1 messages
@[for ros1_msg in ros1_msgs]@
#include <@(ros1_msg.package_name)/@(ros1_msg.message_name).h>
@[end for]@

// include ROS 2 messages
@[for ros2_msg in ros2_msgs]@
#include <@(ros2_msg.package_name)/msg/@(camel_case_to_lower_case_underscore(ros2_msg.message_name)).hpp>
@[end for]@

namespace ros1_bridge
{

std::shared_ptr<FactoryInterface>
get_factory(const std::string & ros1_type_name, const std::string & ros2_type_name)
{
@[if not mappings]@
  (void)ros1_type_name;
  (void)ros2_type_name;
@[end if]@
  // mapping from string to specialized template
@[for m in mappings]@
  if (
    (ros1_type_name == "@(m.ros1_msg.package_name)/@(m.ros1_msg.message_name)" ||
     ros1_type_name == "") &&
    ros2_type_name == "@(m.ros2_msg.package_name)/@(m.ros2_msg.message_name)")
  {
    return std::make_shared<
      Factory<
        @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
        @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
      >
    >();
  }
@[end for]@
  throw std::runtime_error("No template specialization for the pair");
}

// conversion functions for builtin interfaces

template<typename ROS1_T, typename ROS2_T>
void
convert_1_to_2(
  const ROS1_T & ros1_msg,
  ROS2_T & ros2_msg);

template<typename ROS1_T, typename ROS2_T>
void
convert_2_to_1(
  const ROS2_T & ros2_msg,
  ROS1_T & ros1_msg);

template<>
void
convert_1_to_2(
  const ros::Duration & ros1_msg,
  builtin_interfaces::msg::Duration & ros2_msg)
{
  ros2_msg.sec = ros1_msg.sec;
  ros2_msg.nanosec = ros1_msg.nsec;
}

template<>
void
convert_2_to_1(
  const builtin_interfaces::msg::Duration & ros2_msg,
  ros::Duration & ros1_msg)
{
  ros1_msg.sec = ros2_msg.sec;
  ros1_msg.nsec = ros2_msg.nanosec;
}

template<>
void
convert_1_to_2(
  const ros::Time & ros1_msg,
  builtin_interfaces::msg::Time & ros2_msg)
{
  ros2_msg.sec = ros1_msg.sec;
  ros2_msg.nanosec = ros1_msg.nsec;
}

template<>
void
convert_2_to_1(
  const builtin_interfaces::msg::Time & ros2_msg,
  ros::Time & ros1_msg)
{
  ros1_msg.sec = ros2_msg.sec;
  ros1_msg.nsec = ros2_msg.nanosec;
}

// conversion functions for available interfaces
@[for m in mappings]@

template<>
void
Factory<
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
>::convert_1_to_2(
  const @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name) & ros1_msg,
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name) & ros2_msg)
{
@[  if not m.fields_1_to_2]@
  (void)ros1_msg;
  (void)ros2_msg;
@[  end if]@
@[  for ros1_field, ros2_field in m.fields_1_to_2.items()]@
@[    if not ros2_field.type.is_array]@
  // convert non-array field
@[      if not ros2_field.type.pkg_name]@
  // convert primitive field
  ros2_msg.@(ros2_field.name) = ros1_msg.@(ros1_field.name);
@[      elif ros2_field.type.pkg_name == 'builtin_interfaces']@
  // convert builtin field
  ros1_bridge::convert_1_to_2(ros1_msg.@(ros1_field.name), ros2_msg.@(ros2_field.name));
@[      else]@
  // convert sub message field
  Factory<
    @(ros1_field.pkg_name)::@(ros1_field.msg_name),
    @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
  >::convert_1_to_2(
    ros1_msg.@(ros1_field.name), ros2_msg.@(ros2_field.name));
@[      end if]@
@[    else]@
  // convert array field
@[      if not ros2_field.type.array_size or ros2_field.type.is_upper_bound]@
  // ensure array size
@[        if ros2_field.type.is_upper_bound]@
  // check boundary
  assert(ros1_msg.@(ros1_field.name).size() <= @(ros2_field.type.array_size));
@[        end if]@
  // dynamic arrays must be resized
  ros2_msg.@(ros2_field.name).resize(ros1_msg.@(ros1_field.name).size());
@[      end if]@
@[      if not ros2_field.type.pkg_name]@
  // convert primitive array elements
  std::copy(
    ros1_msg.@(ros1_field.name).begin(),
    ros1_msg.@(ros1_field.name).end(),
    ros2_msg.@(ros2_field.name).begin());
@[      else]@
  // copy element wise since the type is different
  {
    auto ros1_it = ros1_msg.@(ros1_field.name).begin();
    auto ros2_it = ros2_msg.@(ros2_field.name).begin();
    for (
      ;
      ros1_it != ros1_msg.@(ros1_field.name).end() &&
      ros2_it != ros2_msg.@(ros2_field.name).end();
      ++ros1_it, ++ros2_it
    )
    {
      // convert sub message element
@[        if ros2_field.type.pkg_name == 'builtin_interfaces']@
      ros1_bridge::convert_1_to_2(*ros1_it, *ros2_it);
@[        else]@
      Factory<
        @(ros1_field.pkg_name)::@(ros1_field.msg_name),
        @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
      >::convert_1_to_2(
        *ros1_it, *ros2_it);
@[        end if]@
    }
  }
@[      end if]@
@[    end if]@
@[  end for]@
}

template<>
void
Factory<
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
>::convert_2_to_1(
  const @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name) & ros2_msg,
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name) & ros1_msg)
{
@[  if not m.fields_2_to_1]@
  (void)ros2_msg;
  (void)ros1_msg;
@[  end if]@
@[  for ros2_field, ros1_field in m.fields_2_to_1.items()]@
@[    if not ros2_field.type.is_array]@
  // convert non-array field
@[      if not ros2_field.type.pkg_name]@
  // convert primitive field
  ros1_msg.@(ros1_field.name) = ros2_msg.@(ros2_field.name);
@[      elif ros2_field.type.pkg_name == 'builtin_interfaces']@
  // convert builtin field
  ros1_bridge::convert_2_to_1(ros2_msg.@(ros2_field.name), ros1_msg.@(ros1_field.name));
@[      else]@
  // convert sub message field
  Factory<
    @(ros1_field.pkg_name)::@(ros1_field.msg_name),
    @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
  >::convert_2_to_1(
    ros2_msg.@(ros2_field.name), ros1_msg.@(ros1_field.name));
@[      end if]@
@[    else]@
  // convert array field
@[      if not ros2_field.type.array_size or ros2_field.type.is_upper_bound]@
  // ensure array size
  // dynamic arrays must be resized
  ros1_msg.@(ros1_field.name).resize(ros2_msg.@(ros2_field.name).size());
@[      end if]@
@[      if not ros2_field.type.pkg_name]@
  // convert primitive array elements
  std::copy(
    ros2_msg.@(ros2_field.name).begin(),
    ros2_msg.@(ros2_field.name).end(),
    ros1_msg.@(ros1_field.name).begin());
@[      else]@
  // copy element wise since the type is different
  {
    auto ros2_it = ros2_msg.@(ros2_field.name).begin();
    auto ros1_it = ros1_msg.@(ros1_field.name).begin();
    for (
      ;
      ros2_it != ros2_msg.@(ros2_field.name).end() &&
      ros1_it != ros1_msg.@(ros1_field.name).end();
      ++ros2_it, ++ros1_it
    )
    {
      // convert sub message element
@[        if ros2_field.type.pkg_name == 'builtin_interfaces']@
      ros1_bridge::convert_2_to_1(*ros2_it, *ros1_it);
@[        else]@
      Factory<
        @(ros1_field.pkg_name)::@(ros1_field.msg_name),
        @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
      >::convert_2_to_1(
        *ros2_it, *ros1_it);
@[        end if]@
    }
  }
@[      end if]@
@[    end if]@
@[  end for]@
}

@[end for]@
}  // namespace ros1_bridge

// generated from ros1_bridge/resource/generated_factories.cpp.em

@###############################################
@#
@# Factory for creating publisher / subscribers
@# based on message names
@#
@# EmPy template for generating generated_factories.cpp
@#
@###############################################
@# Start of Template
@#
@# Context:
@#  - ros1_msgs (list of ros1_bridge.Message)
@#    ROS 1 messages
@#  - ros2_msgs (list of ros1_bridge.Message)
@#    ROS 2 messages
@#  - mappings (list of ros1_bridge.Mapping)
@#    Mapping between messages as well as their fields
@###############################################
@
@{
from ros1_bridge import camel_case_to_lower_case_underscore
}@
#include <ros1_bridge/factory.hpp>

// include ROS 1 builtin messages
#include <ros/duration.h>
#include <ros/time.h>

// include ROS 2 builtin messages
#include <builtin_interfaces/msg/duration.hpp>
#include <builtin_interfaces/msg/time.hpp>

// include ROS 1 messages
@[for ros1_msg in ros1_msgs]@
#include <@(ros1_msg.package_name)/@(ros1_msg.message_name).h>
@[end for]@

// include ROS 2 messages
@[for ros2_msg in ros2_msgs]@
#include <@(ros2_msg.package_name)/msg/@(camel_case_to_lower_case_underscore(ros2_msg.message_name)).hpp>
@[end for]@

namespace ros1_bridge
{

std::shared_ptr<FactoryInterface>
get_factory(const std::string & ros1_type_name, const std::string & ros2_type_name)
{
@[if not mappings]@
  (void)ros1_type_name;
  (void)ros2_type_name;
@[end if]@
  // mapping from string to specialized template
@[for m in mappings]@
  if (
    (ros1_type_name == "@(m.ros1_msg.package_name)/@(m.ros1_msg.message_name)" ||
     ros1_type_name == "") &&
    ros2_type_name == "@(m.ros2_msg.package_name)/@(m.ros2_msg.message_name)")
  {
    return std::make_shared<
      Factory<
        @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
        @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
      >
    >();
  }
@[end for]@
  throw std::runtime_error("No template specialization for the pair");
}

// conversion functions for builtin interfaces

template<typename ROS1_T, typename ROS2_T>
void
convert_1_to_2(
  const ROS1_T & ros1_msg,
  ROS2_T & ros2_msg);

template<typename ROS1_T, typename ROS2_T>
void
convert_2_to_1(
  const ROS2_T & ros2_msg,
  ROS1_T & ros1_msg);

template<>
void
convert_1_to_2(
  const ros::Duration & ros1_msg,
  builtin_interfaces::msg::Duration & ros2_msg)
{
  ros2_msg.sec = ros1_msg.sec;
  ros2_msg.nanosec = ros1_msg.nsec;
}

template<>
void
convert_2_to_1(
  const builtin_interfaces::msg::Duration & ros2_msg,
  ros::Duration & ros1_msg)
{
  ros1_msg.sec = ros2_msg.sec;
  ros1_msg.nsec = ros2_msg.nanosec;
}

template<>
void
convert_1_to_2(
  const ros::Time & ros1_msg,
  builtin_interfaces::msg::Time & ros2_msg)
{
  ros2_msg.sec = ros1_msg.sec;
  ros2_msg.nanosec = ros1_msg.nsec;
}

template<>
void
convert_2_to_1(
  const builtin_interfaces::msg::Time & ros2_msg,
  ros::Time & ros1_msg)
{
  ros1_msg.sec = ros2_msg.sec;
  ros1_msg.nsec = ros2_msg.nanosec;
}

// conversion functions for available interfaces
@[for m in mappings]@

template<>
void
Factory<
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
>::convert_1_to_2(
  const @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name) & ros1_msg,
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name) & ros2_msg)
{
@[  if not m.fields_1_to_2]@
  (void)ros1_msg;
  (void)ros2_msg;
@[  end if]@
@[  for ros1_field, ros2_field in m.fields_1_to_2.items()]@
@[    if not ros2_field.type.is_array]@
  # convert non-array field
@[      if not ros2_field.type.pkg_name]@
  # convert primitive field
  ros2_msg.@(ros2_field.name) = ros1_msg.@(ros1_field.name);
@[      elif ros2_field.type.pkg_name == 'builtin_interfaces']@
  # convert builtin field
  ros1_bridge::convert_1_to_2(ros1_msg.@(ros1_field.name), ros2_msg.@(ros2_field.name));
@[      else]@
  # convert sub message field
  Factory<
    @(ros1_field.pkg_name)::@(ros1_field.msg_name),
    @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
  >::convert_1_to_2(
    ros1_msg.@(ros1_field.name), ros2_msg.@(ros2_field.name));
@[      end if]@
@[    else]@
  # convert array field
@[      if not ros2_field.type.array_size or ros2_field.type.is_upper_bound]@
  # ensure array size
@[        if ros2_field.type.is_upper_bound]@
  # check boundary
  assert(ros1_msg.@(ros1_field.name).size() <= @(ros2_field.type.array_size));
@[        end if]@
  # dynamic arrays must be resized
  ros2_msg.@(ros2_field.name).resize(ros1_msg.@(ros1_field.name).size());
@[      end if]@
@[      if not ros2_field.type.pkg_name]@
  # convert primitive array elements
  std::copy(
    ros1_msg.@(ros1_field.name).begin(),
    ros1_msg.@(ros1_field.name).end(),
    ros2_msg.@(ros2_field.name).begin());
@[      else]@
  # copy element wise since the type is different
  {
    auto ros1_it = ros1_msg.@(ros1_field.name).begin();
    auto ros2_it = ros2_msg.@(ros2_field.name).begin();
    for (
      ;
      ros1_it != ros1_msg.@(ros1_field.name).end() &&
      ros2_it != ros2_msg.@(ros2_field.name).end();
      ++ros1_it, ++ros2_it
    )
    {
      # convert sub message element
@[        if ros2_field.type.pkg_name == 'builtin_interfaces']@
      ros1_bridge::convert_1_to_2(*ros1_it, *ros2_it);
@[        else]@
      Factory<
        @(ros1_field.pkg_name)::@(ros1_field.msg_name),
        @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
      >::convert_1_to_2(
        *ros1_it, *ros2_it);
@[        end if]@
    }
  }
@[      end if]@
@[    end if]@
@[  end for]@
}

template<>
void
Factory<
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
>::convert_2_to_1(
  const @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name) & ros2_msg,
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name) & ros1_msg)
{
@[  if not m.fields_2_to_1]@
  (void)ros2_msg;
  (void)ros1_msg;
@[  end if]@
@[  for ros2_field, ros1_field in m.fields_2_to_1.items()]@
@[    if not ros2_field.type.is_array]@
  # convert non-array field
@[      if not ros2_field.type.pkg_name]@
  # convert primitive field
  ros1_msg.@(ros1_field.name) = ros2_msg.@(ros2_field.name);
@[      elif ros2_field.type.pkg_name == 'builtin_interfaces']@
  # convert builtin field
  ros1_bridge::convert_2_to_1(ros2_msg.@(ros2_field.name), ros1_msg.@(ros1_field.name));
@[      else]@
  # convert sub message field
  Factory<
    @(ros1_field.pkg_name)::@(ros1_field.msg_name),
    @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
  >::convert_2_to_1(
    ros2_msg.@(ros2_field.name), ros1_msg.@(ros1_field.name));
@[      end if]@
@[    else]@
  # convert array field
@[      if not ros2_field.type.array_size or ros2_field.type.is_upper_bound]@
  # ensure array size
  # dynamic arrays must be resized
  ros1_msg.@(ros1_field.name).resize(ros2_msg.@(ros2_field.name).size());
@[      end if]@
@[      if not ros2_field.type.pkg_name]@
  # convert primitive array elements
  std::copy(
    ros2_msg.@(ros2_field.name).begin(),
    ros2_msg.@(ros2_field.name).end(),
    ros1_msg.@(ros1_field.name).begin());
@[      else]@
  # copy element wise since the type is different
  {
    auto ros2_it = ros2_msg.@(ros2_field.name).begin();
    auto ros1_it = ros1_msg.@(ros1_field.name).begin();
    for (
      ;
      ros2_it != ros2_msg.@(ros2_field.name).end() &&
      ros1_it != ros1_msg.@(ros1_field.name).end();
      ++ros2_it, ++ros1_it
    )
    {
      # convert sub message element
@[        if ros2_field.type.pkg_name == 'builtin_interfaces']@
      ros1_bridge::convert_2_to_1(*ros2_it, *ros1_it);
@[        else]@
      Factory<
        @(ros1_field.pkg_name)::@(ros1_field.msg_name),
        @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
      >::convert_2_to_1(
        *ros2_it, *ros1_it);
@[        end if]@
    }
  }
@[      end if]@
@[    end if]@
@[  end for]@
}

@[end for]@
}  // namespace ros1_bridge


group job names and configs in chunks of 1000 to not exceed groovy limits

import difflib.DiffUtils
import java.io.StringBufferInputStream
import java.io.StringWriter
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.stream.StreamSource
import jenkins.model.Jenkins
import org.apache.xml.serialize.OutputFormat
import org.apache.xml.serialize.XMLSerializer

// job types with their prefix and a list of job names
// used to remove obsolete jobs with the same prefix which are not part of the list
job_prefixes_and_names = [:]
@[for job_type in sorted(job_prefixes_and_names.keys())]@
job_prefixes_and_names['@job_type'] = [
    'job_prefix': '@(job_prefixes_and_names[job_type][0])',
    'job_names': [],
]
@{
job_names = sorted(job_prefixes_and_names[job_type][1])
group_size = 1000
}@
// group job names in chunks of @group_size to not exceed groovy limits
@[for i in range(0, len(job_names), group_size)]@
def add_job_prefixes_and_names_@(job_type)_@(int(i / group_size) + 1)(job_names) {
@[for j in range(i, min(i + group_size, len(job_names)))]@
job_names << '@(job_names[j])'
@[end for]@
}
add_job_prefixes_and_names_@(job_type)_@(int(i / group_size) + 1)(job_prefixes_and_names['@job_type'].job_names)
@[end for]@
@[end for]@

// job configurations
job_configs = [:]
@{
job_config_keys = sorted(job_configs.keys())
group_size = 1000
}@
// group job configs in chunks of @group_size to not exceed groovy limits
@[for i in range(0, len(job_config_keys), group_size)]@
def add_job_config_@(int(i / group_size) + 1)(job_configs) {
@[for j in range(i, min(i + group_size, len(job_config_keys)))]@
job_configs['@job_config_keys[j]'] = '''@(job_configs[job_config_keys[j]].replace('\\', '\\\\'))'''

@[end for]@
}
add_job_config_@(int(i / group_size) + 1)(job_configs)

@[end for]@

def diff_configs(current_config_file, new_config) {

    factory = DocumentBuilderFactory.newInstance()
    builder = factory.newDocumentBuilder()

    current_doc = builder.parse(current_config_file.getFile())

    new_config_stream = new StringBufferInputStream(new_config)
    new_doc = builder.parse(new_config_stream)

    // ignore description which contains a timestamp
    if (current_doc.getElementsByTagName('description')) {
        current_doc.getElementsByTagName('description').item(0).setTextContent('')
    }
    if (new_doc.getElementsByTagName('description')) {
        new_doc.getElementsByTagName('description').item(0).setTextContent('')
    }

    current_string = format_xml(current_doc)
    new_string = format_xml(new_doc)

    if (current_string == new_string) {
        return []
    }

    current_lines = []
    current_string.eachLine { line, count ->
        current_lines << line
    }
    new_lines = []
    new_string.eachLine { line, count ->
        new_lines << line
    }

    patch = DiffUtils.diff(current_lines, new_lines)
    return DiffUtils.generateUnifiedDiff('current config', 'new config', current_lines, patch, 0)
}

def format_xml(doc) {
    format = new OutputFormat(doc)
    format.setIndenting(true)
    format.setIndent(2)
    writer = new StringWriter()
    serializer = new XMLSerializer(writer, format)
    serializer.serialize(doc)
    return writer.toString()
}

// reconfigure jobs
println '# BEGIN SECTION: Groovy script - reconfigure jobs'
println 'Reconfiguring ' + job_configs.size() + ' jobs...'
reconfigured = 0
skipped = 0
for (item in job_configs) {
    job_name = item.key
    job_config = item.value
    for (p in Jenkins.instance.allItems) {
        if (p.name != job_name) continue
        job_config_file = p.getConfigFile()

        diff = diff_configs(job_config_file, job_config)
        if (!diff) {
            println "Skipped '" + job_name + "' because the config is the same"
            skipped += 1
        } else {
            println "Updating job '" + job_name + "'"
            println '    <<<'
            for (line in diff) {
                println '    ' + line
            }
            println '    <<<'

            reader = new StringReader(job_config)
            source = new StreamSource(reader)
            p.updateByXml(source)
            reconfigured += 1
        }
        break
    }
}
println 'Reconfigured ' + reconfigured + ' jobs, skipped ' + skipped + ' jobs.'
println '# END SECTION'

// delete obsolete jobs
for (item in job_prefixes_and_names) {
    job_type = item.key
    job_prefix = item.value.job_prefix
    job_names = item.value.job_names
    deleted = 0
    println "# BEGIN SECTION: Groovy script - delete obsolete '" + job_type + "' jobs"
    println "Searching for obsolete jobs starting with '" + job_prefix + "'"
    for (p in Jenkins.instance.allItems) {
        if (!p.name.startsWith(job_prefix)) continue
        if (p.name in job_names) continue
        println "Deleting job '" + p.name + "'"
        p.delete()
        deleted += 1
    }
    println 'Deleted ' + deleted + ' jobs.'
    println '# END SECTION'
}

import difflib.DiffUtils
import java.io.StringBufferInputStream
import java.io.StringWriter
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.stream.StreamSource
import jenkins.model.Jenkins
import org.apache.xml.serialize.OutputFormat
import org.apache.xml.serialize.XMLSerializer

// job types with their prefix and a list of job names
// used to remove obsolete jobs with the same prefix which are not part of the list
job_prefixes_and_names = [:]
@[for job_type in sorted(job_prefixes_and_names.keys())]@
job_prefixes_and_names['@job_type'] = [
    'job_prefix': '@(job_prefixes_and_names[job_type][0])',
    'job_names': [],
]
@[for job_name in sorted(job_prefixes_and_names[job_type][1])]@
job_prefixes_and_names['@job_type'].job_names << '@job_name'
@[end for]@

@[end for]@

// job configurations
job_configs = [:]
@[for job_name in sorted(job_configs.keys())]@
job_configs['@job_name'] = '''@job_configs[job_name]'''
@[end for]@

def diff_configs(current_config_file, new_config) {

    factory = DocumentBuilderFactory.newInstance()
    builder = factory.newDocumentBuilder()

    current_doc = builder.parse(current_config_file.getFile())

    new_config_stream = new StringBufferInputStream(new_config)
    new_doc = builder.parse(new_config_stream)

    // ignore description which contains a timestamp
    if (current_doc.getElementsByTagName('description')) {
        current_doc.getElementsByTagName('description').item(0).setTextContent('')
    }
    if (new_doc.getElementsByTagName('description')) {
        new_doc.getElementsByTagName('description').item(0).setTextContent('')
    }

    current_string = format_xml(current_doc)
    new_string = format_xml(new_doc)

    if (current_string == new_string) {
        return []
    }

    current_lines = []
    current_string.eachLine { line, count ->
        current_lines << line
    }
    new_lines = []
    new_string.eachLine { line, count ->
        new_lines << line
    }

    patch = DiffUtils.diff(current_lines, new_lines)
    return DiffUtils.generateUnifiedDiff('current config', 'new config', current_lines, patch, 0)
}

def format_xml(doc) {
    format = new OutputFormat(doc)
    format.setIndenting(true)
    format.setIndent(2)
    writer = new StringWriter()
    serializer = new XMLSerializer(writer, format)
    serializer.serialize(doc)
    return writer.toString()
}

// reconfigure jobs
println '# BEGIN SECTION: Groovy script - reconfigure jobs'
println 'Reconfiguring ' + job_configs.size() + ' jobs...'
reconfigured = 0
skipped = 0
for (item in job_configs) {
    job_name = item.key
    job_config = item.value
    for (p in Jenkins.instance.allItems) {
        if (p.name != job_name) continue
        job_config_file = p.getConfigFile()

        diff = diff_configs(job_config_file, job_config)
        if (!diff) {
            println "Skipped '" + job_name + "' because the config is the same"
            skipped += 1
        } else {
            println "Updating job '" + job_name + "'"
            println '    <<<'
            for (line in diff) {
                println '    ' + line
            }
            println '    <<<'

            reader = new StringReader(job_config)
            source = new StreamSource(reader)
            p.updateByXml(source)
            reconfigured += 1
        }
        break
    }
}
println 'Reconfigured ' + reconfigured + ' jobs, skipped ' + skipped + ' jobs.'
println '# END SECTION'

// delete obsolete jobs
for (item in job_prefixes_and_names) {
    job_type = item.key
    job_prefix = item.value.job_prefix
    job_names = item.value.job_names
    deleted = 0
    println "# BEGIN SECTION: Groovy script - delete obsolete '" + job_type + "' jobs"
    println "Searching for obsolete jobs starting with '" + job_prefix + "'"
    for (p in Jenkins.instance.allItems) {
        if (!p.name.startsWith(job_prefix)) continue
        if (p.name in job_names) continue
        println "Deleting job '" + p.name + "'"
        p.delete()
        deleted += 1
    }
    println 'Deleted ' + deleted + ' jobs.'
    println '# END SECTION'
}


temporary hack to keep logs on Windows (#242)

<?xml version='1.0' encoding='UTF-8'?>
<project>
  <actions/>
  <description></description>
  <keepDependencies>false</keepDependencies>
  <properties>
    <com.coravy.hudson.plugins.github.GithubProjectProperty plugin="github@@1.25.1">
      <projectUrl>@(ci_scripts_repository)/</projectUrl>
      <displayName />
    </com.coravy.hudson.plugins.github.GithubProjectProperty>
    <com.sonyericsson.rebuild.RebuildSettings plugin="rebuild@@1.25">
      <autoRebuild>false</autoRebuild>
      <rebuildDisabled>false</rebuildDisabled>
    </com.sonyericsson.rebuild.RebuildSettings>
    <org.jenkinsci.plugins.requeuejob.RequeueJobProperty plugin="jobrequeue@@1.1">
      <requeueJob>true</requeueJob>
    </org.jenkinsci.plugins.requeuejob.RequeueJobProperty>
@(SNIPPET(
    'property_parameter-definition',
    ci_scripts_default_branch=ci_scripts_default_branch,
    default_repos_url=default_repos_url,
    supplemental_repos_url=supplemental_repos_url,
    ignore_rmw_default=ignore_rmw_default,
    use_connext_debs_default=use_connext_debs_default,
    use_isolated_default=use_isolated_default,
    ubuntu_distro=ubuntu_distro,
    cmake_build_type=cmake_build_type,
    build_args_default=build_args_default,
    test_args_default=test_args_default,
    enable_c_coverage_default=enable_c_coverage_default,
))@
  </properties>
  <scm class="hudson.plugins.git.GitSCM" plugin="git@@3.0.1">
    <configVersion>2</configVersion>
    <userRemoteConfigs>
      <hudson.plugins.git.UserRemoteConfig>
        <url>@(ci_scripts_repository)</url>
        <credentialsId>1c2004f6-2e00-425d-a421-2e1ba62ca7a7</credentialsId>
      </hudson.plugins.git.UserRemoteConfig>
    </userRemoteConfigs>
    <branches>
      <hudson.plugins.git.BranchSpec>
        <name>refs/heads/${CI_SCRIPTS_BRANCH}</name>
      </hudson.plugins.git.BranchSpec>
    </branches>
    <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
    <browser class="hudson.plugins.git.browser.GithubWeb">
      <url></url>
    </browser>
    <submoduleCfg class="list"/>
    <extensions>@
@[if os_name != 'windows']
      <hudson.plugins.git.extensions.impl.SubmoduleOption>
        <disableSubmodules>false</disableSubmodules>
        <recursiveSubmodules>true</recursiveSubmodules>
        <trackingSubmodules>false</trackingSubmodules>
        <reference/>
        <parentCredentials>false</parentCredentials>
      </hudson.plugins.git.extensions.impl.SubmoduleOption>
    @
@[end if]</extensions>
  </scm>
  <assignedNode>@(label_expression)</assignedNode>
  <canRoam>false</canRoam>
  <disabled>false</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers>@
@[if time_trigger_spec]
    <hudson.triggers.TimerTrigger>
      <spec>@(time_trigger_spec)</spec>
    </hudson.triggers.TimerTrigger>
  @
@[end if]</triggers>
  <concurrentBuild>true</concurrentBuild>
  <builders>
    <hudson.plugins.groovy.SystemGroovy plugin="groovy@@2.0">
      <source class="hudson.plugins.groovy.StringSystemScriptSource">

          <sandbox>false</sandbox>
        </script>
      </source>
    </hudson.plugins.groovy.SystemGroovy>
    <hudson.tasks.@(shell_type)>
      <command>@
@[if os_name in ['linux', 'osx', 'linux-aarch64']]@
rm -rf ws workspace "work space"

echo "# BEGIN SECTION: Determine arguments"
export CI_ARGS="--do-venv --force-ansi-color --workspace-path $WORKSPACE"
if [ -n "${CI_BRANCH_TO_TEST+x}" ]; then
  export CI_ARGS="$CI_ARGS --test-branch $CI_BRANCH_TO_TEST"
fi
if [ -n "${CI_COLCON_BRANCH+x}" ]; then
  export CI_ARGS="$CI_ARGS --colcon-branch $CI_COLCON_BRANCH"
fi
if [ "$CI_USE_WHITESPACE_IN_PATHS" = "true" ]; then
  export CI_ARGS="$CI_ARGS --white-space-in sourcespace buildspace installspace workspace"
fi
export CI_ARGS="$CI_ARGS --ignore-rmw"
if [ "$CI_USE_CONNEXT_STATIC" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_connext_cpp"
fi
if [ "$CI_USE_CONNEXT_DYNAMIC" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_connext_dynamic_cpp"
fi
if [ "$CI_USE_FASTRTPS_STATIC" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_fastrtps_cpp"
fi
if [ "$CI_USE_FASTRTPS_DYNAMIC" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_fastrtps_dynamic_cpp"
fi
if [ "$CI_USE_OPENSPLICE" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_opensplice_cpp"
fi
if [ "$CI_USE_CONNEXT_DEBS" = "true" ]; then
  export CI_ARGS="$CI_ARGS --connext-debs"
  export DOCKER_BUILD_ARGS="$DOCKER_BUILD_ARGS --build-arg INSTALL_CONNEXT_DEBS=$CI_USE_CONNEXT_DEBS"
fi
if [ -z "${CI_ROS2_REPOS_URL+x}" ]; then
  CI_ROS2_REPOS_URL="@default_repos_url"
fi
export CI_ARGS="$CI_ARGS --repo-file-url $CI_ROS2_REPOS_URL"
if [ -n "${CI_ROS2_SUPPLEMENTAL_REPOS_URL+x}" ]; then
  export CI_ARGS="$CI_ARGS --supplemental-repo-file-url $CI_ROS2_SUPPLEMENTAL_REPOS_URL"
fi
if [ "$CI_ISOLATED" = "true" ]; then
  export CI_ARGS="$CI_ARGS --isolated"
fi
if [ "${CI_UBUNTU_DISTRO}" = "bionic" ]; then
  export CI_ROS1_DISTRO=melodic
elif [ "${CI_UBUNTU_DISTRO}" = "xenial" ]; then
  export CI_ROS1_DISTRO=kinetic
fi
if [ "${CI_CMAKE_BUILD_TYPE}" != "None" ]; then
  export CI_ARGS="$CI_ARGS --cmake-build-type $CI_CMAKE_BUILD_TYPE"
fi
if [ "$CI_ENABLE_C_COVERAGE" = "true" ]; then
  export CI_ARGS="$CI_ARGS --coverage"
fi
@[  if os_name in ['linux', 'linux-aarch64'] and turtlebot_demo]@
export CI_ARGS="$CI_ARGS --ros1-path /opt/ros/$CI_ROS1_DISTRO"
@[  end if]@
if [ -n "${CI_BUILD_ARGS+x}" ]; then
  export CI_ARGS="$CI_ARGS --build-args $CI_BUILD_ARGS"
fi
if [ -n "${CI_TEST_ARGS+x}" ]; then
  export CI_ARGS="$CI_ARGS --test-args $CI_TEST_ARGS"
fi
echo "Using args: $CI_ARGS"
echo "# END SECTION"

@[  if os_name in ['linux', 'linux-aarch64']]@
sed -i "s+^FROM.*$+FROM ubuntu:$CI_UBUNTU_DISTRO+" linux_docker_resources/Dockerfile
export DOCKER_BUILD_ARGS="${DOCKER_BUILD_ARGS} --build-arg UBUNTU_DISTRO=$CI_UBUNTU_DISTRO --build-arg ROS1_DISTRO=$CI_ROS1_DISTRO"

mkdir -p $HOME/.ccache
echo "# BEGIN SECTION: docker version"
docker version
echo "# END SECTION"
echo "# BEGIN SECTION: docker info"
docker info
echo "# END SECTION"
echo "# BEGIN SECTION: Inject date into Dockerfile"
sed -i "s/@@today_str/`date +%Y-%m-%d`/" linux_docker_resources/Dockerfile
echo "# END SECTION"
echo "# BEGIN SECTION: Build Dockerfile"
@[    if os_name == 'linux-aarch64']@
@[      if turtlebot_demo]@
docker build ${DOCKER_BUILD_ARGS} --build-arg PLATFORM=arm --build-arg INSTALL_TURTLEBOT2_DEMO_DEPS=true -t ros2_batch_ci_turtlebot_demo linux_docker_resources
@[      else]@
docker build ${DOCKER_BUILD_ARGS} --build-arg PLATFORM=arm -t ros2_batch_ci_aarch64 linux_docker_resources
@[      end if]@
@[    elif os_name == 'linux']@
@[      if turtlebot_demo]@
docker build ${DOCKER_BUILD_ARGS} --build-arg INSTALL_TURTLEBOT2_DEMO_DEPS=true -t ros2_batch_ci_turtlebot_demo linux_docker_resources
@[      else]@
docker build ${DOCKER_BUILD_ARGS} -t ros2_batch_ci linux_docker_resources
@[      end if]@
@[    else]@
@{ assert False, 'Unknown os_name: ' + os_name }@
@[    end if]@
echo "# END SECTION"
echo "# BEGIN SECTION: Run Dockerfile"
@[    if turtlebot_demo]@
export CONTAINER_NAME=ros2_batch_ci_turtlebot_demo
@[    elif os_name == 'linux']@
export CONTAINER_NAME=ros2_batch_ci
@[    elif os_name == 'linux-aarch64']@
export CONTAINER_NAME=ros2_batch_ci_aarch64
@[    else]@
@{ assert False, 'Unknown os_name: ' + os_name }@
@[    end if]@
# Create a network that prevents docker containers on the same host from communicating.
# This prevents cross-talk between builds running in parallel on different executors on a single host.
# It may have already been created.
docker network create -o com.docker.network.bridge.enable_icc=false isolated_network || true
docker run --rm --net=isolated_network --privileged -e UID=`id -u` -e GID=`id -g` -e CI_ARGS="$CI_ARGS" -e CCACHE_DIR=/home/rosbuild/.ccache -i -v `pwd`:/home/rosbuild/ci_scripts -v $HOME/.ccache:/home/rosbuild/.ccache $CONTAINER_NAME
echo "# END SECTION"
@[  else]@
echo "# BEGIN SECTION: Run script"
/usr/local/bin/python3 -u run_ros2_batch.py $CI_ARGS
echo "# END SECTION"
@[  end if]@
@[elif os_name == 'windows']@
setlocal enableDelayedExpansion
REM rmdir /S /Q ws workspace "work space"
rmdir /S /Q ws/build ws/install ws/src ws/*.repos ws/env.bat

echo "# BEGIN SECTION: Determine arguments"
set "PATH=!PATH:"=!"
set "CI_ARGS=--force-ansi-color --workspace-path !WORKSPACE!"
if "!CI_BRANCH_TO_TEST!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --test-branch !CI_BRANCH_TO_TEST!"
)
if "!CI_COLCON_BRANCH!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --colcon-branch !CI_COLCON_BRANCH!"
)
if "!CI_USE_WHITESPACE_IN_PATHS!" == "true" (
  set "CI_ARGS=!CI_ARGS! --white-space-in sourcespace buildspace installspace workspace"
)
set "CI_ARGS=!CI_ARGS! --ignore-rmw"
if "!CI_USE_CONNEXT_STATIC!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_connext_cpp"
)
if "!CI_USE_CONNEXT_DYNAMIC!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_connext_dynamic_cpp"
)
if "!CI_USE_FASTRTPS_STATIC!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_fastrtps_cpp"
)
if "!CI_USE_FASTRTPS_DYNAMIC!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_fastrtps_dynamic_cpp"
)
if "!CI_USE_OPENSPLICE!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_opensplice_cpp"
)
if "!CI_USE_CONNEXT_DEBS!" == "true" (
  set "CI_ARGS=!CI_ARGS! --connext-debs"
)
if "!CI_ROS2_REPOS_URL!" EQU "" (
  set "CI_ROS2_REPOS_URL=@default_repos_url"
)
set "CI_ARGS=!CI_ARGS! --repo-file-url !CI_ROS2_REPOS_URL!"
if "!CI_ROS2_SUPPLEMENTAL_REPOS_URL!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --supplemental-repo-file-url !CI_ROS2_SUPPLEMENTAL_REPOS_URL!"
)
if "!CI_ISOLATED!" == "true" (
  set "CI_ARGS=!CI_ARGS! --isolated"
)
if "!CI_CMAKE_BUILD_TYPE!" NEQ "None" (
  set "CI_ARGS=!CI_ARGS! --cmake-build-type !CI_CMAKE_BUILD_TYPE!"
)
if "!CI_CMAKE_BUILD_TYPE!" == "Debug" (
  where python_d > python_debug_interpreter.txt
  set /p PYTHON_DEBUG_INTERPRETER=<python_debug_interpreter.txt
  set "CI_ARGS=!CI_ARGS! --python-interpreter !PYTHON_DEBUG_INTERPRETER!"
)
if "!CI_ENABLE_C_COVERAGE!" == "true" (
  set "CI_ARGS=!CI_ARGS! --coverage"
)
if "!CI_BUILD_ARGS!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --build-args !CI_BUILD_ARGS!"
)
if "!CI_TEST_ARGS!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --test-args !CI_TEST_ARGS!"
)
echo Using args: !CI_ARGS!
echo "# END SECTION"

echo "# BEGIN SECTION: Run script"
python -u run_ros2_batch.py !CI_ARGS!
echo "# END SECTION"
@[else]@
@{ assert False, 'Unknown os_name: ' + os_name }@
@[end if]</command>
    </hudson.tasks.@(shell_type)>
  </builders>
  <publishers>
@(SNIPPET(
    'publisher_warnings',
    os_name=os_name,
))@
@(SNIPPET(
    'publisher_cobertura',
))@
@(SNIPPET(
    'publisher_xunit',
))@
@[if mailer_recipients]@
    <hudson.tasks.Mailer plugin="mailer@@1.20">
      <recipients>@(mailer_recipients)</recipients>
      <dontNotifyEveryUnstableBuild>@(dont_notify_every_unstable_build)</dontNotifyEveryUnstableBuild>
      <sendToIndividuals>false</sendToIndividuals>
    </hudson.tasks.Mailer>
@[end if]@
  </publishers>
  <buildWrappers>
@[if build_timeout_mins]@
    <hudson.plugins.build__timeout.BuildTimeoutWrapper plugin="build-timeout@@1.18">
      <strategy class="hudson.plugins.build_timeout.impl.AbsoluteTimeOutStrategy">
        <timeoutMinutes>@(build_timeout_mins)</timeoutMinutes>
      </strategy>
      <operationList>
        <hudson.plugins.build__timeout.operations.AbortOperation />
      </operationList>
    </hudson.plugins.build__timeout.BuildTimeoutWrapper>
@[end if]@
    <hudson.plugins.timestamper.TimestamperBuildWrapper plugin="timestamper@@1.8.8" />
    <hudson.plugins.ansicolor.AnsiColorBuildWrapper plugin="ansicolor@@0.5.0">
      <colorMapName>xterm</colorMapName>
    </hudson.plugins.ansicolor.AnsiColorBuildWrapper>
@[if os_name != 'windows']@
    <com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper plugin="ssh-agent@@1.15">
      <credentialIds>
        <string>1c2004f6-2e00-425d-a421-2e1ba62ca7a7</string>
      </credentialIds>
      <ignoreMissing>false</ignoreMissing>
    </com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper>
@[end if]@
  </buildWrappers>
</project>

<?xml version='1.0' encoding='UTF-8'?>
<project>
  <actions/>
  <description></description>
  <keepDependencies>false</keepDependencies>
  <properties>
    <com.coravy.hudson.plugins.github.GithubProjectProperty plugin="github@@1.25.1">
      <projectUrl>@(ci_scripts_repository)/</projectUrl>
      <displayName />
    </com.coravy.hudson.plugins.github.GithubProjectProperty>
    <com.sonyericsson.rebuild.RebuildSettings plugin="rebuild@@1.25">
      <autoRebuild>false</autoRebuild>
      <rebuildDisabled>false</rebuildDisabled>
    </com.sonyericsson.rebuild.RebuildSettings>
    <org.jenkinsci.plugins.requeuejob.RequeueJobProperty plugin="jobrequeue@@1.1">
      <requeueJob>true</requeueJob>
    </org.jenkinsci.plugins.requeuejob.RequeueJobProperty>
@(SNIPPET(
    'property_parameter-definition',
    ci_scripts_default_branch=ci_scripts_default_branch,
    default_repos_url=default_repos_url,
    supplemental_repos_url=supplemental_repos_url,
    ignore_rmw_default=ignore_rmw_default,
    use_connext_debs_default=use_connext_debs_default,
    use_isolated_default=use_isolated_default,
    ubuntu_distro=ubuntu_distro,
    cmake_build_type=cmake_build_type,
    build_args_default=build_args_default,
    test_args_default=test_args_default,
    enable_c_coverage_default=enable_c_coverage_default,
))@
  </properties>
  <scm class="hudson.plugins.git.GitSCM" plugin="git@@3.0.1">
    <configVersion>2</configVersion>
    <userRemoteConfigs>
      <hudson.plugins.git.UserRemoteConfig>
        <url>@(ci_scripts_repository)</url>
        <credentialsId>1c2004f6-2e00-425d-a421-2e1ba62ca7a7</credentialsId>
      </hudson.plugins.git.UserRemoteConfig>
    </userRemoteConfigs>
    <branches>
      <hudson.plugins.git.BranchSpec>
        <name>refs/heads/${CI_SCRIPTS_BRANCH}</name>
      </hudson.plugins.git.BranchSpec>
    </branches>
    <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
    <browser class="hudson.plugins.git.browser.GithubWeb">
      <url></url>
    </browser>
    <submoduleCfg class="list"/>
    <extensions>@
@[if os_name != 'windows']
      <hudson.plugins.git.extensions.impl.SubmoduleOption>
        <disableSubmodules>false</disableSubmodules>
        <recursiveSubmodules>true</recursiveSubmodules>
        <trackingSubmodules>false</trackingSubmodules>
        <reference/>
        <parentCredentials>false</parentCredentials>
      </hudson.plugins.git.extensions.impl.SubmoduleOption>
    @
@[end if]</extensions>
  </scm>
  <assignedNode>@(label_expression)</assignedNode>
  <canRoam>false</canRoam>
  <disabled>false</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers>@
@[if time_trigger_spec]
    <hudson.triggers.TimerTrigger>
      <spec>@(time_trigger_spec)</spec>
    </hudson.triggers.TimerTrigger>
  @
@[end if]</triggers>
  <concurrentBuild>true</concurrentBuild>
  <builders>
    <hudson.plugins.groovy.SystemGroovy plugin="groovy@@2.0">
      <source class="hudson.plugins.groovy.StringSystemScriptSource">

          <sandbox>false</sandbox>
        </script>
      </source>
    </hudson.plugins.groovy.SystemGroovy>
    <hudson.tasks.@(shell_type)>
      <command>@
@[if os_name in ['linux', 'osx', 'linux-aarch64']]@
rm -rf ws workspace "work space"

echo "# BEGIN SECTION: Determine arguments"
export CI_ARGS="--do-venv --force-ansi-color --workspace-path $WORKSPACE"
if [ -n "${CI_BRANCH_TO_TEST+x}" ]; then
  export CI_ARGS="$CI_ARGS --test-branch $CI_BRANCH_TO_TEST"
fi
if [ -n "${CI_COLCON_BRANCH+x}" ]; then
  export CI_ARGS="$CI_ARGS --colcon-branch $CI_COLCON_BRANCH"
fi
if [ "$CI_USE_WHITESPACE_IN_PATHS" = "true" ]; then
  export CI_ARGS="$CI_ARGS --white-space-in sourcespace buildspace installspace workspace"
fi
export CI_ARGS="$CI_ARGS --ignore-rmw"
if [ "$CI_USE_CONNEXT_STATIC" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_connext_cpp"
fi
if [ "$CI_USE_CONNEXT_DYNAMIC" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_connext_dynamic_cpp"
fi
if [ "$CI_USE_FASTRTPS_STATIC" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_fastrtps_cpp"
fi
if [ "$CI_USE_FASTRTPS_DYNAMIC" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_fastrtps_dynamic_cpp"
fi
if [ "$CI_USE_OPENSPLICE" = "false" ]; then
  export CI_ARGS="$CI_ARGS rmw_opensplice_cpp"
fi
if [ "$CI_USE_CONNEXT_DEBS" = "true" ]; then
  export CI_ARGS="$CI_ARGS --connext-debs"
  export DOCKER_BUILD_ARGS="$DOCKER_BUILD_ARGS --build-arg INSTALL_CONNEXT_DEBS=$CI_USE_CONNEXT_DEBS"
fi
if [ -z "${CI_ROS2_REPOS_URL+x}" ]; then
  CI_ROS2_REPOS_URL="@default_repos_url"
fi
export CI_ARGS="$CI_ARGS --repo-file-url $CI_ROS2_REPOS_URL"
if [ -n "${CI_ROS2_SUPPLEMENTAL_REPOS_URL+x}" ]; then
  export CI_ARGS="$CI_ARGS --supplemental-repo-file-url $CI_ROS2_SUPPLEMENTAL_REPOS_URL"
fi
if [ "$CI_ISOLATED" = "true" ]; then
  export CI_ARGS="$CI_ARGS --isolated"
fi
if [ "${CI_UBUNTU_DISTRO}" = "bionic" ]; then
  export CI_ROS1_DISTRO=melodic
elif [ "${CI_UBUNTU_DISTRO}" = "xenial" ]; then
  export CI_ROS1_DISTRO=kinetic
fi
if [ "${CI_CMAKE_BUILD_TYPE}" != "None" ]; then
  export CI_ARGS="$CI_ARGS --cmake-build-type $CI_CMAKE_BUILD_TYPE"
fi
if [ "$CI_ENABLE_C_COVERAGE" = "true" ]; then
  export CI_ARGS="$CI_ARGS --coverage"
fi
@[  if os_name in ['linux', 'linux-aarch64'] and turtlebot_demo]@
export CI_ARGS="$CI_ARGS --ros1-path /opt/ros/$CI_ROS1_DISTRO"
@[  end if]@
if [ -n "${CI_BUILD_ARGS+x}" ]; then
  export CI_ARGS="$CI_ARGS --build-args $CI_BUILD_ARGS"
fi
if [ -n "${CI_TEST_ARGS+x}" ]; then
  export CI_ARGS="$CI_ARGS --test-args $CI_TEST_ARGS"
fi
echo "Using args: $CI_ARGS"
echo "# END SECTION"

@[  if os_name in ['linux', 'linux-aarch64']]@
sed -i "s+^FROM.*$+FROM ubuntu:$CI_UBUNTU_DISTRO+" linux_docker_resources/Dockerfile
export DOCKER_BUILD_ARGS="${DOCKER_BUILD_ARGS} --build-arg UBUNTU_DISTRO=$CI_UBUNTU_DISTRO --build-arg ROS1_DISTRO=$CI_ROS1_DISTRO"

mkdir -p $HOME/.ccache
echo "# BEGIN SECTION: docker version"
docker version
echo "# END SECTION"
echo "# BEGIN SECTION: docker info"
docker info
echo "# END SECTION"
echo "# BEGIN SECTION: Inject date into Dockerfile"
sed -i "s/@@today_str/`date +%Y-%m-%d`/" linux_docker_resources/Dockerfile
echo "# END SECTION"
echo "# BEGIN SECTION: Build Dockerfile"
@[    if os_name == 'linux-aarch64']@
@[      if turtlebot_demo]@
docker build ${DOCKER_BUILD_ARGS} --build-arg PLATFORM=arm --build-arg INSTALL_TURTLEBOT2_DEMO_DEPS=true -t ros2_batch_ci_turtlebot_demo linux_docker_resources
@[      else]@
docker build ${DOCKER_BUILD_ARGS} --build-arg PLATFORM=arm -t ros2_batch_ci_aarch64 linux_docker_resources
@[      end if]@
@[    elif os_name == 'linux']@
@[      if turtlebot_demo]@
docker build ${DOCKER_BUILD_ARGS} --build-arg INSTALL_TURTLEBOT2_DEMO_DEPS=true -t ros2_batch_ci_turtlebot_demo linux_docker_resources
@[      else]@
docker build ${DOCKER_BUILD_ARGS} -t ros2_batch_ci linux_docker_resources
@[      end if]@
@[    else]@
@{ assert False, 'Unknown os_name: ' + os_name }@
@[    end if]@
echo "# END SECTION"
echo "# BEGIN SECTION: Run Dockerfile"
@[    if turtlebot_demo]@
export CONTAINER_NAME=ros2_batch_ci_turtlebot_demo
@[    elif os_name == 'linux']@
export CONTAINER_NAME=ros2_batch_ci
@[    elif os_name == 'linux-aarch64']@
export CONTAINER_NAME=ros2_batch_ci_aarch64
@[    else]@
@{ assert False, 'Unknown os_name: ' + os_name }@
@[    end if]@
# Create a network that prevents docker containers on the same host from communicating.
# This prevents cross-talk between builds running in parallel on different executors on a single host.
# It may have already been created.
docker network create -o com.docker.network.bridge.enable_icc=false isolated_network || true
docker run --rm --net=isolated_network --privileged -e UID=`id -u` -e GID=`id -g` -e CI_ARGS="$CI_ARGS" -e CCACHE_DIR=/home/rosbuild/.ccache -i -v `pwd`:/home/rosbuild/ci_scripts -v $HOME/.ccache:/home/rosbuild/.ccache $CONTAINER_NAME
echo "# END SECTION"
@[  else]@
echo "# BEGIN SECTION: Run script"
/usr/local/bin/python3 -u run_ros2_batch.py $CI_ARGS
echo "# END SECTION"
@[  end if]@
@[elif os_name == 'windows']@
setlocal enableDelayedExpansion
rmdir /S /Q ws workspace "work space"

echo "# BEGIN SECTION: Determine arguments"
set "PATH=!PATH:"=!"
set "CI_ARGS=--force-ansi-color --workspace-path !WORKSPACE!"
if "!CI_BRANCH_TO_TEST!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --test-branch !CI_BRANCH_TO_TEST!"
)
if "!CI_COLCON_BRANCH!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --colcon-branch !CI_COLCON_BRANCH!"
)
if "!CI_USE_WHITESPACE_IN_PATHS!" == "true" (
  set "CI_ARGS=!CI_ARGS! --white-space-in sourcespace buildspace installspace workspace"
)
set "CI_ARGS=!CI_ARGS! --ignore-rmw"
if "!CI_USE_CONNEXT_STATIC!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_connext_cpp"
)
if "!CI_USE_CONNEXT_DYNAMIC!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_connext_dynamic_cpp"
)
if "!CI_USE_FASTRTPS_STATIC!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_fastrtps_cpp"
)
if "!CI_USE_FASTRTPS_DYNAMIC!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_fastrtps_dynamic_cpp"
)
if "!CI_USE_OPENSPLICE!" == "false" (
  set "CI_ARGS=!CI_ARGS! rmw_opensplice_cpp"
)
if "!CI_USE_CONNEXT_DEBS!" == "true" (
  set "CI_ARGS=!CI_ARGS! --connext-debs"
)
if "!CI_ROS2_REPOS_URL!" EQU "" (
  set "CI_ROS2_REPOS_URL=@default_repos_url"
)
set "CI_ARGS=!CI_ARGS! --repo-file-url !CI_ROS2_REPOS_URL!"
if "!CI_ROS2_SUPPLEMENTAL_REPOS_URL!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --supplemental-repo-file-url !CI_ROS2_SUPPLEMENTAL_REPOS_URL!"
)
if "!CI_ISOLATED!" == "true" (
  set "CI_ARGS=!CI_ARGS! --isolated"
)
if "!CI_CMAKE_BUILD_TYPE!" NEQ "None" (
  set "CI_ARGS=!CI_ARGS! --cmake-build-type !CI_CMAKE_BUILD_TYPE!"
)
if "!CI_CMAKE_BUILD_TYPE!" == "Debug" (
  where python_d > python_debug_interpreter.txt
  set /p PYTHON_DEBUG_INTERPRETER=<python_debug_interpreter.txt
  set "CI_ARGS=!CI_ARGS! --python-interpreter !PYTHON_DEBUG_INTERPRETER!"
)
if "!CI_ENABLE_C_COVERAGE!" == "true" (
  set "CI_ARGS=!CI_ARGS! --coverage"
)
if "!CI_BUILD_ARGS!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --build-args !CI_BUILD_ARGS!"
)
if "!CI_TEST_ARGS!" NEQ "" (
  set "CI_ARGS=!CI_ARGS! --test-args !CI_TEST_ARGS!"
)
echo Using args: !CI_ARGS!
echo "# END SECTION"

echo "# BEGIN SECTION: Run script"
python -u run_ros2_batch.py !CI_ARGS!
echo "# END SECTION"
@[else]@
@{ assert False, 'Unknown os_name: ' + os_name }@
@[end if]</command>
    </hudson.tasks.@(shell_type)>
  </builders>
  <publishers>
@(SNIPPET(
    'publisher_warnings',
    os_name=os_name,
))@
@(SNIPPET(
    'publisher_cobertura',
))@
@(SNIPPET(
    'publisher_xunit',
))@
@[if mailer_recipients]@
    <hudson.tasks.Mailer plugin="mailer@@1.20">
      <recipients>@(mailer_recipients)</recipients>
      <dontNotifyEveryUnstableBuild>@(dont_notify_every_unstable_build)</dontNotifyEveryUnstableBuild>
      <sendToIndividuals>false</sendToIndividuals>
    </hudson.tasks.Mailer>
@[end if]@
  </publishers>
  <buildWrappers>
@[if build_timeout_mins]@
    <hudson.plugins.build__timeout.BuildTimeoutWrapper plugin="build-timeout@@1.18">
      <strategy class="hudson.plugins.build_timeout.impl.AbsoluteTimeOutStrategy">
        <timeoutMinutes>@(build_timeout_mins)</timeoutMinutes>
      </strategy>
      <operationList>
        <hudson.plugins.build__timeout.operations.AbortOperation />
      </operationList>
    </hudson.plugins.build__timeout.BuildTimeoutWrapper>
@[end if]@
    <hudson.plugins.timestamper.TimestamperBuildWrapper plugin="timestamper@@1.8.8" />
    <hudson.plugins.ansicolor.AnsiColorBuildWrapper plugin="ansicolor@@0.5.0">
      <colorMapName>xterm</colorMapName>
    </hudson.plugins.ansicolor.AnsiColorBuildWrapper>
@[if os_name != 'windows']@
    <com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper plugin="ssh-agent@@1.15">
      <credentialIds>
        <string>1c2004f6-2e00-425d-a421-2e1ba62ca7a7</string>
      </credentialIds>
      <ignoreMissing>false</ignoreMissing>
    </com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper>
@[end if]@
  </buildWrappers>
</project>