Fix the Jenkins job authorization snippet order (#837)

<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_authorization-matrix',
    project_authorization_xml=project_authorization_xml,
))@
@(SNIPPET(
    'property_log-rotator',
    days_to_keep=730,
    num_to_keep=100,
))@
@[if job_priority is not None]@
@(SNIPPET(
    'property_job-priority',
    priority=job_priority,
))@
@[end if]@
@(SNIPPET(
    'property_rebuild-settings',
))@
@(SNIPPET(
    'property_requeue-job',
))@
@{
parameters = [
    {
        'type': 'boolean',
        'name': 'skip_cleanup',
        'description': 'Skip cleanup of build artifacts as well as rosdoc index',
    },
    {
        'type': 'string',
        'name': 'install_packages',
        'default_value': ' '.join(install_packages),
        'description': 'Package(s) to be installed prior to any packages detected for installation by rosdep (space-separated)',
    },
    {
        'type': 'string',
        'name': 'repos_file_urls',
        'default_value': ' '.join(repos_file_urls),
        'description': 'URL(s) of repos file(s) containing the list of packages to be built (space-separated)',
    },
    {
        'type': 'string',
        'name': 'repository_names',
        'default_value': ' '.join(repository_names),
        'description': 'Repositories names from the rosdistro to be built (space-separated)',
    },
    {
        'type': 'string',
        'name': 'test_branch',
        'default_value': test_branch or '',
        'description': 'Branch to attempt to checkout before doing batch job',
    },
    {
        'type': 'string',
        'name': 'package_selection_args',
        'default_value': package_selection_args or '',
        'description': 'Package selection arguments passed to colcon to specify which packages should be built and tested, or blank for ALL',
    },
    {
        'type': 'string',
        'name': 'build_tool_args',
        'default_value': build_tool_args or '',
        'description': 'Arbitrary arguments passed to the build tool',
    },
    {
        'type': 'string',
        'name': 'build_tool_test_args',
        'default_value': build_tool_test_args or '',
        'description': 'Arbitrary arguments passed to the build tool during testing',
    },
]
}@
@(SNIPPET(
    'property_parameters-definition',
    parameters=parameters,
))@
  </properties>
  <scm class="hudson.scm.NullSCM"/>
  <scmCheckoutRetryCount>2</scmCheckoutRetryCount>
  <assignedNode>@(node_label)</assignedNode>
  <canRoam>false</canRoam>
  <disabled>@('true' if disabled else 'false')</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers>
@[if trigger_jobs]@
@(SNIPPET(
    'trigger_reverse-build',
    upstream_projects=trigger_jobs,
))@
@[end if]@
@[if trigger_timer is not None]@
@(SNIPPET(
    'trigger_timer',
    spec=trigger_timer,
))@
@[end if]@
  </triggers>
  <concurrentBuild>true</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_key-files',
    script_generating_key_files=script_generating_key_files,
))@
@[if underlay_source_jobs]@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: Prepare package underlay"',
    ]),
))@
@[for i, underlay_source_job in enumerate(underlay_source_jobs, 1)]@
@(SNIPPET(
    'copy_artifacts',
    artifacts=[
      '*.tar.bz2',
    ],
    project=underlay_source_job,
    target_directory='$WORKSPACE/underlay%d' % (i),
))@
@[end for]@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'tar -xjf $WORKSPACE/underlay%d/*.tar.bz2 -C $WORKSPACE/underlay%d' %
        (i + 1, i + 1) for i in range(len(underlay_source_jobs))
    ] + [
        'echo "# END SECTION"',
    ]),
))@
@[end if]@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'rm -fr $WORKSPACE/docker_generating_dockers',
        'mkdir -p $WORKSPACE/docker_generating_dockers',
        '',
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_generating_dockers/docker.cid > $WORKSPACE/docker_generating_dockers/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# create a unique dockerfile name prefix',
        '[ -z "$EXECUTOR_NUMBER" ] && export EXECUTOR_NUMBER=0',
        'export DOCKER_IMAGE_PREFIX=executor_$EXECUTOR_NUMBER',
        '',
        '# generate Dockerfile, build and run it',
        '# generating the Dockerfiles for the actual CI tasks',
        'echo "# BEGIN SECTION: Generate Dockerfile - CI tasks"',
        'export TZ="%s"' % timezone,
        'export PYTHONPATH=$WORKSPACE/ros_buildfarm:$PYTHONPATH',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/ci/run_ci_job.py' +
        ' ' + rosdistro_name +
        ' ' + os_name +
        ' ' + os_code_name +
        ' ' + arch +
        ' ' + ' '.join(repository_args) +
        ' --build-tool ' + build_tool +
        ' --ros-version ' + str(ros_version) +
        ' --env-vars ' + ' '.join([v.replace('$', '\\$',) for v in build_environment_variables]) +
        ' --dockerfile-dir $WORKSPACE/docker_generating_dockers' +
        ' --repos-file-urls $repos_file_urls' +
        ' --repository-names $repository_names' +
        ' --test-branch "$test_branch"' +
        ' --skip-rosdep-keys ' + ' '.join(skip_rosdep_keys) +
        ' --install-packages $install_packages' +
        ' --workspace-mount-point /tmp/ws' + ''.join([
            ' /tmp/ws%d' % (i + 2) for i in range(len(underlay_source_paths))
        ]) +
        ' --package-selection-args $package_selection_args' +
        ' --build-tool-args $build_tool_args' +
        ' --build-tool-test-args $build_tool_test_args',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - generating CI tasks"',
        'cd $WORKSPACE/docker_generating_dockers',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t $DOCKER_IMAGE_PREFIX.ci_task_generation.%s .' % (rosdistro_name),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - generating CI tasks"',
        'rm -fr $WORKSPACE/docker_create_workspace',
        'rm -fr $WORKSPACE/docker_build_and_install',
        'rm -fr $WORKSPACE/docker_build_and_test',
        'mkdir -p $WORKSPACE/docker_create_workspace',
        'mkdir -p $WORKSPACE/docker_build_and_install',
        'mkdir -p $WORKSPACE/docker_build_and_test',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_generating_dockers/docker.cid' +
        ' -e=HOME=/home/buildfarm' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ' -v $WORKSPACE/docker_create_workspace:/tmp/docker_create_workspace' +
        ' -v $WORKSPACE/docker_build_and_install:/tmp/docker_build_and_install' +
        ' -v $WORKSPACE/docker_build_and_test:/tmp/docker_build_and_test' +
        ' $DOCKER_IMAGE_PREFIX.ci_task_generation.%s' % (rosdistro_name),
        'cd -',  # restore pwd when used in scripts
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_create_workspace/docker.cid > $WORKSPACE/docker_create_workspace/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# create a unique dockerfile name prefix',
        'export DOCKER_IMAGE_PREFIX=$(date +%s.%N)',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - create workspace"',
        '# build and run create_workspace Dockerfile',
        'cd $WORKSPACE/docker_create_workspace',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t $DOCKER_IMAGE_PREFIX.ci_create_workspace.%s .' % (rosdistro_name),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - create workspace"',
    ] + [
        'export UNDERLAY%d_JOB_SPACE=$WORKSPACE/underlay%d/ros%d-linux' % (i + 1, i + 1, local_ros_version)
        for i, local_ros_version in zip(range(len(underlay_source_jobs)), [ros_version] * len(underlay_source_jobs))
    ] + [
        'rm -fr $WORKSPACE/ws/src',
        'mkdir -p $WORKSPACE/ws/src',
    ] + [
        'mkdir -p %s' % (dir) for dir in underlay_source_paths
    ] + [
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_create_workspace/docker.cid' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ''.join([
            ' -v %s:/tmp/ws%s/install_isolated:ro' % (space, i if i > 1 else '')
            for i, space in enumerate(underlay_source_paths, 1)
        ]) +
        ' -v $WORKSPACE/ws:/tmp/ws%s' % (len(underlay_source_paths) + 1 if len(underlay_source_paths) else '') +
        ' $DOCKER_IMAGE_PREFIX.ci_create_workspace.%s' % (rosdistro_name),
        'cd -',  # restore pwd when used in scripts
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: Copy dependency list"',
        '/bin/cp -f $WORKSPACE/ws/install_list_build.txt $WORKSPACE/docker_build_and_install/install_list_build.txt',
        '/bin/cp -f $WORKSPACE/ws/install_list_build.txt $WORKSPACE/docker_build_and_test/install_list_build.txt',
        '/bin/cp -f $WORKSPACE/ws/install_list_test.txt $WORKSPACE/docker_build_and_test/install_list_test.txt',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_build_and_install/docker.cid > $WORKSPACE/docker_build_and_install/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# create a unique dockerfile name prefix',
        'export DOCKER_IMAGE_PREFIX=$(date +%s.%N)',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - build and install"',
        '# build and run build and install Dockerfile',
        'cd $WORKSPACE/docker_build_and_install',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t $DOCKER_IMAGE_PREFIX.ci_build_and_install.%s .' % (rosdistro_name),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: ccache stats (before)"',
        'mkdir -p $HOME/.ccache',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_install/docker_ccache_before.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_install.%s' % (rosdistro_name) +
        ' "ccache -s"',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - build and install"',
    ] + [
        'export UNDERLAY%d_JOB_SPACE=$WORKSPACE/underlay%d/ros%d-linux' % (i + 1, i + 1, local_ros_version)
        for i, local_ros_version in zip(range(len(underlay_source_jobs)), [ros_version] * len(underlay_source_jobs))
    ] + [
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_install/docker.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ''.join([
            ' -v %s:/tmp/ws%s/install_isolated:ro' % (space, i if i > 1 else '')
            for i, space in enumerate(underlay_source_paths, 1)
        ]) +
        ' -v $WORKSPACE/ws:/tmp/ws%s' % (len(underlay_source_paths) + 1 if len(underlay_source_paths) else '') +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_install.%s' % (rosdistro_name),
        'cd -',  # restore pwd when used in scripts
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: ccache stats (after)"',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_install/docker_ccache_after.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_install.%s' % (rosdistro_name) +
        ' "ccache -s"',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: Compress install space"',
        'tar -cjf $WORKSPACE/ros%d-%s-linux-%s-%s-ci.tar.bz2 ' % (ros_version, rosdistro_name, os_code_name, arch) +
        ' -C $WORKSPACE/ws' +
        ' --transform "s/^install_isolated/ros%d-linux/"' % (ros_version) +
        ' install_isolated',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_build_and_test/docker.cid > $WORKSPACE/docker_build_and_test/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# create a unique dockerfile name prefix',
        'export DOCKER_IMAGE_PREFIX=$(date +%s.%N)',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - build and test"',
        '# build and run build and test Dockerfile',
        'cd $WORKSPACE/docker_build_and_test',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t $DOCKER_IMAGE_PREFIX.ci_build_and_test.%s .' % (rosdistro_name),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: ccache stats (before)"',
        'mkdir -p $HOME/.ccache',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_test/docker_ccache_before.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_test.%s' % (rosdistro_name) +
        ' "ccache -s"',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - build and test"',
    ] + [
        'export UNDERLAY%d_JOB_SPACE=$WORKSPACE/underlay%d/ros%d-linux' % (i + 1, i + 1, local_ros_version)
        for i, local_ros_version in zip(range(len(underlay_source_jobs)), [ros_version] * len(underlay_source_jobs))
    ] + [
        'rm -fr $WORKSPACE/ws/test_results',
        'mkdir -p $WORKSPACE/ws/test_results',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_test/docker.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ''.join([
            ' -v %s:/tmp/ws%s/install_isolated:ro' % (space, i if i > 1 else '')
            for i, space in enumerate(underlay_source_paths, 1)
        ]) +
        ' -v $WORKSPACE/ws:/tmp/ws%s' % (len(underlay_source_paths) + 1 if len(underlay_source_paths) else '') +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_test.%s' % (rosdistro_name),
        'cd -',  # restore pwd when used in scripts
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: ccache stats (after)"',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_test/docker_ccache_after.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_test.%s' % (rosdistro_name) +
        ' "ccache -s"',
        '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 ws/build_isolated',
        'rm -fr ws/devel_isolated',
        'rm -fr ws/install_isolated',
        'echo "# END SECTION"',
        'fi',
    ]),
))@
  </builders>
  <publishers>
@(SNIPPET(
    'publisher_warnings',
    build_tool=build_tool,
    unstable_threshold='',
))@
@(SNIPPET(
    'archive_artifacts',
    artifacts=[
      'ros%d-%s-linux-%s-%s-ci.tar.bz2' % (ros_version, rosdistro_name, os_code_name, arch),
    ] + archive_files + [
      image for images in show_images.values() for image in images
    ],
))@
@[for title, artifacts in show_images.items()]@
@(SNIPPET(
    'image_gallery',
    title=title,
    image_width='',
    artifacts=artifacts,
))@
@[end for]@
@[if show_plots]@
@(SNIPPET(
    'plot_plugin',
    plots=show_plots,
))@
@[end if]@
@[if xunit_publisher_types]@
@(SNIPPET(
    'publisher_xunit',
    types=xunit_publisher_types,
))@
@[end if]@
  </publishers>
  <buildWrappers>
@[if timeout_minutes is not None]@
@(SNIPPET(
    'build-wrapper_build-timeout',
    timeout_minutes=timeout_minutes,
))@
@[end if]@
@(SNIPPET(
    'build-wrapper_timestamper',
))@
  </buildWrappers>
</project>

<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=730,
    num_to_keep=100,
))@
@[if job_priority is not None]@
@(SNIPPET(
    'property_job-priority',
    priority=job_priority,
))@
@[end if]@
@(SNIPPET(
    'property_rebuild-settings',
))@
@(SNIPPET(
    'property_requeue-job',
))@
@{
parameters = [
    {
        'type': 'boolean',
        'name': 'skip_cleanup',
        'description': 'Skip cleanup of build artifacts as well as rosdoc index',
    },
    {
        'type': 'string',
        'name': 'install_packages',
        'default_value': ' '.join(install_packages),
        'description': 'Package(s) to be installed prior to any packages detected for installation by rosdep (space-separated)',
    },
    {
        'type': 'string',
        'name': 'repos_file_urls',
        'default_value': ' '.join(repos_file_urls),
        'description': 'URL(s) of repos file(s) containing the list of packages to be built (space-separated)',
    },
    {
        'type': 'string',
        'name': 'repository_names',
        'default_value': ' '.join(repository_names),
        'description': 'Repositories names from the rosdistro to be built (space-separated)',
    },
    {
        'type': 'string',
        'name': 'test_branch',
        'default_value': test_branch or '',
        'description': 'Branch to attempt to checkout before doing batch job',
    },
    {
        'type': 'string',
        'name': 'package_selection_args',
        'default_value': package_selection_args or '',
        'description': 'Package selection arguments passed to colcon to specify which packages should be built and tested, or blank for ALL',
    },
    {
        'type': 'string',
        'name': 'build_tool_args',
        'default_value': build_tool_args or '',
        'description': 'Arbitrary arguments passed to the build tool',
    },
    {
        'type': 'string',
        'name': 'build_tool_test_args',
        'default_value': build_tool_test_args or '',
        'description': 'Arbitrary arguments passed to the build tool during testing',
    },
]
}@
@(SNIPPET(
    'property_parameters-definition',
    parameters=parameters,
))@
@(SNIPPET(
    'property_authorization-matrix',
    project_authorization_xml=project_authorization_xml
))@
  </properties>
  <scm class="hudson.scm.NullSCM"/>
  <scmCheckoutRetryCount>2</scmCheckoutRetryCount>
  <assignedNode>@(node_label)</assignedNode>
  <canRoam>false</canRoam>
  <disabled>@('true' if disabled else 'false')</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers>
@[if trigger_jobs]@
@(SNIPPET(
    'trigger_reverse-build',
    upstream_projects=trigger_jobs,
))@
@[end if]@
@[if trigger_timer is not None]@
@(SNIPPET(
    'trigger_timer',
    spec=trigger_timer,
))@
@[end if]@
  </triggers>
  <concurrentBuild>true</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_key-files',
    script_generating_key_files=script_generating_key_files,
))@
@[if underlay_source_jobs]@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: Prepare package underlay"',
    ]),
))@
@[for i, underlay_source_job in enumerate(underlay_source_jobs, 1)]@
@(SNIPPET(
    'copy_artifacts',
    artifacts=[
      '*.tar.bz2',
    ],
    project=underlay_source_job,
    target_directory='$WORKSPACE/underlay%d' % (i),
))@
@[end for]@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'tar -xjf $WORKSPACE/underlay%d/*.tar.bz2 -C $WORKSPACE/underlay%d' %
        (i + 1, i + 1) for i in range(len(underlay_source_jobs))
    ] + [
        'echo "# END SECTION"',
    ]),
))@
@[end if]@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'rm -fr $WORKSPACE/docker_generating_dockers',
        'mkdir -p $WORKSPACE/docker_generating_dockers',
        '',
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_generating_dockers/docker.cid > $WORKSPACE/docker_generating_dockers/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# create a unique dockerfile name prefix',
        '[ -z "$EXECUTOR_NUMBER" ] && export EXECUTOR_NUMBER=0',
        'export DOCKER_IMAGE_PREFIX=executor_$EXECUTOR_NUMBER',
        '',
        '# generate Dockerfile, build and run it',
        '# generating the Dockerfiles for the actual CI tasks',
        'echo "# BEGIN SECTION: Generate Dockerfile - CI tasks"',
        'export TZ="%s"' % timezone,
        'export PYTHONPATH=$WORKSPACE/ros_buildfarm:$PYTHONPATH',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/ci/run_ci_job.py' +
        ' ' + rosdistro_name +
        ' ' + os_name +
        ' ' + os_code_name +
        ' ' + arch +
        ' ' + ' '.join(repository_args) +
        ' --build-tool ' + build_tool +
        ' --ros-version ' + str(ros_version) +
        ' --env-vars ' + ' '.join([v.replace('$', '\\$',) for v in build_environment_variables]) +
        ' --dockerfile-dir $WORKSPACE/docker_generating_dockers' +
        ' --repos-file-urls $repos_file_urls' +
        ' --repository-names $repository_names' +
        ' --test-branch "$test_branch"' +
        ' --skip-rosdep-keys ' + ' '.join(skip_rosdep_keys) +
        ' --install-packages $install_packages' +
        ' --workspace-mount-point /tmp/ws' + ''.join([
            ' /tmp/ws%d' % (i + 2) for i in range(len(underlay_source_paths))
        ]) +
        ' --package-selection-args $package_selection_args' +
        ' --build-tool-args $build_tool_args' +
        ' --build-tool-test-args $build_tool_test_args',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - generating CI tasks"',
        'cd $WORKSPACE/docker_generating_dockers',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t $DOCKER_IMAGE_PREFIX.ci_task_generation.%s .' % (rosdistro_name),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - generating CI tasks"',
        'rm -fr $WORKSPACE/docker_create_workspace',
        'rm -fr $WORKSPACE/docker_build_and_install',
        'rm -fr $WORKSPACE/docker_build_and_test',
        'mkdir -p $WORKSPACE/docker_create_workspace',
        'mkdir -p $WORKSPACE/docker_build_and_install',
        'mkdir -p $WORKSPACE/docker_build_and_test',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_generating_dockers/docker.cid' +
        ' -e=HOME=/home/buildfarm' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ' -v $WORKSPACE/docker_create_workspace:/tmp/docker_create_workspace' +
        ' -v $WORKSPACE/docker_build_and_install:/tmp/docker_build_and_install' +
        ' -v $WORKSPACE/docker_build_and_test:/tmp/docker_build_and_test' +
        ' $DOCKER_IMAGE_PREFIX.ci_task_generation.%s' % (rosdistro_name),
        'cd -',  # restore pwd when used in scripts
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_create_workspace/docker.cid > $WORKSPACE/docker_create_workspace/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# create a unique dockerfile name prefix',
        'export DOCKER_IMAGE_PREFIX=$(date +%s.%N)',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - create workspace"',
        '# build and run create_workspace Dockerfile',
        'cd $WORKSPACE/docker_create_workspace',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t $DOCKER_IMAGE_PREFIX.ci_create_workspace.%s .' % (rosdistro_name),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - create workspace"',
    ] + [
        'export UNDERLAY%d_JOB_SPACE=$WORKSPACE/underlay%d/ros%d-linux' % (i + 1, i + 1, local_ros_version)
        for i, local_ros_version in zip(range(len(underlay_source_jobs)), [ros_version] * len(underlay_source_jobs))
    ] + [
        'rm -fr $WORKSPACE/ws/src',
        'mkdir -p $WORKSPACE/ws/src',
    ] + [
        'mkdir -p %s' % (dir) for dir in underlay_source_paths
    ] + [
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_create_workspace/docker.cid' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ''.join([
            ' -v %s:/tmp/ws%s/install_isolated:ro' % (space, i if i > 1 else '')
            for i, space in enumerate(underlay_source_paths, 1)
        ]) +
        ' -v $WORKSPACE/ws:/tmp/ws%s' % (len(underlay_source_paths) + 1 if len(underlay_source_paths) else '') +
        ' $DOCKER_IMAGE_PREFIX.ci_create_workspace.%s' % (rosdistro_name),
        'cd -',  # restore pwd when used in scripts
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: Copy dependency list"',
        '/bin/cp -f $WORKSPACE/ws/install_list_build.txt $WORKSPACE/docker_build_and_install/install_list_build.txt',
        '/bin/cp -f $WORKSPACE/ws/install_list_build.txt $WORKSPACE/docker_build_and_test/install_list_build.txt',
        '/bin/cp -f $WORKSPACE/ws/install_list_test.txt $WORKSPACE/docker_build_and_test/install_list_test.txt',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_build_and_install/docker.cid > $WORKSPACE/docker_build_and_install/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# create a unique dockerfile name prefix',
        'export DOCKER_IMAGE_PREFIX=$(date +%s.%N)',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - build and install"',
        '# build and run build and install Dockerfile',
        'cd $WORKSPACE/docker_build_and_install',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t $DOCKER_IMAGE_PREFIX.ci_build_and_install.%s .' % (rosdistro_name),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: ccache stats (before)"',
        'mkdir -p $HOME/.ccache',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_install/docker_ccache_before.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_install.%s' % (rosdistro_name) +
        ' "ccache -s"',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - build and install"',
    ] + [
        'export UNDERLAY%d_JOB_SPACE=$WORKSPACE/underlay%d/ros%d-linux' % (i + 1, i + 1, local_ros_version)
        for i, local_ros_version in zip(range(len(underlay_source_jobs)), [ros_version] * len(underlay_source_jobs))
    ] + [
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_install/docker.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ''.join([
            ' -v %s:/tmp/ws%s/install_isolated:ro' % (space, i if i > 1 else '')
            for i, space in enumerate(underlay_source_paths, 1)
        ]) +
        ' -v $WORKSPACE/ws:/tmp/ws%s' % (len(underlay_source_paths) + 1 if len(underlay_source_paths) else '') +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_install.%s' % (rosdistro_name),
        'cd -',  # restore pwd when used in scripts
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: ccache stats (after)"',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_install/docker_ccache_after.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_install.%s' % (rosdistro_name) +
        ' "ccache -s"',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        'echo "# BEGIN SECTION: Compress install space"',
        'tar -cjf $WORKSPACE/ros%d-%s-linux-%s-%s-ci.tar.bz2 ' % (ros_version, rosdistro_name, os_code_name, arch) +
        ' -C $WORKSPACE/ws' +
        ' --transform "s/^install_isolated/ros%d-linux/"' % (ros_version) +
        ' install_isolated',
        'echo "# END SECTION"',
    ]),
))@
@(SNIPPET(
    'builder_shell',
    script='\n'.join([
        '# monitor all subprocesses and enforce termination',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/subprocess_reaper.py $$ --cid-file $WORKSPACE/docker_build_and_test/docker.cid > $WORKSPACE/docker_build_and_test/subprocess_reaper.log 2>&1 &',
        '# sleep to give python time to startup',
        'sleep 1',
        '',
        '# create a unique dockerfile name prefix',
        'export DOCKER_IMAGE_PREFIX=$(date +%s.%N)',
        '',
        'echo "# BEGIN SECTION: Build Dockerfile - build and test"',
        '# build and run build and test Dockerfile',
        'cd $WORKSPACE/docker_build_and_test',
        'python3 -u $WORKSPACE/ros_buildfarm/scripts/misc/docker_pull_baseimage.py',
        'docker build --force-rm -t $DOCKER_IMAGE_PREFIX.ci_build_and_test.%s .' % (rosdistro_name),
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: ccache stats (before)"',
        'mkdir -p $HOME/.ccache',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_test/docker_ccache_before.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_test.%s' % (rosdistro_name) +
        ' "ccache -s"',
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: Run Dockerfile - build and test"',
    ] + [
        'export UNDERLAY%d_JOB_SPACE=$WORKSPACE/underlay%d/ros%d-linux' % (i + 1, i + 1, local_ros_version)
        for i, local_ros_version in zip(range(len(underlay_source_jobs)), [ros_version] * len(underlay_source_jobs))
    ] + [
        'rm -fr $WORKSPACE/ws/test_results',
        'mkdir -p $WORKSPACE/ws/test_results',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_test/docker.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' -v $WORKSPACE/ros_buildfarm:/tmp/ros_buildfarm:ro' +
        ''.join([
            ' -v %s:/tmp/ws%s/install_isolated:ro' % (space, i if i > 1 else '')
            for i, space in enumerate(underlay_source_paths, 1)
        ]) +
        ' -v $WORKSPACE/ws:/tmp/ws%s' % (len(underlay_source_paths) + 1 if len(underlay_source_paths) else '') +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_test.%s' % (rosdistro_name),
        'cd -',  # restore pwd when used in scripts
        'echo "# END SECTION"',
        '',
        'echo "# BEGIN SECTION: ccache stats (after)"',
        'docker run' +
        ' --rm ' +
        ' --cidfile=$WORKSPACE/docker_build_and_test/docker_ccache_after.cid' +
        ' -e CCACHE_DIR=/home/buildfarm/.ccache' +
        ' -v $HOME/.ccache:/home/buildfarm/.ccache' +
        ' $DOCKER_IMAGE_PREFIX.ci_build_and_test.%s' % (rosdistro_name) +
        ' "ccache -s"',
        '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 ws/build_isolated',
        'rm -fr ws/devel_isolated',
        'rm -fr ws/install_isolated',
        'echo "# END SECTION"',
        'fi',
    ]),
))@
  </builders>
  <publishers>
@(SNIPPET(
    'publisher_warnings',
    build_tool=build_tool,
    unstable_threshold='',
))@
@(SNIPPET(
    'archive_artifacts',
    artifacts=[
      'ros%d-%s-linux-%s-%s-ci.tar.bz2' % (ros_version, rosdistro_name, os_code_name, arch),
    ] + archive_files + [
      image for images in show_images.values() for image in images
    ],
))@
@[for title, artifacts in show_images.items()]@
@(SNIPPET(
    'image_gallery',
    title=title,
    image_width='',
    artifacts=artifacts,
))@
@[end for]@
@[if show_plots]@
@(SNIPPET(
    'plot_plugin',
    plots=show_plots,
))@
@[end if]@
@[if xunit_publisher_types]@
@(SNIPPET(
    'publisher_xunit',
    types=xunit_publisher_types,
))@
@[end if]@
  </publishers>
  <buildWrappers>
@[if timeout_minutes is not None]@
@(SNIPPET(
    'build-wrapper_build-timeout',
    timeout_minutes=timeout_minutes,
))@
@[end if]@
@(SNIPPET(
    'build-wrapper_timestamper',
))@
  </buildWrappers>
</project>


Can now use gui to send actions over network to visibles.

(function()
 {

     /**
      @param {std.ScriptingGui.Controller}

      @param {object: <String(visibleId):visible object>} nearbyVisMap
      -- all the visible objects that satisfy scripter's proximity
      query.

      @param {object: <String(visibleId):
      std.FileManager.FileManagerElement> scriptedVisMap -- A record
      of all visibles that we have scripted at some point.

      @param {object: <int:std.ScriptingGui.Action> actionMap -- Which
      actions are selectable by scripter.

      @param {std.ScriptingGui.Console} console -- has several
      scripting events.
      */
     std.ScriptingGui =
         function(controller,nearbyVisMap,scriptedVisMap,actionMap,console)
     {
         if (typeof(simulator) == 'undefined')
         {
             throw new Error('Cannot initialize scripting gui without ' +
                             'simulator graphics.');
         }

         this.controller       = controller;
         this.nearbyVisMap     = nearbyVisMap;
         this.scriptedVisMap   = scriptedVisMap;
         this.actionMap        = actionMap;
         this.console          = console;

         this.guiMod = simulator._simulator.addGUITextModule(
             guiName(),
             getGuiText(),
             std.core.bind(guiInitFunc,undefined,this));
         this.hasInited = false;
     };

     system.require('scriptingGuiUtil.em');

     std.ScriptingGui.prototype.redraw = function()
     {
         if (!this.hasInited)
             return;

         //trigger redraw call
         this.guiMod.call(
             'ishmaelRedraw',toHtmlNearbyMap(this),toHtmlScriptedMap(this),
             toHtmlActionMap(this));

     };

     /**
      @param {String} visId -- Id of visible.
      */
     //called by html to add the visible with id
     std.ScriptingGui.prototype.hAddVisible = function(visId)
     {
         //already can script the visible.
         if (visId in this.scriptedVisMap)
         {
             this.console.guiEvent();
             this.redraw();
             return;
         }

         if (!(visId in this.nearbyVisMap))
         {
             //visible is no longer available.
             this.console.guiEvent();
             this.redraw();
             return;
         }

         //redraw called from inside of addVisible.
         this.controller.addVisible(this.nearbyVisMap[visId]);
     };

     std.ScriptingGui.prototype.hRemoveVisible = function(visId)
     {
         //FIXME: should finish this call
         throw new Error('FIXME: must finish hRemoveVisible call ' +
                         'in scriptingGui');
     };

     /**
      @param {String?} actId -- Should be parsedInt to get an index
      into actionMap
      @param {String} newText -- What action with actId should set as
      its text.
      */
     std.ScriptingGui.prototype.hSaveAction = function(actId,newText)
     {
         this.controller.editAction(parseInt(actId),newText);
     };

     /**
      @param {String?} actId -- Should be parsedInt to get an index
      into actionMap
      @param {String} newText -- What action with actId should set as
      its text.
      @param {String} visId   -- Id of visible to execute action on.
      */
     std.ScriptingGui.prototype.hSaveAndExecuteAction =
         function(actId,newText, visId)
     {
         this.hSaveAction(actId,newText);
         this.controller.execAction(actId,visId);
     };

     // //whenever user selects an action to display, then we change
     // //model of internal action that should be displaying.
     // std.ScriptingGui.prototype.hActionSelected = function(actId)
     // {
     //     if(actId in this.actionMap)
     //         this.selectedAction = this.actionMap[actId];
     //     else
     //         this.selectedAction = undefined;
     // };

     /**
      @param {std.ScriptingGui}
      */
     function guiInitFunc(scriptingGui)
     {
         scriptingGui.hasInited = true;

         //when a user clicks on any of the nearby visibles to script
         //them, want that object to move into scripted objects.
         scriptingGui.guiMod.bind(
             'addVisible',
             std.core.bind(scriptingGui.hAddVisible,scriptingGui));

         //when a user clicks to remove any of the scripted visibles
         //from scripted map, then destroy it.
         scriptingGui.guiMod.bind(
             'removeVisible',
             std.core.bind(scriptingGui.hRemoveVisible,scriptingGui));

         //when a user updates a particular action, and clicks to save
         //the new action text.
         scriptingGui.guiMod.bind(
             'saveAction',
             std.core.bind(scriptingGui.hSaveAction,scriptingGui));

         //saves and executes action to visible.
         scriptingGui.guiMod.bind(
             'saveAndExecuteAction',
             std.core.bind(scriptingGui.hSaveAndExecuteAction,scriptingGui));

         scriptingGui.redraw();
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlNearbyMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.nearbyVisMap)
             returner[s] = s;
         return returner;
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlScriptedMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.scriptedVisMap)
             returner[s] = s;
         return returner;
     }

     function toHtmlActionMap(scriptingGui)
     {
         return scriptingGui.actionMap;
     }

     function guiName()
     {
         return 'ishmaelEditor';
     }

     function getGuiText()
     {

         var returner = "sirikata.ui('" + guiName() + "',";
         returner += 'function(){ ';

         returner += @

         function ishmaelWindowId()
         {
             return 'ishmael__windowID_';
         }

         //the div that surrounds all the nearby objects.
         function nearbyListId()
         {
             return 'ishmael__nearbyListID__';
         }

         //the div that surrounds all the scripted objects.
         function scriptedListId()
         {
             return 'ishmael__scriptedListID__';
         }

         function actionListId()
         {
             return 'ishmael__actionListID__';
         }

         function actionTareaId()
         {
             return 'ishmael__actionEditor__';
         }

         function saveActionButtonId()
         {
             return 'ishmael__saveActionButton__';
         }

         function execActionButtonId()
         {
             return 'ishmael__execActionButton__';
         }

         /**
          \param {String} nearbyObj (id of visible that we are
          communicating with).
          gives the div for each nearby object.
          */
         function generateNearbyDivId(nearbyObj)
         {
             var visIdDivable = divizeVisibleId(nearbyObj);
             return 'ishmael__nearbyDivID___' + visIdDivable;
         }

         /**
          \param {String} scriptedObj (id of visible that we are
          communicating with).
          gives the div for each scripted object.
          */
         function generateScriptedDivId(scriptedObj)
         {
             var visIdDivable = divizeVisibleId(scriptedObj);
             return 'ishmael__scriptedDivID___' + visIdDivable;
         }

         function divizeVisibleId(visId)
         {
             return visId.replace(':','');
         }

         $('
'   +

           'Scripted presences
' +
           '<select id="'+ scriptedListId() + '"  size=5>' +
           '</select>
'  +

           'Nearby presences
'      +
           '<select id="'+ nearbyListId() + '"  size=5>' +
           '</select>
'  +

           '<select id="' + actionListId() + '" size=5>'   +
           '</select>' +

           '<textarea id="'+ actionTareaId() + '"  >' +
           '</textarea>' +

           '<button id="' + saveActionButtonId() + '">' +
           'save action' +
           '</button>' +

           '<button id="' + execActionButtonId() + '">' +
           'exec&save action' +
           '</button>' +

           '
' //end div at top.
          ).attr({id:ishmaelWindowId(),title:'ishmael'}).appendTo('body');

         //The id of the visible that the scripter has selected to
         //program.
         var currentlySelectedVisible = undefined;

         //int id of the currently selected action.
         var currentlySelectedAction = undefined;
         //map from int to std.ScriptingGui.Action objects.  It gets
         //updated whenever we received an ishmaelRedraw call.  Note
         //that the redraw call will not write over the text of
         //currentlySelectedAction.  This ensures that scripter
         //edits will not be lost while they are being written if some
         //other action triggers a call to ishmaelRedraw (for
         //instance, a new nearbyObject gets added).
         var allActions = undefined;

         $('#' + scriptedListId()).change(
             function()
             {
                 //loads the visible id
                 var val = $('#' + scriptedListId()).val();
                 currentlySelectedVisible = val;

                 //for debugging
                 sirikata.log(
                     'error','Selected new vis to script: ' + val.toString());

                 //if we change which visible we're scripting from the
                 //scripting selection menu, we want that change to be
                 //reflected in the nearby selection list.
                 updateNearbySelection(val.toString());
             });

         //set a listener for action list.  whenever select an option,
         //should communicate that to emerson gui, so that can keep
         //track of selected action.
         $('#' + actionListId()).change(
             function()
             {
                 var val =
                     $('#' + actionListId()).val();
                 changeActionText(parseInt(val));
                 sirikata.log('error', 'Selected action: '  + val.toString());
             });

         $('#' + nearbyListId()).change(
             function()
             {
                 var val = $('#'+nearbyListId()).val();
                 currentlySelectedVisible = val;
                 sirikata.event('addVisible',val);
             });

         //when hit save, sends the action text through to controller
         //to save it.
         $('#' + saveActionButtonId()).click(
             function()
             {
                 //no action is selected
                 if ((typeof(currentlySelectedAction) == 'undefined') ||
                     (currentlySelectedAction === null))
                     return;

                 var toSaveText = $('#' + actionTareaId()).val();

                 //saving action does not force a redraw.  must
                 //preserve new text in allActions on our end. (takes
                 //care of failure case where save an action, then
                 //click on another action, then return to current
                 //action).
                 allActions[currentlySelectedAction].text = toSaveText;

                 sirikata.event(
                     'saveAction',currentlySelectedAction,toSaveText);
             });

         //saves and executes current action
         $('#' + execActionButtonId()).click(
             function()
             {
                 if ((typeof(currentlySelectedAction)  == 'undefined') ||
                     (typeof(currentlySelectedVisible) == 'undefined'))
                 {
                     sirikata.log(
                         'error','Cannot execute action.  ' +
                             'No vis or action selected.');
                     return;
                 }

                 //see comments in click handler for saveActionButton.
                 var toSaveText = $('#' + actionTareaId()).val();
                 allActions[currentlySelectedAction].text = toSaveText;
                 sirikata.event(
                     'saveAndExecuteAction',currentlySelectedAction,
                     toSaveText,currentlySelectedVisible);
             });

         var inputWindow = new sirikata.ui.window(
             '#' + ishmaelWindowId(),
                 {
	             autoOpen: true,
	             height: 'auto',
	             width: 600,
                     height: 600,
                     position: 'right'
                 }
             );
         inputWindow.show();

         /**
          changes selection in updateNearby to the one associated with
          visibleId (if it's available).  If it's not, then we just
          unselect.

          Right now, we take a performance hit, because the selection
          change that we do here will trigger the .change handler
          associated with nearbyList.  Should still maintain semantics
          though.
          */
         function updateNearbySelection(visibleId)
         {
             var nearbyOption = $('#' + generateNearbyDivId(visibleId));
             if (nearbyOption.size())
             {
                 //means that the element did exist.  now want it to
                 //appear selected in nearbyList.
                 var nearbyVal = nearbyOption.val();
                 $('#' + nearbyListId()).val(nearbyVal);
             }
             else
             {
                 var errMsg =
                     'In updatenearbyselection attempting '+
                     'to set selector to none.';

                 sirikatal.log('error',errMsg);
                 $('#' + nearbyListId()).val(null);
             }
         }

         /**
          \param {int or undefined} idActSelected.  If an int, then
          looks through record of allActions, and sets action text
          area to that.  If undefined, then clears action text area.
          */
         function changeActionText(idActSelected)
         {
             currentlySelectedAction = idActSelected;
             var textToSetTo = '';

             if (typeof(idActSelected) !='undefined')
             {
                 if (! idActSelected in allActions)
                 {
                     sirikata.log('error','action ids out of ' +
                                  'sync with actions in scripting gui.');
                     return;
                 }
                 textToSetTo = allActions[idActSelected].text;
             }

             //actually update textarea with correct text
             $('#' + actionTareaId()).val(textToSetTo);
         }

         /**
          \param {object: <int:std.ScriptingGui.Action>} actionMap

          FIXEM: currentlySelectedAction is no longer passed. Instead,
          maintain it in html/js

          \param {int or undefined} currentlySelectedAction -- null if
          do not have a currently selected action.  the id of the
          action that is currently selected otherwise.  this id can be
          used to index into actionMap
          */
         ishmaelRedraw = function(
             nearbyObjs,scriptedObjs,actionMap)
         {
             redrawNearby(nearbyObjs);
             redrawScriptedObjs(scriptedObjs);
             redrawActionList(actionMap);
         };

         /**
          \param {object: <string (visibleId): string (visibleId)>}
          nearbyObjs -- all objects that are in vicinity.
          */
         function redrawNearby(nearbyObjs)
         {
             var newHtml = '';
             for (var s in nearbyObjs)
             {
                 if (s===currentlySelectedVisible)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '" ';
                 newHtml += 'id="' + generateNearbyDivId(s) + '">';
                 newHtml += s;
                 newHtml += '</option>';
             }
             $('#' + nearbyListId()).html(newHtml);
         }

         /**
          \param {object: <string (visibleId): string(visibleId)>}
          scriptedObjs -- all objects that we have a scripting
          relationship with.
          */
         function redrawScriptedObjs(scriptedObjs)
         {
             var newHtml = '';
             for (var s in scriptedObjs)
             {
                 if (s === currentlySelectedVisible)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' +s +  '">';
                 newHtml += s;
                 newHtml += '</option>';
             }
             $('#' + scriptedListId()).html(newHtml);
         }

         function redrawActionList(actionMap)
         {
             var prevCurAct = null;
             if (typeof(currentlySelectedAction) != 'undefined')
             {
                 prevCurAct = allActions[currentlySelectedAction];
                 //update with text that had entered in tarea.
                 prevCurAct.text = $('#' + actionTareaId()).val();
             }

             allActions = actionMap;
             //preserves edits that scripter was potentially making
             //when other action triggered redraw (eg. a new nearby
             //object).
             if (prevCurAct !== null)
                 allActions[prevCurAct.id] = prevCurAct;

             var newHtml = '';
             for (var s in actionMap)
             {
                 if (parseInt(s) === parseInt(currentlySelectedAction))
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '">';
                 newHtml += actionMap[s].name ;
                 newHtml += '</option>';
             }

             $('#' + actionListId()).html(newHtml);
         }

         @;

         returner += '});';
         return returner;
     }
 })();

//do all further imports for file and gui control.
system.require('controller.em');
system.require('action.em');
system.require('console.em');
system.require('fileManagerElement.em');

(function()
 {

     /**
      @param {std.ScriptingGui.Controller}

      @param {object: <String(visibleId):visible object>} nearbyVisMap
      -- all the visible objects that satisfy scripter's proximity
      query.

      @param {object: <String(visibleId):
      std.FileManager.FileManagerElement> scriptedVisMap -- A record
      of all visibles that we have scripted at some point.

      @param {object: <int:std.ScriptingGui.Action> actionMap -- Which
      actions are selectable by scripter.

      @param {std.ScriptingGui.Console} console -- has several
      scripting events.
      */
     std.ScriptingGui =
         function(controller,nearbyVisMap,scriptedVisMap,actionMap,console)
     {
         if (typeof(simulator) == 'undefined')
         {
             throw new Error('Cannot initialize scripting gui without ' +
                             'simulator graphics.');
         }

         this.controller       = controller;
         this.nearbyVisMap     = nearbyVisMap;
         this.scriptedVisMap   = scriptedVisMap;
         this.actionMap        = actionMap;
         this.console          = console;

         this.guiMod = simulator._simulator.addGUITextModule(
             guiName(),
             getGuiText(),
             std.core.bind(guiInitFunc,undefined,this));
         this.hasInited = false;
     };

     system.require('scriptingGuiUtil.em');

     std.ScriptingGui.prototype.redraw = function()
     {
         if (!this.hasInited)
             return;

         //trigger redraw call
         this.guiMod.call(
             'ishmaelRedraw',toHtmlNearbyMap(this),toHtmlScriptedMap(this),
             toHtmlActionMap(this));

     };

     /**
      @param {String} visId -- Id of visible.
      */
     //called by html to add the visible with id
     std.ScriptingGui.prototype.hAddVisible = function(visId)
     {
         //already can script the visible.
         if (visId in this.scriptedVisMap)
         {
             this.console.guiEvent();
             this.redraw();
             return;
         }

         if (!(visId in this.nearbyVisMap))
         {
             //visible is no longer available.
             this.console.guiEvent();
             this.redraw();
             return;
         }

         //redraw called from inside of addVisible.
         this.controller.addVisible(this.nearbyVisMap[visId]);
     };

     std.ScriptingGui.prototype.hRemoveVisible = function(visId)
     {
         //FIXME: should finish this call
         throw new Error('FIXME: must finish hRemoveVisible call ' +
                         'in scriptingGui');
     };

     /**
      @param {String?} actId -- Should be parsedInt to get an index
      into actionMap
      @param {String} newText -- What action with actId should set as
      its text.
      */
     std.ScriptingGui.prototype.hSaveAction = function(actId,newText)
     {
         this.controller.editAction(parseInt(actId),newText);
     };

     // //whenever user selects an action to display, then we change
     // //model of internal action that should be displaying.
     // std.ScriptingGui.prototype.hActionSelected = function(actId)
     // {
     //     if(actId in this.actionMap)
     //         this.selectedAction = this.actionMap[actId];
     //     else
     //         this.selectedAction = undefined;
     // };

     /**
      @param {std.ScriptingGui}
      */
     function guiInitFunc(scriptingGui)
     {
         scriptingGui.hasInited = true;

         //when a user clicks on any of the nearby visibles to script
         //them, want that object to move into scripted objects.
         scriptingGui.guiMod.bind(
             'addVisible',
             std.core.bind(scriptingGui.hAddVisible,scriptingGui));

         //when a user clicks to remove any of the scripted visibles
         //from scripted map, then destroy it.
         scriptingGui.guiMod.bind(
             'removeVisible',
             std.core.bind(scriptingGui.hRemoveVisible,scriptingGui));

         //when a user updates a particular action, and clicks to save
         //the new action text.
         scriptingGui.guiMod.bind(
             'saveAction',
             std.core.bind(scriptingGui.hSaveAction,scriptingGui));

         scriptingGui.redraw();
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlNearbyMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.nearbyVisMap)
             returner[s] = s;
         return returner;
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlScriptedMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.scriptedVisMap)
             returner[s] = s;
         return returner;
     }

     function toHtmlActionMap(scriptingGui)
     {
         return scriptingGui.actionMap;
     }

     function guiName()
     {
         return 'ishmaelEditor';
     }

     function getGuiText()
     {

         var returner = "sirikata.ui('" + guiName() + "',";
         returner += 'function(){ ';

         returner += @

         function ishmaelWindowId()
         {
             return 'ishmael__windowID_';
         }

         //the div that surrounds all the nearby objects.
         function nearbyListId()
         {
             return 'ishmael__nearbyListID__';
         }

         //the div that surrounds all the scripted objects.
         function scriptedListId()
         {
             return 'ishmael__scriptedListID__';
         }

         function actionListId()
         {
             return 'ishmael__actionListID__';
         }

         function actionTareaId()
         {
             return 'ishmael__actionEditor__';
         }

         function saveActionButtonId()
         {
             return 'ishmael__saveActionButton__';
         }

         /**
          \param {String} nearbyObj (id of visible that we are
          communicating with).
          gives the div for each nearby object.
          */
         function generateNearbyDivId(nearbyObj)
         {
             var visIdDivable = divizeVisibleId(nearbyObj);
             return 'ishmael__nearbyDivID___' + visIdDivable;
         }

         /**
          \param {String} scriptedObj (id of visible that we are
          communicating with).
          gives the div for each scripted object.
          */
         function generateScriptedDivId(scriptedObj)
         {
             var visIdDivable = divizeVisibleId(scriptedObj);
             return 'ishmael__scriptedDivID___' + visIdDivable;
         }

         function divizeVisibleId(visId)
         {
             return visId.replace(':','');
         }

         $('
'   +

           'Scripted presences
' +
           '<select id="'+ scriptedListId() + '"  size=5>' +
           '</select>
'  +

           'Nearby presences
'      +
           '<select id="'+ nearbyListId() + '"  size=5>' +
           '</select>
'  +

           '<select id="' + actionListId() + '" size=5>'   +
           '</select>' +

           '<textarea id="'+ actionTareaId() + '"  >' +
           '</textarea>' +

           '<button id="' + saveActionButtonId() + '">' +
           'save action' +
           '</button>' +

           '
' //end div at top.
          ).attr({id:ishmaelWindowId(),title:'ishmael'}).appendTo('body');

         //The id of the visible that the scripter has selected to
         //program.
         var currentlySelectedVisible = undefined;

         //int id of the currently selected action.
         var currentlySelectedAction = undefined;
         //map from int to std.ScriptingGui.Action objects.  It gets
         //updated whenever we received an ishmaelRedraw call.  Note
         //that the redraw call will not write over the text of
         //currentlySelectedAction.  This ensures that scripter
         //edits will not be lost while they are being written if some
         //other action triggers a call to ishmaelRedraw (for
         //instance, a new nearbyObject gets added).
         var allActions = undefined;

         $('#' + scriptedListId()).change(
             function()
             {
                 //loads the visible id
                 var val = $('#' + scriptedListId()).val();
                 currentlySelectedVisible = val;

                 //for debugging
                 sirikata.log(
                     'error','Selected new vis to script: ' + val.toString());

                 //if we change which visible we're scripting from the
                 //scripting selection menu, we want that change to be
                 //reflected in the nearby selection list.
                 updateNearbySelection(val.toString());
             });

         //set a listener for action list.  whenever select an option,
         //should communicate that to emerson gui, so that can keep
         //track of selected action.
         $('#' + actionListId()).change(
             function()
             {
                 var val =
                     $('#' + actionListId()).val();
                 changeActionText(parseInt(val));
                 sirikata.log('error', 'Selected action: '  + val.toString());
             });

         $('#' + nearbyListId()).change(
             function()
             {
                 var val = $('#'+nearbyListId()).val();
                 currentlySelectedVisible = val;
                 sirikata.event('addVisible',val);
             });

         //when hit save, sends the action text through to controller
         //to save it.
         $('#' + saveActionButtonId()).click(
             function()
             {
                 //no action is selected
                 if ((typeof(currentlySelectedAction) == 'undefined') ||
                     (currentlySelectedAction === null))
                     return;

                 var toSaveText = $('#' + actionTareaId()).val();

                 //saving action does not force a redraw.  must
                 //preserve new text in allActions on our end. (takes
                 //care of failure case where save an action, then
                 //click on another action, then return to current
                 //action).
                 allActions[currentlySelectedAction].text = toSaveText;

                 sirikata.event(
                     'saveAction',currentlySelectedAction,toSaveText);
             });

         var inputWindow = new sirikata.ui.window(
             '#' + ishmaelWindowId(),
                 {
	             autoOpen: true,
	             height: 'auto',
	             width: 600,
                     height: 600,
                     position: 'right'
                 }
             );
         inputWindow.show();

         /**
          changes selection in updateNearby to the one associated with
          visibleId (if it's available).  If it's not, then we just
          unselect.

          Right now, we take a performance hit, because the selection
          change that we do here will trigger the .change handler
          associated with nearbyList.  Should still maintain semantics
          though.
          */
         function updateNearbySelection(visibleId)
         {
             var nearbyOption = $('#' + generateNearbyDivId(visibleId));
             if (nearbyOption.size())
             {
                 //means that the element did exist.  now want it to
                 //appear selected in nearbyList.
                 var nearbyVal = nearbyOption.val();
                 $('#' + nearbyListId()).val(nearbyVal);
             }
             else
             {
                 var errMsg =
                     'In updatenearbyselection attempting '+
                     'to set selector to none.';

                 sirikatal.log('error',errMsg);
                 $('#' + nearbyListId()).val(null);
             }
         }

         /**
          \param {int or undefined} idActSelected.  If an int, then
          looks through record of allActions, and sets action text
          area to that.  If undefined, then clears action text area.
          */
         function changeActionText(idActSelected)
         {
             currentlySelectedAction = idActSelected;
             var textToSetTo = '';

             if (typeof(idActSelected) !='undefined')
             {
                 if (! idActSelected in allActions)
                 {
                     sirikata.log('error','action ids out of ' +
                                  'sync with actions in scripting gui.');
                     return;
                 }
                 textToSetTo = allActions[idActSelected].text;
             }

             //actually update textarea with correct text
             $('#' + actionTareaId()).val(textToSetTo);
         }

         /**
          \param {object: <int:std.ScriptingGui.Action>} actionMap

          FIXEM: currentlySelectedAction is no longer passed. Instead,
          maintain it in html/js

          \param {int or undefined} currentlySelectedAction -- null if
          do not have a currently selected action.  the id of the
          action that is currently selected otherwise.  this id can be
          used to index into actionMap
          */
         ishmaelRedraw = function(
             nearbyObjs,scriptedObjs,actionMap)
         {
             redrawNearby(nearbyObjs);
             redrawScriptedObjs(scriptedObjs);
             redrawActionList(actionMap);
         };

         /**
          \param {object: <string (visibleId): string (visibleId)>}
          nearbyObjs -- all objects that are in vicinity.
          */
         function redrawNearby(nearbyObjs)
         {
             var newHtml = '';
             for (var s in nearbyObjs)
             {
                 if (s===currentlySelectedVisible)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '" ';
                 newHtml += 'id="' + generateNearbyDivId(s) + '">';
                 newHtml += s;
                 newHtml += '</option>';
             }
             $('#' + nearbyListId()).html(newHtml);
         }

         /**
          \param {object: <string (visibleId): string(visibleId)>}
          scriptedObjs -- all objects that we have a scripting
          relationship with.
          */
         function redrawScriptedObjs(scriptedObjs)
         {
             var newHtml = '';
             for (var s in scriptedObjs)
             {
                 if (s === currentlySelectedVisible)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' +s +  '">';
                 newHtml += s;
                 newHtml += '</option>';
             }
             $('#' + scriptedListId()).html(newHtml);
         }

         function redrawActionList(actionMap)
         {
             var prevCurAct = null;
             if (typeof(currentlySelectedAction) != 'undefined')
             {
                 prevCurAct = allActions[currentlySelectedAction];
                 //update with text that had entered in tarea.
                 prevCurAct.text = $('#' + actionTareaId()).val();
             }

             allActions = actionMap;
             //preserves edits that scripter was potentially making
             //when other action triggered redraw (eg. a new nearby
             //object).
             if (prevCurAct !== null)
                 allActions[prevCurAct.id] = prevCurAct;

             var newHtml = '';
             for (var s in actionMap)
             {
                 if (parseInt(s) === parseInt(currentlySelectedAction))
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '">';
                 newHtml += actionMap[s].name ;
                 newHtml += '</option>';
             }

             $('#' + actionListId()).html(newHtml);
         }

         @;

         returner += '});';
         return returner;
     }
 })();

//do all further imports for file and gui control.
system.require('controller.em');
system.require('action.em');
system.require('console.em');
system.require('fileManagerElement.em');