Make prettyprint handle multiple arguments.

/*  Sirikata
 *  vec3.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/pretty.em');

(function() {
     // Scope of this function hides the real print function and the callback from direct manipulation.
     var realprint = system.print;
     var printhandler = undefined;

     system.onPrint = function(cb) {
         printhandler = cb;
     };
     system.print = function() {
         if (printhandler !== undefined && printhandler !== null)
             printhandler.apply(this, arguments);
         else
             realprint.apply(this, arguments);
     };
 }
)();

system.prettyprint = function() {
    res = '';
    for(var i = 0; i < arguments.length; i++)
        res += std.core.pretty(arguments[i]);
    system.print(res);
};

/*  Sirikata
 *  vec3.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/pretty.em');

(function() {
     // Scope of this function hides the real print function and the callback from direct manipulation.
     var realprint = system.print;
     var printhandler = undefined;

     system.onPrint = function(cb) {
         printhandler = cb;
     };
     system.print = function() {
         if (printhandler !== undefined && printhandler !== null)
             printhandler.apply(this, arguments);
         else
             realprint.apply(this, arguments);
     };
 }
)();

system.prettyprint = function(x) {
    system.print( std.core.pretty(x) );
};


Mount the shared jenkins hgcache to allow hg operations. (#526)

* Mount the shared jenkins hgcache to allow hg operations.

This fixes #502 by mounting the hgcache directory in-place within the
doc_task_generation container which uses `hg id --id` to get the current
commit id when checking whether docs should be rebuilt.

* avoid generating an empty line, use four space indentation for Python code

@{import os}@
<project>
  <actions/>
  <description>Generated at @ESCAPE(now_str) from template '@ESCAPE(template_name)'@
@[if disabled]
but disabled since the package is blacklisted (or not whitelisted) in the configuration file@
@[end if]@
@ </description>
  <keepDependencies>false</keepDependencies>
  <properties>
@(SNIPPET(
    'property_log-rotator',
    days_to_keep=365,
    num_to_keep=100,
))@
@[if github_url]@
@(SNIPPET(
    'property_github-project',
    project_url=github_url,
))@
@[end if]@
@[if job_priority is not None]@
@(SNIPPET(
    'property_job-priority',
    priority=job_priority,
))@
@[end if]@
@(SNIPPET(
    'property_requeue-job',
))@
@(SNIPPET(
    'property_parameters-definition',
    parameters=[
        {
            'type': 'boolean',
            'name': 'force',
            'description': 'Run documentation generation even if neither the source repository nor any of the tools have changes',
        },
        {
            'type': 'boolean',
            'name': 'skip_cleanup',
            'description': 'Skip cleanup of catkin build artifacts as well as rosdoc index',
        },
    ],
))@
  </properties>
@(SNIPPET(
    'scm',
    repo_spec=doc_repo_spec,
    path='catkin_workspace/src/%s' % doc_repo_spec.name,
    git_ssh_credential_id=git_ssh_credential_id,
))@
  <scmCheckoutRetryCount>2</scmCheckoutRetryCount>
  <assignedNode>@(node_label)</assignedNode>
  <canRoam>false</canRoam>
  <disabled>@('true' if disabled else 'false')</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers>
@(SNIPPET(
    'trigger_poll',
    spec='H 3 H/3 * *',
))@
  </triggers>
  <concurrentBuild>false</concurrentBuild>
  <builders>
@(SNIPPET(
    'builder_system-groovy_check-free-disk-space',
))@
@(SNIPPET(
    'builder_shell_docker-info',
))@
@(SNIPPET(
    'builder_check-docker',
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
))@
@(SNIPPET(
    'builder_shell_clone-ros-buildfarm',
    ros_buildfarm_repository=ros_buildfarm_repository,
    wrapper_scripts=wrapper_scripts,
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: Clone rosdoc_lite"',
        'rm -fr rosdoc_lite',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/wrapper/git.py clone --depth 1 https://github.com/ros-infrastructure/rosdoc_lite.git rosdoc_lite',
        'git -C rosdoc_lite log -n 1',
        'rm -fr rosdoc_lite/doc',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Clone catkin-sphinx"',
        'rm -fr catkin-sphinx',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/wrapper/git.py clone --depth 1 https://github.com/ros-infrastructure/catkin-sphinx catkin-sphinx',
        'git -C catkin-sphinx log -n 1',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: rsync (most of) the rosdoc_index to agent"',
        'rm -fr rosdoc_index',
        'mkdir rosdoc_index',
        '# since rsync fails if the source folder does not exist we need to check it before',
        'if ssh %s@%s stat %s/%s > /dev/null 2> /dev/null; then' % \
          (upload_user, upload_host, upload_root.rstrip('/'), rosdistro_name),
        '  rsync -e ssh --stats' +
        ' --prune-empty-dirs --recursive' +
        ' --include="*/"' +
        ' --include="api/*/manifest.yaml"' +
        ' --include="deps/*"' +
        ' --include="hashes/%s"' % doc_repo_spec.name +
        ' --include="locations/*"' +
        ' --include="metapackage_deps/*"' +
        ' --include="symbols/*"' +
        ' --exclude="*"' +
        ' %s@%s:%s/%s $WORKSPACE/rosdoc_index' % \
          (upload_user, upload_host, upload_root.rstrip('/'), rosdistro_name),
        'fi',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell_key-files',
    script_generating_key_files=script_generating_key_files,
))@
@{
if doc_repo_spec.type == 'hg':
    hgcache_mount_arg = ' -v $HOME/hgcache:$HOME/hgcache '
else:
    hgcache_mount_arg = ''
}@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'rm -fr $WORKSPACE/docker_generating_docker',
        'rm -fr $WORKSPACE/generated_documentation',
        'mkdir -p $WORKSPACE/docker_generating_docker',
        'mkdir -p $WORKSPACE/generated_documentation',
        '',
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_generating_docker/docker.cid > $WORKSPACE/docker_generating_docker/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# generate Dockerfile, build and run it',
        '# generating the Dockerfiles for the actual doc task',
        'echo "# BEGIN SECTION: Generate Dockerfile - doc task"',
        'export TZ="%s"' % timezone,
        'export PYTHONPATH=$WORKSPACE/ros_buildfarm:$PYTHONPATH',
        'if [ "$force" = "true" ]; then FORCE_FLAG="--force"; fi',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/doc/run_doc_job.py' +
        ' ' + config_url +
        ' --rosdistro-index-url ' + rosdistro_index_url +
        ' ' + rosdistro_name +
        ' ' + doc_build_name +
        ' ' + doc_repo_spec.name +
        ' ' + os_name +
        ' ' + os_code_name +
        ' ' + arch +
        ' --vcs-info "%s %s %s"' % (doc_repo_spec.type, doc_repo_spec.version if doc_repo_spec.version is not None else '', doc_repo_spec.url) +
        ' ' + ' '.join(repository_args) +
        ' $FORCE_FLAG' +
        ' --dockerfile-dir $WORKSPACE/docker_generating_docker',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - generating doc task"',
        'cd $WORKSPACE/docker_generating_docker',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t doc_task_generation.%s_%s .' % (rosdistro_name, doc_repo_spec.name.lower()),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - generating doc task"',
        'rm -fr $WORKSPACE/docker_doc',
        'mkdir -p $WORKSPACE/docker_doc',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_generating_docker/docker.cid' +
        ' -e=HOME=/home/buildfarm' +
        ' -e=TRAVIS=$TRAVIS' +
        ' -e=ROS_BUILDFARM_PULL_REQUEST_BRANCH=$ROS_BUILDFARM_PULL_REQUEST_BRANCH' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ' -v $WORKSPACE/rosdoc_lite:/tmp/rosdoc_lite:ro' +
        ' -v $WORKSPACE/catkin-sphinx:/tmp/catkin-sphinx:ro' +
        ' -v $WORKSPACE/rosdoc_index:/tmp/rosdoc_index:ro' +
        ' -v $WORKSPACE/catkin_workspace:/tmp/catkin_workspace' +
        ' -v $WORKSPACE/generated_documentation:/tmp/generated_documentation' +
        ' -v $WORKSPACE/docker_doc:/tmp/docker_doc' +
        hgcache_mount_arg +
        ' doc_task_generation.%s_%s' % (rosdistro_name, doc_repo_spec.name.lower()),
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'if [ ! -f "$WORKSPACE/docker_doc/Dockerfile" ]; then',
        '  exit 0',
        'fi',
        '',
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_doc/docker.cid > $WORKSPACE/docker_doc/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - doc"',
        '# build and run build_and_install Dockerfile',
        'cd $WORKSPACE/docker_doc',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t doc.%s_%s .' % (rosdistro_name, doc_repo_spec.name.lower()),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - doc"',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_doc/docker.cid' +
        ' -e=TRAVIS=$TRAVIS' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ' -v $WORKSPACE/rosdoc_lite:/tmp/rosdoc_lite:ro' +
        ' -v $WORKSPACE/catkin-sphinx:/tmp/catkin-sphinx:ro' +
        ' -v $WORKSPACE/rosdoc_index:/tmp/rosdoc_index:ro' +
        ' -v $WORKSPACE/catkin_workspace:/tmp/catkin_workspace' +
        ' -v $WORKSPACE/generated_documentation:/tmp/generated_documentation' +
        ' doc.%s_%s' % (rosdistro_name, doc_repo_spec.name.lower()),
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'if [ "$skip_cleanup" = "false" ]; then',
        'echo "# BEGIN SECTION: Clean up to save disk space on agents"',
        'rm -fr catkin_workspace/build_isolated',
        'rm -fr catkin_workspace/devel_isolated',
        'rm -fr catkin_workspace/install_isolated',
        'rm -fr catkin-sphinx',
        'rm -fr rosdoc_index',
        'rm -fr rosdoc_lite',
        'echo "# END SECTION"',
        'fi',
    ]),
))@
@(SNIPPET(
    'builder_publish-over-ssh',
    config_name='docs',
    remote_directory=rosdistro_name,
    source_files=[
        'generated_documentation/api/**/manifest.yaml',
        'generated_documentation/api/**/stamp',
        'generated_documentation/changelogs/**/*.html',
        'generated_documentation/symbols/*.tag',

        'generated_documentation/deps/*',
        'generated_documentation/hashes/*',
        'generated_documentation/locations/*',
        'generated_documentation/metapackage_deps/*',
    ],
    remove_prefix='generated_documentation',
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'if [ -d "$WORKSPACE/generated_documentation/api_rosdoc" ]; then',
        '  echo "# BEGIN SECTION: rsync API documentation to server"',
        '  cd $WORKSPACE/generated_documentation/api_rosdoc',
        '  for pkg_name in $(find . -maxdepth 1 -mindepth 1 -type d); do',
        '    rsync -e ssh --stats -r --delete $pkg_name %s@%s:%s' % \
          (upload_user, upload_host, os.path.join(upload_root, rosdistro_name, 'api')),
        '  done',
        '  echo "# END SECTION"',
        'fi',
    ]),
))@
@(SNIPPET(
    'builder_system-groovy_extract-warnings',
))@
  </builders>
  <publishers>
@[if notify_maintainers]@
@(SNIPPET(
    'publisher_groovy-postbuild_maintainer-notification',
))@
@[end if]@
@(SNIPPET(
    'publisher_mailer',
    recipients=notify_emails,
    dynamic_recipients=maintainer_emails,
    send_to_individuals=notify_committers,
))@
  </publishers>
  <buildWrappers>
@[if timeout_minutes is not None]@
@(SNIPPET(
    'build-wrapper_build-timeout',
    timeout_minutes=timeout_minutes,
))@
@[end if]@
@(SNIPPET(
    'build-wrapper_timestamper',
))@
@(SNIPPET(
    'build-wrapper_ssh-agent',
    credential_ids=[credential_id],
))@
  </buildWrappers>
</project>

@{import os}@
<project>
  <actions/>
  <description>Generated at @ESCAPE(now_str) from template '@ESCAPE(template_name)'@
@[if disabled]
but disabled since the package is blacklisted (or not whitelisted) in the configuration file@
@[end if]@
@ </description>
  <keepDependencies>false</keepDependencies>
  <properties>
@(SNIPPET(
    'property_log-rotator',
    days_to_keep=365,
    num_to_keep=100,
))@
@[if github_url]@
@(SNIPPET(
    'property_github-project',
    project_url=github_url,
))@
@[end if]@
@[if job_priority is not None]@
@(SNIPPET(
    'property_job-priority',
    priority=job_priority,
))@
@[end if]@
@(SNIPPET(
    'property_requeue-job',
))@
@(SNIPPET(
    'property_parameters-definition',
    parameters=[
        {
            'type': 'boolean',
            'name': 'force',
            'description': 'Run documentation generation even if neither the source repository nor any of the tools have changes',
        },
        {
            'type': 'boolean',
            'name': 'skip_cleanup',
            'description': 'Skip cleanup of catkin build artifacts as well as rosdoc index',
        },
    ],
))@
  </properties>
@(SNIPPET(
    'scm',
    repo_spec=doc_repo_spec,
    path='catkin_workspace/src/%s' % doc_repo_spec.name,
    git_ssh_credential_id=git_ssh_credential_id,
))@
  <scmCheckoutRetryCount>2</scmCheckoutRetryCount>
  <assignedNode>@(node_label)</assignedNode>
  <canRoam>false</canRoam>
  <disabled>@('true' if disabled else 'false')</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers>
@(SNIPPET(
    'trigger_poll',
    spec='H 3 H/3 * *',
))@
  </triggers>
  <concurrentBuild>false</concurrentBuild>
  <builders>
@(SNIPPET(
    'builder_system-groovy_check-free-disk-space',
))@
@(SNIPPET(
    'builder_shell_docker-info',
))@
@(SNIPPET(
    'builder_check-docker',
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
))@
@(SNIPPET(
    'builder_shell_clone-ros-buildfarm',
    ros_buildfarm_repository=ros_buildfarm_repository,
    wrapper_scripts=wrapper_scripts,
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: Clone rosdoc_lite"',
        'rm -fr rosdoc_lite',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/wrapper/git.py clone --depth 1 https://github.com/ros-infrastructure/rosdoc_lite.git rosdoc_lite',
        'git -C rosdoc_lite log -n 1',
        'rm -fr rosdoc_lite/doc',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Clone catkin-sphinx"',
        'rm -fr catkin-sphinx',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/wrapper/git.py clone --depth 1 https://github.com/ros-infrastructure/catkin-sphinx catkin-sphinx',
        'git -C catkin-sphinx log -n 1',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: rsync (most of) the rosdoc_index to agent"',
        'rm -fr rosdoc_index',
        'mkdir rosdoc_index',
        '# since rsync fails if the source folder does not exist we need to check it before',
        'if ssh %s@%s stat %s/%s > /dev/null 2> /dev/null; then' % \
          (upload_user, upload_host, upload_root.rstrip('/'), rosdistro_name),
        '  rsync -e ssh --stats' +
        ' --prune-empty-dirs --recursive' +
        ' --include="*/"' +
        ' --include="api/*/manifest.yaml"' +
        ' --include="deps/*"' +
        ' --include="hashes/%s"' % doc_repo_spec.name +
        ' --include="locations/*"' +
        ' --include="metapackage_deps/*"' +
        ' --include="symbols/*"' +
        ' --exclude="*"' +
        ' %s@%s:%s/%s $WORKSPACE/rosdoc_index' % \
          (upload_user, upload_host, upload_root.rstrip('/'), rosdistro_name),
        'fi',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell_key-files',
    script_generating_key_files=script_generating_key_files,
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'rm -fr $WORKSPACE/docker_generating_docker',
        'rm -fr $WORKSPACE/generated_documentation',
        'mkdir -p $WORKSPACE/docker_generating_docker',
        'mkdir -p $WORKSPACE/generated_documentation',
        '',
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_generating_docker/docker.cid > $WORKSPACE/docker_generating_docker/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# generate Dockerfile, build and run it',
        '# generating the Dockerfiles for the actual doc task',
        'echo "# BEGIN SECTION: Generate Dockerfile - doc task"',
        'export TZ="%s"' % timezone,
        'export PYTHONPATH=$WORKSPACE/ros_buildfarm:$PYTHONPATH',
        'if [ "$force" = "true" ]; then FORCE_FLAG="--force"; fi',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/doc/run_doc_job.py' +
        ' ' + config_url +
        ' --rosdistro-index-url ' + rosdistro_index_url +
        ' ' + rosdistro_name +
        ' ' + doc_build_name +
        ' ' + doc_repo_spec.name +
        ' ' + os_name +
        ' ' + os_code_name +
        ' ' + arch +
        ' --vcs-info "%s %s %s"' % (doc_repo_spec.type, doc_repo_spec.version if doc_repo_spec.version is not None else '', doc_repo_spec.url) +
        ' ' + ' '.join(repository_args) +
        ' $FORCE_FLAG' +
        ' --dockerfile-dir $WORKSPACE/docker_generating_docker',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - generating doc task"',
        'cd $WORKSPACE/docker_generating_docker',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t doc_task_generation.%s_%s .' % (rosdistro_name, doc_repo_spec.name.lower()),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - generating doc task"',
        'rm -fr $WORKSPACE/docker_doc',
        'mkdir -p $WORKSPACE/docker_doc',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_generating_docker/docker.cid' +
        ' -e=HOME=/home/buildfarm' +
        ' -e=TRAVIS=$TRAVIS' +
        ' -e=ROS_BUILDFARM_PULL_REQUEST_BRANCH=$ROS_BUILDFARM_PULL_REQUEST_BRANCH' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ' -v $WORKSPACE/rosdoc_lite:/tmp/rosdoc_lite:ro' +
        ' -v $WORKSPACE/catkin-sphinx:/tmp/catkin-sphinx:ro' +
        ' -v $WORKSPACE/rosdoc_index:/tmp/rosdoc_index:ro' +
        ' -v $WORKSPACE/catkin_workspace:/tmp/catkin_workspace' +
        ' -v $WORKSPACE/generated_documentation:/tmp/generated_documentation' +
        ' -v $WORKSPACE/docker_doc:/tmp/docker_doc' +
        ' doc_task_generation.%s_%s' % (rosdistro_name, doc_repo_spec.name.lower()),
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'if [ ! -f "$WORKSPACE/docker_doc/Dockerfile" ]; then',
        '  exit 0',
        'fi',
        '',
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_doc/docker.cid > $WORKSPACE/docker_doc/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - doc"',
        '# build and run build_and_install Dockerfile',
        'cd $WORKSPACE/docker_doc',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t doc.%s_%s .' % (rosdistro_name, doc_repo_spec.name.lower()),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - doc"',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_doc/docker.cid' +
        ' -e=TRAVIS=$TRAVIS' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ' -v $WORKSPACE/rosdoc_lite:/tmp/rosdoc_lite:ro' +
        ' -v $WORKSPACE/catkin-sphinx:/tmp/catkin-sphinx:ro' +
        ' -v $WORKSPACE/rosdoc_index:/tmp/rosdoc_index:ro' +
        ' -v $WORKSPACE/catkin_workspace:/tmp/catkin_workspace' +
        ' -v $WORKSPACE/generated_documentation:/tmp/generated_documentation' +
        ' doc.%s_%s' % (rosdistro_name, doc_repo_spec.name.lower()),
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'if [ "$skip_cleanup" = "false" ]; then',
        'echo "# BEGIN SECTION: Clean up to save disk space on agents"',
        'rm -fr catkin_workspace/build_isolated',
        'rm -fr catkin_workspace/devel_isolated',
        'rm -fr catkin_workspace/install_isolated',
        'rm -fr catkin-sphinx',
        'rm -fr rosdoc_index',
        'rm -fr rosdoc_lite',
        'echo "# END SECTION"',
        'fi',
    ]),
))@
@(SNIPPET(
    'builder_publish-over-ssh',
    config_name='docs',
    remote_directory=rosdistro_name,
    source_files=[
        'generated_documentation/api/**/manifest.yaml',
        'generated_documentation/api/**/stamp',
        'generated_documentation/changelogs/**/*.html',
        'generated_documentation/symbols/*.tag',

        'generated_documentation/deps/*',
        'generated_documentation/hashes/*',
        'generated_documentation/locations/*',
        'generated_documentation/metapackage_deps/*',
    ],
    remove_prefix='generated_documentation',
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'if [ -d "$WORKSPACE/generated_documentation/api_rosdoc" ]; then',
        '  echo "# BEGIN SECTION: rsync API documentation to server"',
        '  cd $WORKSPACE/generated_documentation/api_rosdoc',
        '  for pkg_name in $(find . -maxdepth 1 -mindepth 1 -type d); do',
        '    rsync -e ssh --stats -r --delete $pkg_name %s@%s:%s' % \
          (upload_user, upload_host, os.path.join(upload_root, rosdistro_name, 'api')),
        '  done',
        '  echo "# END SECTION"',
        'fi',
    ]),
))@
@(SNIPPET(
    'builder_system-groovy_extract-warnings',
))@
  </builders>
  <publishers>
@[if notify_maintainers]@
@(SNIPPET(
    'publisher_groovy-postbuild_maintainer-notification',
))@
@[end if]@
@(SNIPPET(
    'publisher_mailer',
    recipients=notify_emails,
    dynamic_recipients=maintainer_emails,
    send_to_individuals=notify_committers,
))@
  </publishers>
  <buildWrappers>
@[if timeout_minutes is not None]@
@(SNIPPET(
    'build-wrapper_build-timeout',
    timeout_minutes=timeout_minutes,
))@
@[end if]@
@(SNIPPET(
    'build-wrapper_timestamper',
))@
@(SNIPPET(
    'build-wrapper_ssh-agent',
    credential_ids=[credential_id],
))@
  </buildWrappers>
</project>


Group message initializations by their appropriate checks (#350)

* Group message initializations by their appropriate checks

Signed-off-by: Hunter L. Allen <313f9568b0cbc24f5880e825c3d9da935bca82a5@kns.com>

* Fix indentation

Signed-off-by: Hunter L. Allen <313f9568b0cbc24f5880e825c3d9da935bca82a5@kns.com>

* Rename variables to reflect their contents not their use

Signed-off-by: Hunter L. Allen <313f9568b0cbc24f5880e825c3d9da935bca82a5@kns.com>

* More indentation fixing

Signed-off-by: Hunter L. Allen <313f9568b0cbc24f5880e825c3d9da935bca82a5@kns.com>

* Fix indentation

Signed-off-by: Hunter L. Allen <313f9568b0cbc24f5880e825c3d9da935bca82a5@kns.com>

@# Included from rosidl_generator_cpp/resource/idl__struct.hpp.em
// Protect against ERROR being predefined on Windows, in case somebody defines a
// constant by that name.
#if defined(_WIN32)
  #if defined(ERROR)
    #undef ERROR
  #endif
  #if defined(NO_ERROR)
    #undef NO_ERROR
  #endif
#endif
@
@{
from rosidl_generator_cpp import create_init_alloc_and_member_lists
from rosidl_generator_cpp import escape_string
from rosidl_generator_cpp import msg_type_to_cpp
from rosidl_generator_cpp import MSG_TYPE_TO_CPP
from rosidl_parser.definition import ACTION_FEEDBACK_SUFFIX
from rosidl_parser.definition import ACTION_GOAL_SUFFIX
from rosidl_parser.definition import ACTION_RESULT_SUFFIX
from rosidl_parser.definition import BaseString
from rosidl_parser.definition import BasicType
from rosidl_parser.definition import NamespacedType
from rosidl_parser.definition import NestedType

message_typename = '::'.join(message.structure.type.namespaces + [message.structure.type.name])
}@
@
@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@# Collect necessary include directives for all members
@{
from collections import OrderedDict
from rosidl_cmake import convert_camel_case_to_lower_case_underscore
includes = OrderedDict()
for member in message.structure.members:
    type_ = member.type
    if isinstance(type_, NestedType):
        type_ = type_.basetype
    if isinstance(type_, NamespacedType):
        if (
            type_.name.endswith(ACTION_GOAL_SUFFIX) or
            type_.name.endswith(ACTION_RESULT_SUFFIX) or
            type_.name.endswith(ACTION_FEEDBACK_SUFFIX)
        ):
            typename = type_.name.rsplit('_', 1)[0]
        else:
            typename = type_.name
        member_names = includes.setdefault(
            '/'.join((type_.namespaces + [convert_camel_case_to_lower_case_underscore(typename)])) + '__struct.hpp', [])
        member_names.append(member.name)
}@
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@
@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@[if includes]@

// Include directives for member types
@[    for header_file, member_names in includes.items()]@
@[        for member_name in member_names]@
// Member '@(member_name)'
@[        end for]@
@[        if header_file in include_directives]@
// already included above
// @
@[        else]@
@{include_directives.add(header_file)}@
@[        end if]@
#include "@(header_file)"
@[    end for]@
@[end if]@
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

@{
deprecated_macro_name = \
    '__'.join(['DEPRECATED', package_name] + list(interface_path.parents[0].parts) + [message.structure.type.name])
}@
#ifndef _WIN32
# define @(deprecated_macro_name) __attribute__((deprecated))
#else
# define @(deprecated_macro_name) __declspec(deprecated)
#endif

@[for ns in message.structure.type.namespaces]@
namespace @(ns)
{

@[end for]@
// message struct
template<class ContainerAllocator>
struct @(message.structure.type.name)_
{
  using Type = @(message.structure.type.name)_<ContainerAllocator>;

@{
# The creation of the constructors for messages is a bit complicated.  The goal
# is to have a constructor where the user can control how the fields of the
# message get initialized via the _init parameter to the constructor.  See
# http://design.ros2.org/articles/generated_interfaces_cpp.html#constructors
# for a detailed explanation of the different _init parameters.
init_list, alloc_list, member_list = create_init_alloc_and_member_lists(message)

def generate_default_string(membset):
    from rosidl_generator_cpp import msg_type_only_to_cpp
    from rosidl_generator_cpp import msg_type_to_cpp
    strlist = []
    for member in membset.members:
        if member.default_value is not None:
            if member.num_prealloc > 0:
                strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
            if isinstance(member.default_value, list):
                if all(v == member.default_value[0] for v in member.default_value):
                    # Specifying type for std::fill because of MSVC 14.12 warning about casting 'const int' to smaller types (C4244)
                    # For more info, see https://github.com/ros2/rosidl/issues/309
                    # TODO(jacobperron): Investigate reason for build warnings on Windows
                    # TODO(jacobperron): Write test case for this path of execution
                    strlist.append('std::fill<typename %s::iterator, %s>(this->%s.begin(), this->%s.end(), %s);' % (msg_type_to_cpp(member.type), msg_type_only_to_cpp(member.type), member.name, member.name, member.default_value[0]))
                else:
                    for index, val in enumerate(member.default_value):
                        strlist.append('this->%s[%d] = %s;' % (member.name, index, val))
            else:
                strlist.append('this->%s = %s;' % (member.name, member.default_value))

    return strlist

def generate_zero_string(membset, fill_args):
    from rosidl_generator_cpp import msg_type_only_to_cpp
    from rosidl_generator_cpp import msg_type_to_cpp
    strlist = []
    for member in membset.members:
        if isinstance(member.zero_value, list):
            if member.num_prealloc > 0:
                strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
            if member.zero_need_array_override:
                strlist.append('this->%s.fill(%s{%s});' % (member.name, msg_type_only_to_cpp(member.type), fill_args))
            else:
                # Specifying type for std::fill because of MSVC 14.12 warning about casting 'const int' to smaller types (C4244)
                # For more info, see https://github.com/ros2/rosidl/issues/309
                # TODO(jacobperron): Investigate reason for build warnings on Windows
                strlist.append('std::fill<typename %s::iterator, %s>(this->%s.begin(), this->%s.end(), %s);' % (msg_type_to_cpp(member.type), msg_type_only_to_cpp(member.type), member.name, member.name, member.zero_value[0]))
        else:
            strlist.append('this->%s = %s;' % (member.name, member.zero_value))
    return strlist
}@
  explicit @(message.structure.type.name)_(rosidl_generator_cpp::MessageInitialization _init = rosidl_generator_cpp::MessageInitialization::ALL)
@[if init_list]@
  : @(',\n    '.join(init_list))
@[end if]@
  {
@[if not member_list]@
    (void)_init;
@[end if]@
@{
default_value_members = [m for m in member_list if m.members[0].default_value]
zero_value_members = [m for m in member_list if m.members[0].zero_value]
non_defaulted_zero_initialized_members = [
    m for m in member_list
    if (m.members[0].zero_value or m.members[0].zero_need_array_override) and not m.members[0].default_value
]
}@
@[if default_value_members]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
    {
@[  for membset in default_value_members]@
@[    for line in generate_default_string(membset)]@
      @(line)
@[    end for]@
@[  end for]@
@[  if zero_value_members]@
    } else if (rosidl_generator_cpp::MessageInitialization::ZERO == _init) {
@[    for membset in zero_value_members]@
@[      for line in generate_zero_string(membset, '_init')]@
      @(line)
@[      end for]@
@[    end for]@
@[  end if]@
    }
@[  end if]@
@[  if non_defaulted_zero_initialized_members]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::ZERO == _init)
    {
@[  for membset in non_defaulted_zero_initialized_members]@
@[    for line in generate_zero_string(membset, '_init')]@
@[      if line]@
      @(line)
@[      end if]@
@[    end for]@
@[  end for]@
    }
@[end if]@
  }

  explicit @(message.structure.type.name)_(const ContainerAllocator & _alloc, rosidl_generator_cpp::MessageInitialization _init = rosidl_generator_cpp::MessageInitialization::ALL)
@[if alloc_list]@
  : @(',\n    '.join(alloc_list))
@[end if]@
  {
@[if not member_list]@
    (void)_init;
@[end if]@
@[if not alloc_list]@
    (void)_alloc;
@[end if]@
@[if default_value_members]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
    {
@[  for membset in default_value_members]@
@[    for line in generate_default_string(membset)]@
      @(line)
@[    end for]@
@[  end for]@
@[  if zero_value_members]@
    } else if (rosidl_generator_cpp::MessageInitialization::ZERO == _init) {
@[    for membset in zero_value_members]@
@[      for line in generate_zero_string(membset, '_alloc, _init')]@
      @(line)
@[      end for]@
@[    end for]@
@[  end if]@
    }
@[end if]@
@[if non_defaulted_zero_initialized_members]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::ZERO == _init)
    {
@[  for membset in non_defaulted_zero_initialized_members]@
@[    for line in generate_zero_string(membset, '_alloc, _init')]@
      @(line)
@[    end for]@
@[  end for]@
    }
@[end if]@
  }

  // field types and members
@[for member in message.structure.members]@
  using _@(member.name)_type =
    @(msg_type_to_cpp(member.type));
  _@(member.name)_type @(member.name);
@[end for]@

  // setters for named parameter idiom
@[for member in message.structure.members]@
  Type & set__@(member.name)(
    const @(msg_type_to_cpp(member.type)) & _arg)
  {
    this->@(member.name) = _arg;
    return *this;
  }
@[end for]@

  // constant declarations
@[for constant in message.constants.values()]@
@[ if isinstance(constant.type, BaseString)]@
  static const @(MSG_TYPE_TO_CPP['string']) @(constant.name);
@[ else]@
  static constexpr @(MSG_TYPE_TO_CPP[constant.type.type]) @(constant.name) =
@[  if isinstance(constant.type, BasicType) and constant.type.type in ['short', 'unsigned short', 'long', 'unsigned long', 'long long', 'unsigned long long', 'char', 'wchar', 'boolean', 'octet', 'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64']]@
    @(int(constant.value))@
@[   if constant.type.type.startswith('u')]@
u@
@[   end if];
@[  else]@
    @(constant.value);
@[  end if]@
@[ end if]@
@[end for]@

  // pointer types
  using RawPtr =
    @(message_typename)_<ContainerAllocator> *;
  using ConstRawPtr =
    const @(message_typename)_<ContainerAllocator> *;
  using SharedPtr =
    std::shared_ptr<@(message_typename)_<ContainerAllocator>>;
  using ConstSharedPtr =
    std::shared_ptr<@(message_typename)_<ContainerAllocator> const>;

  template<typename Deleter = std::default_delete<
      @(message_typename)_<ContainerAllocator>>>
  using UniquePtrWithDeleter =
    std::unique_ptr<@(message_typename)_<ContainerAllocator>, Deleter>;

  using UniquePtr = UniquePtrWithDeleter<>;

  template<typename Deleter = std::default_delete<
      @(message_typename)_<ContainerAllocator>>>
  using ConstUniquePtrWithDeleter =
    std::unique_ptr<@(message_typename)_<ContainerAllocator> const, Deleter>;
  using ConstUniquePtr = ConstUniquePtrWithDeleter<>;

  using WeakPtr =
    std::weak_ptr<@(message_typename)_<ContainerAllocator>>;
  using ConstWeakPtr =
    std::weak_ptr<@(message_typename)_<ContainerAllocator> const>;

  // pointer types similar to ROS 1, use SharedPtr / ConstSharedPtr instead
  // NOTE: Can't use 'using' here because GNU C++ can't parse attributes properly
  typedef @(deprecated_macro_name)
    std::shared_ptr<@(message_typename)_<ContainerAllocator>>
    Ptr;
  typedef @(deprecated_macro_name)
    std::shared_ptr<@(message_typename)_<ContainerAllocator> const>
    ConstPtr;

  // comparison operators
  bool operator==(const @(message.structure.type.name)_ & other) const
  {
@[if not message.structure.members]@
    (void)other;
@[end if]@
@[for member in message.structure.members]@
    if (this->@(member.name) != other.@(member.name)) {
      return false;
    }
@[end for]@
    return true;
  }
  bool operator!=(const @(message.structure.type.name)_ & other) const
  {
    return !this->operator==(other);
  }
};  // struct @(message.structure.type.name)_

// alias to use template instance with default allocator
using @(message.structure.type.name) =
  @(message_typename)_<std::allocator<void>>;

// constant definitions
@[for c in message.constants.values()]@
@[ if isinstance(c.type, BaseString)]@
template<typename ContainerAllocator>
const @(MSG_TYPE_TO_CPP['string'])
@(message.structure.type.name)_<ContainerAllocator>::@(c.name) = "@(escape_string(c.value))";
@[ else ]@
template<typename ContainerAllocator>
constexpr @(MSG_TYPE_TO_CPP[c.type.type]) @(message.structure.type.name)_<ContainerAllocator>::@(c.name);
@[ end if]@
@[end for]@
@
@[for ns in reversed(message.structure.type.namespaces)]@

}  // namespace @(ns)
@[end for]@

@# Included from rosidl_generator_cpp/resource/idl__struct.hpp.em
// Protect against ERROR being predefined on Windows, in case somebody defines a
// constant by that name.
#if defined(_WIN32)
  #if defined(ERROR)
    #undef ERROR
  #endif
  #if defined(NO_ERROR)
    #undef NO_ERROR
  #endif
#endif
@
@{
from rosidl_generator_cpp import create_init_alloc_and_member_lists
from rosidl_generator_cpp import escape_string
from rosidl_generator_cpp import msg_type_to_cpp
from rosidl_generator_cpp import MSG_TYPE_TO_CPP
from rosidl_parser.definition import ACTION_FEEDBACK_SUFFIX
from rosidl_parser.definition import ACTION_GOAL_SUFFIX
from rosidl_parser.definition import ACTION_RESULT_SUFFIX
from rosidl_parser.definition import BaseString
from rosidl_parser.definition import BasicType
from rosidl_parser.definition import NamespacedType
from rosidl_parser.definition import NestedType

message_typename = '::'.join(message.structure.type.namespaces + [message.structure.type.name])
}@
@
@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@# Collect necessary include directives for all members
@{
from collections import OrderedDict
from rosidl_cmake import convert_camel_case_to_lower_case_underscore
includes = OrderedDict()
for member in message.structure.members:
    type_ = member.type
    if isinstance(type_, NestedType):
        type_ = type_.basetype
    if isinstance(type_, NamespacedType):
        if (
            type_.name.endswith(ACTION_GOAL_SUFFIX) or
            type_.name.endswith(ACTION_RESULT_SUFFIX) or
            type_.name.endswith(ACTION_FEEDBACK_SUFFIX)
        ):
            typename = type_.name.rsplit('_', 1)[0]
        else:
            typename = type_.name
        member_names = includes.setdefault(
            '/'.join((type_.namespaces + [convert_camel_case_to_lower_case_underscore(typename)])) + '__struct.hpp', [])
        member_names.append(member.name)
}@
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@
@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@[if includes]@

// Include directives for member types
@[    for header_file, member_names in includes.items()]@
@[        for member_name in member_names]@
// Member '@(member_name)'
@[        end for]@
@[        if header_file in include_directives]@
// already included above
// @
@[        else]@
@{include_directives.add(header_file)}@
@[        end if]@
#include "@(header_file)"
@[    end for]@
@[end if]@
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

@{
deprecated_macro_name = \
    '__'.join(['DEPRECATED', package_name] + list(interface_path.parents[0].parts) + [message.structure.type.name])
}@
#ifndef _WIN32
# define @(deprecated_macro_name) __attribute__((deprecated))
#else
# define @(deprecated_macro_name) __declspec(deprecated)
#endif

@[for ns in message.structure.type.namespaces]@
namespace @(ns)
{

@[end for]@
// message struct
template<class ContainerAllocator>
struct @(message.structure.type.name)_
{
  using Type = @(message.structure.type.name)_<ContainerAllocator>;

@{
# The creation of the constructors for messages is a bit complicated.  The goal
# is to have a constructor where the user can control how the fields of the
# message get initialized via the _init parameter to the constructor.  See
# http://design.ros2.org/articles/generated_interfaces_cpp.html#constructors
# for a detailed explanation of the different _init parameters.
init_list, alloc_list, member_list = create_init_alloc_and_member_lists(message)

def generate_default_string(membset):
    from rosidl_generator_cpp import msg_type_only_to_cpp
    from rosidl_generator_cpp import msg_type_to_cpp
    strlist = []
    for member in membset.members:
        if member.default_value is not None:
            if member.num_prealloc > 0:
                strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
            if isinstance(member.default_value, list):
                if all(v == member.default_value[0] for v in member.default_value):
                    # Specifying type for std::fill because of MSVC 14.12 warning about casting 'const int' to smaller types (C4244)
                    # For more info, see https://github.com/ros2/rosidl/issues/309
                    # TODO(jacobperron): Investigate reason for build warnings on Windows
                    # TODO(jacobperron): Write test case for this path of execution
                    strlist.append('std::fill<typename %s::iterator, %s>(this->%s.begin(), this->%s.end(), %s);' % (msg_type_to_cpp(member.type), msg_type_only_to_cpp(member.type), member.name, member.name, member.default_value[0]))
                else:
                    for index, val in enumerate(member.default_value):
                        strlist.append('this->%s[%d] = %s;' % (member.name, index, val))
            else:
                strlist.append('this->%s = %s;' % (member.name, member.default_value))

    return strlist

def generate_zero_string(membset, fill_args):
    from rosidl_generator_cpp import msg_type_only_to_cpp
    from rosidl_generator_cpp import msg_type_to_cpp
    strlist = []
    for member in membset.members:
        if isinstance(member.zero_value, list):
            if member.num_prealloc > 0:
                strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
            if member.zero_need_array_override:
                strlist.append('this->%s.fill(%s{%s});' % (member.name, msg_type_only_to_cpp(member.type), fill_args))
            else:
                # Specifying type for std::fill because of MSVC 14.12 warning about casting 'const int' to smaller types (C4244)
                # For more info, see https://github.com/ros2/rosidl/issues/309
                # TODO(jacobperron): Investigate reason for build warnings on Windows
                strlist.append('std::fill<typename %s::iterator, %s>(this->%s.begin(), this->%s.end(), %s);' % (msg_type_to_cpp(member.type), msg_type_only_to_cpp(member.type), member.name, member.name, member.zero_value[0]))
        else:
            strlist.append('this->%s = %s;' % (member.name, member.zero_value))
    return strlist
}@
  explicit @(message.structure.type.name)_(rosidl_generator_cpp::MessageInitialization _init = rosidl_generator_cpp::MessageInitialization::ALL)
@[if init_list]@
  : @(',\n    '.join(init_list))
@[end if]@
  {
@[if not member_list]@
    (void)_init;
@[end if]@
@[for membset in member_list]@
@[ if membset.members[0].default_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
    {
@[  for line in generate_default_string(membset)]@
      @(line)
@[  end for]@
@[  if membset.members[0].zero_value is not None]@
    } else if (rosidl_generator_cpp::MessageInitialization::ZERO == _init) {
@[   for line in generate_zero_string(membset, '_init')]@
      @(line)
@[   end for]@
@[  end if]@
    }
@[ elif membset.members[0].zero_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::ZERO == _init)
    {
@[  for line in generate_zero_string(membset, '_init')]@
      @(line)
@[  end for]@
    }
@[ end if]@
@[end for]@
  }

  explicit @(message.structure.type.name)_(const ContainerAllocator & _alloc, rosidl_generator_cpp::MessageInitialization _init = rosidl_generator_cpp::MessageInitialization::ALL)
@[if alloc_list]@
  : @(',\n    '.join(alloc_list))
@[end if]@
  {
@[if not member_list]@
    (void)_init;
@[end if]@
@[if not alloc_list]@
    (void)_alloc;
@[end if]@
@[for membset in member_list]@
@[ if membset.members[0].default_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
    {
@[  for line in generate_default_string(membset)]@
      @(line)
@[  end for]@
@[  if membset.members[0].zero_value is not None]@
    } else if (rosidl_generator_cpp::MessageInitialization::ZERO == _init) {
@[   for line in generate_zero_string(membset, '_alloc, _init')]@
      @(line)
@[   end for]@
@[  end if]@
    }
@[ elif membset.members[0].zero_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::ZERO == _init)
    {
@[  for line in generate_zero_string(membset, '_alloc, _init')]@
      @(line)
@[  end for]@
    }
@[ end if]@
@[end for]@
  }

  // field types and members
@[for member in message.structure.members]@
  using _@(member.name)_type =
    @(msg_type_to_cpp(member.type));
  _@(member.name)_type @(member.name);
@[end for]@

  // setters for named parameter idiom
@[for member in message.structure.members]@
  Type & set__@(member.name)(
    const @(msg_type_to_cpp(member.type)) & _arg)
  {
    this->@(member.name) = _arg;
    return *this;
  }
@[end for]@

  // constant declarations
@[for constant in message.constants.values()]@
@[ if isinstance(constant.type, BaseString)]@
  static const @(MSG_TYPE_TO_CPP['string']) @(constant.name);
@[ else]@
  static constexpr @(MSG_TYPE_TO_CPP[constant.type.type]) @(constant.name) =
@[  if isinstance(constant.type, BasicType) and constant.type.type in ['short', 'unsigned short', 'long', 'unsigned long', 'long long', 'unsigned long long', 'char', 'wchar', 'boolean', 'octet', 'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64']]@
    @(int(constant.value))@
@[   if constant.type.type.startswith('u')]@
u@
@[   end if];
@[  else]@
    @(constant.value);
@[  end if]@
@[ end if]@
@[end for]@

  // pointer types
  using RawPtr =
    @(message_typename)_<ContainerAllocator> *;
  using ConstRawPtr =
    const @(message_typename)_<ContainerAllocator> *;
  using SharedPtr =
    std::shared_ptr<@(message_typename)_<ContainerAllocator>>;
  using ConstSharedPtr =
    std::shared_ptr<@(message_typename)_<ContainerAllocator> const>;

  template<typename Deleter = std::default_delete<
      @(message_typename)_<ContainerAllocator>>>
  using UniquePtrWithDeleter =
    std::unique_ptr<@(message_typename)_<ContainerAllocator>, Deleter>;

  using UniquePtr = UniquePtrWithDeleter<>;

  template<typename Deleter = std::default_delete<
      @(message_typename)_<ContainerAllocator>>>
  using ConstUniquePtrWithDeleter =
    std::unique_ptr<@(message_typename)_<ContainerAllocator> const, Deleter>;
  using ConstUniquePtr = ConstUniquePtrWithDeleter<>;

  using WeakPtr =
    std::weak_ptr<@(message_typename)_<ContainerAllocator>>;
  using ConstWeakPtr =
    std::weak_ptr<@(message_typename)_<ContainerAllocator> const>;

  // pointer types similar to ROS 1, use SharedPtr / ConstSharedPtr instead
  // NOTE: Can't use 'using' here because GNU C++ can't parse attributes properly
  typedef @(deprecated_macro_name)
    std::shared_ptr<@(message_typename)_<ContainerAllocator>>
    Ptr;
  typedef @(deprecated_macro_name)
    std::shared_ptr<@(message_typename)_<ContainerAllocator> const>
    ConstPtr;

  // comparison operators
  bool operator==(const @(message.structure.type.name)_ & other) const
  {
@[if not message.structure.members]@
    (void)other;
@[end if]@
@[for member in message.structure.members]@
    if (this->@(member.name) != other.@(member.name)) {
      return false;
    }
@[end for]@
    return true;
  }
  bool operator!=(const @(message.structure.type.name)_ & other) const
  {
    return !this->operator==(other);
  }
};  // struct @(message.structure.type.name)_

// alias to use template instance with default allocator
using @(message.structure.type.name) =
  @(message_typename)_<std::allocator<void>>;

// constant definitions
@[for c in message.constants.values()]@
@[ if isinstance(c.type, BaseString)]@
template<typename ContainerAllocator>
const @(MSG_TYPE_TO_CPP['string'])
@(message.structure.type.name)_<ContainerAllocator>::@(c.name) = "@(escape_string(c.value))";
@[ else ]@
template<typename ContainerAllocator>
constexpr @(MSG_TYPE_TO_CPP[c.type.type]) @(message.structure.type.name)_<ContainerAllocator>::@(c.name);
@[ end if]@
@[end for]@
@
@[for ns in reversed(message.structure.type.namespaces)]@

}  // namespace @(ns)
@[end for]@


Add test args to packaging job (#25)

Add test args to packaging job (#25)

* Add test args to packaging job

* Add -- delimeter to end of test args

<?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>
    <hudson.model.ParametersDefinitionProperty>
      <parameterDefinitions>
@(SNIPPET(
    'property_parameter-definition_common',
    ci_scripts_default_branch=ci_scripts_default_branch,
    default_repos_url=default_repos_url,
    cmake_build_type=cmake_build_type,
))@
        <hudson.model.ChoiceParameterDefinition>
          <name>CI_USED_RMW_IMPL</name>
          <description/>
          <choices class="java.util.Arrays$ArrayList">

              <string>FastRTPS</string>
              <string>OpenSplice</string>

          </choices>
        </hudson.model.ChoiceParameterDefinition>
        <hudson.model.BooleanParameterDefinition>
          <name>CI_TEST_BRIDGE</name>
          <description>By setting this to True, the tests for the ros1_bridge will be run.</description>
          <defaultValue>@(test_bridge_default)</defaultValue>
        </hudson.model.BooleanParameterDefinition>
        <hudson.model.StringParameterDefinition>
          <name>CI_AMENT_TEST_ARGS</name>
          <description>Additional arguments passed to 'ament test' if testing the bridge.</description>
          <defaultValue>@(ament_test_args_default)</defaultValue>
        </hudson.model.StringParameterDefinition>
      </parameterDefinitions>
    </hudson.model.ParametersDefinitionProperty>
  </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>false</concurrentBuild>
  <builders>
    <hudson.plugins.groovy.SystemGroovy plugin="groovy@@1.30">

      <bindings/>
      <classpath/>
    </hudson.plugins.groovy.SystemGroovy>
    <hudson.tasks.@(shell_type)>
      <command>@
@[if os_name in ['linux', 'osx']]@
rm -rf ws workspace

echo "# BEGIN SECTION: Determine arguments"
export CI_ARGS="--do-venv --force-ansi-color"
if [ -n "${CI_BRANCH_TO_TEST+x}" ]; then
  export CI_ARGS="$CI_ARGS --test-branch $CI_BRANCH_TO_TEST"
fi
if [ "${CI_USED_RMW_IMPL}" = "FastRTPS" ]; then
  export CI_ARGS="$CI_ARGS --fastrtps"
elif [ "${CI_USED_RMW_IMPL}" = "OpenSplice" ]; then
  export CI_ARGS="$CI_ARGS --opensplice"
fi
if [ -n "${CI_ROS2_REPOS_URL+x}" ]; then
  export CI_ARGS="$CI_ARGS --repo-file-url $CI_ROS2_REPOS_URL"
fi
if [ "$CI_TEST_BRIDGE" = "true" ]; then
  export CI_ARGS="$CI_ARGS --test-bridge"
fi
if [ "${CI_CMAKE_BUILD_TYPE}" != "None" ]; then
  export CI_ARGS="$CI_ARGS --cmake-build-type $CI_CMAKE_BUILD_TYPE"
fi
if [ -n "${CI_AMENT_TEST_ARGS+x}" ]; then
  if [[ "$CI_AMENT_TEST_ARGS" != *-- ]]; then
    CI_AMENT_TEST_ARGS="$CI_AMENT_TEST_ARGS --"
  fi
  export CI_ARGS="$CI_ARGS --ament-test-args $CI_AMENT_TEST_ARGS --"
fi
@[if os_name == 'linux']@
export CI_ARGS="$CI_ARGS --ros1-path /opt/ros/kinetic"
@[else]@
export CI_ARGS="$CI_ARGS --ros1-path /Users/osrf/kinetic/install_isolated"
@[end if]@
echo "Using args: $CI_ARGS"
echo "# END SECTION"

@[if os_name == 'linux']@
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: Build Dockerfile"
docker build -t ros2_packaging linux_packaging_docker_resources
echo "# END SECTION"
echo "# BEGIN SECTION: Run Dockerfile"
docker run --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 ros2_packaging
echo "# END SECTION"
@[else]@
echo "# BEGIN SECTION: Run packaging script"
/usr/local/bin/python3 -u run_ros2_packaging.py $CI_ARGS
echo "# END SECTION"
@[end if]@
@[elif os_name == 'windows']@
rmdir /S /Q ws workspace

echo "# BEGIN SECTION: Determine arguments"
set "PATH=%PATH:"=%"
set "CI_ARGS=--force-ansi-color"
if "%CI_BRANCH_TO_TEST%" NEQ "" (
  set "CI_ARGS=%CI_ARGS% --test-branch %CI_BRANCH_TO_TEST%"
)
if "%CI_USED_RMW_IMPL%" EQU "FastRTPS" (
  set "CI_ARGS=%CI_ARGS% --fastrtps"
) else if "%CI_USED_RMW_IMPL%" EQU "OpenSplice" (
  set "CI_ARGS=%CI_ARGS% --opensplice"
)
if "%CI_ROS2_REPOS_URL%" NEQ "" (
  set "CI_ARGS=%CI_ARGS% --repo-file-url %CI_ROS2_REPOS_URL%"
)
if "%CI_TEST_BRIDGE%" == "true" (
  set "CI_ARGS=%CI_ARGS% --test-bridge"
)
if "%CI_CMAKE_BUILD_TYPE%" NEQ "None" (
  set "CI_ARGS=%CI_ARGS% --cmake-build-type %CI_CMAKE_BUILD_TYPE%"
)
if "%CI_AMENT_TEST_ARGS%" NEQ "" (
  if "%CI_AMENT_TEST_ARGS:~-2%" NEQ "--" (
    set "CI_AMENT_TEST_ARGS=%CI_AMENT_TEST_ARGS% --"
  )
  set "CI_ARGS=%CI_ARGS% --ament-test-args %CI_AMENT_TEST_ARGS% --"
)
echo Using args: %CI_ARGS%
echo "# END SECTION"

echo "# BEGIN SECTION: Run packaging script"
python -u run_ros2_packaging.py %CI_ARGS%
echo "# END SECTION"
@[else]@
@{ assert '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',
))@
    <hudson.tasks.ArtifactArchiver>
      <artifacts>ws/ros2-package-*.*</artifacts>
      <allowEmptyArchive>false</allowEmptyArchive>
      <onlyIfSuccessful>true</onlyIfSuccessful>
      <fingerprint>false</fingerprint>
      <defaultExcludes>true</defaultExcludes>
      <caseSensitive>true</caseSensitive>
    </hudson.tasks.ArtifactArchiver>
@[if mailer_recipients]@
    <hudson.tasks.Mailer plugin="mailer@@1.19">
      <recipients>@(mailer_recipients)</recipients>
      <dontNotifyEveryUnstableBuild>false</dontNotifyEveryUnstableBuild>
      <sendToIndividuals>false</sendToIndividuals>
    </hudson.tasks.Mailer>
@[end if]@
  </publishers>
  <buildWrappers>
    <hudson.plugins.timestamper.TimestamperBuildWrapper plugin="timestamper@@1.8.8" />
    <hudson.plugins.ansicolor.AnsiColorBuildWrapper plugin="ansicolor@@0.4.3">
      <colorMapName>xterm</colorMapName>
    </hudson.plugins.ansicolor.AnsiColorBuildWrapper>
@[if os_name != 'windows']@
    <com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper plugin="ssh-agent@@1.13">
      <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>
    <hudson.model.ParametersDefinitionProperty>
      <parameterDefinitions>
@(SNIPPET(
    'property_parameter-definition_common',
    ci_scripts_default_branch=ci_scripts_default_branch,
    default_repos_url=default_repos_url,
    cmake_build_type=cmake_build_type,
))@
        <hudson.model.ChoiceParameterDefinition>
          <name>CI_USED_RMW_IMPL</name>
          <description/>
          <choices class="java.util.Arrays$ArrayList">

              <string>FastRTPS</string>
              <string>OpenSplice</string>

          </choices>
        </hudson.model.ChoiceParameterDefinition>
        <hudson.model.BooleanParameterDefinition>
          <name>CI_TEST_BRIDGE</name>
          <description>By setting this to True, the tests for the ros1_bridge will be run.</description>
          <defaultValue>@(test_bridge_default)</defaultValue>
        </hudson.model.BooleanParameterDefinition>
      </parameterDefinitions>
    </hudson.model.ParametersDefinitionProperty>
  </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>false</concurrentBuild>
  <builders>
    <hudson.plugins.groovy.SystemGroovy plugin="groovy@@1.30">

      <bindings/>
      <classpath/>
    </hudson.plugins.groovy.SystemGroovy>
    <hudson.tasks.@(shell_type)>
      <command>@
@[if os_name in ['linux', 'osx']]@
rm -rf ws workspace

echo "# BEGIN SECTION: Determine arguments"
export CI_ARGS="--do-venv --force-ansi-color"
if [ -n "${CI_BRANCH_TO_TEST+x}" ]; then
  export CI_ARGS="$CI_ARGS --test-branch $CI_BRANCH_TO_TEST"
fi
if [ "${CI_USED_RMW_IMPL}" = "FastRTPS" ]; then
  export CI_ARGS="$CI_ARGS --fastrtps"
elif [ "${CI_USED_RMW_IMPL}" = "OpenSplice" ]; then
  export CI_ARGS="$CI_ARGS --opensplice"
fi
if [ -n "${CI_ROS2_REPOS_URL+x}" ]; then
  export CI_ARGS="$CI_ARGS --repo-file-url $CI_ROS2_REPOS_URL"
fi
if [ "$CI_TEST_BRIDGE" = "true" ]; then
  export CI_ARGS="$CI_ARGS --test-bridge"
fi
if [ "${CI_CMAKE_BUILD_TYPE}" != "None" ]; then
  export CI_ARGS="$CI_ARGS --cmake-build-type $CI_CMAKE_BUILD_TYPE"
fi
@[if os_name == 'linux']@
export CI_ARGS="$CI_ARGS --ros1-path /opt/ros/kinetic"
@[else]@
export CI_ARGS="$CI_ARGS --ros1-path /Users/osrf/kinetic/install_isolated"
@[end if]@
echo "Using args: $CI_ARGS"
echo "# END SECTION"

@[if os_name == 'linux']@
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: Build Dockerfile"
docker build -t ros2_packaging linux_packaging_docker_resources
echo "# END SECTION"
echo "# BEGIN SECTION: Run Dockerfile"
docker run --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 ros2_packaging
echo "# END SECTION"
@[else]@
echo "# BEGIN SECTION: Run packaging script"
/usr/local/bin/python3 -u run_ros2_packaging.py $CI_ARGS
echo "# END SECTION"
@[end if]@
@[elif os_name == 'windows']@
rmdir /S /Q ws workspace

echo "# BEGIN SECTION: Determine arguments"
set "PATH=%PATH:"=%"
set "CI_ARGS=--force-ansi-color"
if "%CI_BRANCH_TO_TEST%" NEQ "" (
  set "CI_ARGS=%CI_ARGS% --test-branch %CI_BRANCH_TO_TEST%"
)
if "%CI_USED_RMW_IMPL%" EQU "FastRTPS" (
  set "CI_ARGS=%CI_ARGS% --fastrtps"
) else if "%CI_USED_RMW_IMPL%" EQU "OpenSplice" (
  set "CI_ARGS=%CI_ARGS% --opensplice"
)
if "%CI_ROS2_REPOS_URL%" NEQ "" (
  set "CI_ARGS=%CI_ARGS% --repo-file-url %CI_ROS2_REPOS_URL%"
)
if "%CI_TEST_BRIDGE%" == "true" (
  set "CI_ARGS=%CI_ARGS% --test-bridge"
)
if "%CI_CMAKE_BUILD_TYPE%" NEQ "None" (
  set "CI_ARGS=%CI_ARGS% --cmake-build-type %CI_CMAKE_BUILD_TYPE%"
)
echo Using args: %CI_ARGS%
echo "# END SECTION"

echo "# BEGIN SECTION: Run packaging script"
python -u run_ros2_packaging.py %CI_ARGS%
echo "# END SECTION"
@[else]@
@{ assert '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',
))@
    <hudson.tasks.ArtifactArchiver>
      <artifacts>ws/ros2-package-*.*</artifacts>
      <allowEmptyArchive>false</allowEmptyArchive>
      <onlyIfSuccessful>true</onlyIfSuccessful>
      <fingerprint>false</fingerprint>
      <defaultExcludes>true</defaultExcludes>
      <caseSensitive>true</caseSensitive>
    </hudson.tasks.ArtifactArchiver>
@[if mailer_recipients]@
    <hudson.tasks.Mailer plugin="mailer@@1.19">
      <recipients>@(mailer_recipients)</recipients>
      <dontNotifyEveryUnstableBuild>false</dontNotifyEveryUnstableBuild>
      <sendToIndividuals>false</sendToIndividuals>
    </hudson.tasks.Mailer>
@[end if]@
  </publishers>
  <buildWrappers>
    <hudson.plugins.timestamper.TimestamperBuildWrapper plugin="timestamper@@1.8.8" />
    <hudson.plugins.ansicolor.AnsiColorBuildWrapper plugin="ansicolor@@0.4.3">
      <colorMapName>xterm</colorMapName>
    </hudson.plugins.ansicolor.AnsiColorBuildWrapper>
@[if os_name != 'windows']@
    <com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper plugin="ssh-agent@@1.13">
      <credentialIds>
        <string>1c2004f6-2e00-425d-a421-2e1ba62ca7a7</string>
      </credentialIds>
      <ignoreMissing>false</ignoreMissing>
    </com.cloudbees.jenkins.plugins.sshagent.SSHAgentBuildWrapper>
@[end if]@
  </buildWrappers>
</project>