rebuild dependency graph after reconfiguring jobs

import difflib.DiffUtils
import groovy.io.FileType
import hudson.AbortException
import hudson.model.View
import java.io.StringBufferInputStream
import java.io.StringWriter
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.stream.StreamSource
import jenkins.model.Jenkins
import org.apache.xml.serialize.OutputFormat
import org.apache.xml.serialize.XMLSerializer
import org.xml.sax.InputSource

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

println '# BEGIN SECTION: Groovy script - reconfigure'
dry_run = @('true' if dry_run else 'false')
dry_run_suffix = dry_run ? ' (dry run)' : ''

@[if vars().get('expected_num_views')]@
// reconfigure views
println '# BEGIN SUBSECTION: reconfigure @(expected_num_views) views'
created_views = 0
updated_views = 0
skipped_views = 0

view_config_dir = build.getWorkspace().toString() + '/reconfigure_jobs/view_configs'

def view_dir = new File(view_config_dir)
def views = view_dir.listFiles()
views.sort()

if (views.size() != @(expected_num_views)) {
    println "ERROR: Found different number of view configs than expected!! " + views.size() + " is not @(expected_num_views) as expected."
    // fail this build
    throw new AbortException("Wrong number of view configs")
}

views.each{
    found_view = false
    view_name = it.getName()
    view_config = new File(it.path).getText('UTF-8')
    for (v in Jenkins.instance.views) {
        if (v.name != view_name) continue
        found_view = true
        output_stream= new ByteArrayOutputStream()
        v.writeXml(output_stream)
        reader = new StringReader(output_stream.toString())
        source = new InputSource(reader)

        diff = diff_configs(source, view_config)
        if (!diff) {
            println "Skipped view '" + view_name + "' because the config is the same"
            skipped_views += 1
        } else {
            println "Updating view '" + view_name + "'" + dry_run_suffix
            println '    <<<'
            for (line in diff) {
                println '    ' + line
            }
            println '    >>>'

            if (!dry_run) {
                reader = new StringReader(view_config)
                source = new StreamSource(reader)
                v.updateByXml(source)
            }
            updated_views += 1
        }
        break
    }
    if (!found_view) {
        println "Creating view '" + view_name + "'" + dry_run_suffix
        if (!dry_run) {
            stream = new StringBufferInputStream(view_config)
            view = View.createViewFromXML(view_name, stream)
            Jenkins.instance.addView(view)
        }
        created_views += 1
    }
}

println 'Created ' + created_views + ' views, updated ' + updated_views + ' views, skipped ' + skipped_views + ' views' + dry_run_suffix + '.'
println '# END SUBSECTION'

@[end if]@
// reconfigure jobs
println '# BEGIN SUBSECTION: reconfigure @(expected_num_jobs) jobs'
created_jobs = 0
updated_jobs = 0
skipped_jobs = 0

job_config_dir = build.getWorkspace().toString() + '/reconfigure_jobs/job_configs'

def job_dir = new File(job_config_dir)
def jobs = job_dir.listFiles()
jobs.sort()

if (jobs.size() != @(expected_num_jobs)) {
    println "ERROR: Found different number of job configs than expected!! " + jobs.size() + " is not @(expected_num_jobs) as expected."
    // fail this build
    throw new AbortException("Wrong number of job configs")
}

def mergePullRequestData(job_name, current_file, job_config) {
    factory = DocumentBuilderFactory.newInstance()
    builder = factory.newDocumentBuilder()
    document = builder.parse(current_file)

    nodelist = document.getElementsByTagName("triggers")
    if (nodelist.getLength() != 1) return job_config
    trigger_node = nodelist.item(0)

    nodelist = trigger_node.getElementsByTagName("org.jenkinsci.plugins.ghprb.GhprbTrigger")
    if (nodelist.getLength() != 1) return job_config
    ghprb_trigger_node = nodelist.item(0)

    nodelist = ghprb_trigger_node.getElementsByTagName("pullRequests")
    if (nodelist.getLength() != 1) return job_config
    pull_requests_node = nodelist.item(0)

    builder2 = factory.newDocumentBuilder()
    stream = new StringBufferInputStream(job_config)
    document2 = builder2.parse(stream)

    nodelist = document2.getElementsByTagName("triggers")
    if (nodelist.getLength() != 1) return job_config
    trigger_node = nodelist.item(0)

    nodelist = trigger_node.getElementsByTagName("org.jenkinsci.plugins.ghprb.GhprbTrigger")
    if (nodelist.getLength() != 1) return job_config
    ghprb_trigger_node = nodelist.item(0)

    pull_requests_node = document2.importNode(pull_requests_node, true)
    ghprb_trigger_node.appendChild(pull_requests_node)

    println "Merged configuration with existing pull request job '" + job_name + "' to maintain pull request information"

    return format_xml(document2)
}

jobs.each{
    found_project = false
    job_name = it.getName()
    // remove leading serial number
    job_name = job_name[job_name.indexOf(' ') + 1..-1]
    job_config = new File(it.path).getText('UTF-8')
    for (p in Jenkins.instance.allItems) {
        if (p.name != job_name) continue
        found_project = true
        job_config_file = p.getConfigFile()

        if (p.name.substring(1, 5) == 'pr__') {
            job_config = mergePullRequestData(job_name, job_config_file.getFile(), job_config)
        }

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

            if (!dry_run) {
                reader = new StringReader(job_config)
                source = new StreamSource(reader)
                p.updateByXml(source)
            }
            updated_jobs += 1
        }
        break
    }
    if (!found_project) {
        println "Creating job '" + job_name + "'" + dry_run_suffix
        if (!dry_run) {
            stream = new StringBufferInputStream(job_config)
            Jenkins.instance.createProjectFromXML(job_name, stream)
        }
        created_jobs += 1
    }
}

println 'Created ' + created_jobs + ' jobs, updated ' + updated_jobs + ' jobs, skipped ' + skipped_jobs + ' jobs' + dry_run_suffix + '.'
println 'Rebuilding dependency graph...'
Jenkins.instance.rebuildDependencyGraph()
println '# END SUBSECTION'

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

println '# END SECTION'

def diff_configs(current_config, new_config) {

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

    current_doc = builder.parse(current_config)

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

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

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

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

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

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

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

import difflib.DiffUtils
import groovy.io.FileType
import hudson.AbortException
import hudson.model.View
import java.io.StringBufferInputStream
import java.io.StringWriter
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.stream.StreamSource
import jenkins.model.Jenkins
import org.apache.xml.serialize.OutputFormat
import org.apache.xml.serialize.XMLSerializer
import org.xml.sax.InputSource

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

println '# BEGIN SECTION: Groovy script - reconfigure'
dry_run = @('true' if dry_run else 'false')
dry_run_suffix = dry_run ? ' (dry run)' : ''

@[if vars().get('expected_num_views')]@
// reconfigure views
println '# BEGIN SUBSECTION: reconfigure @(expected_num_views) views'
created_views = 0
updated_views = 0
skipped_views = 0

view_config_dir = build.getWorkspace().toString() + '/reconfigure_jobs/view_configs'

def view_dir = new File(view_config_dir)
def views = view_dir.listFiles()
views.sort()

if (views.size() != @(expected_num_views)) {
    println "ERROR: Found different number of view configs than expected!! " + views.size() + " is not @(expected_num_views) as expected."
    // fail this build
    throw new AbortException("Wrong number of view configs")
}

views.each{
    found_view = false
    view_name = it.getName()
    view_config = new File(it.path).getText('UTF-8')
    for (v in Jenkins.instance.views) {
        if (v.name != view_name) continue
        found_view = true
        output_stream= new ByteArrayOutputStream()
        v.writeXml(output_stream)
        reader = new StringReader(output_stream.toString())
        source = new InputSource(reader)

        diff = diff_configs(source, view_config)
        if (!diff) {
            println "Skipped view '" + view_name + "' because the config is the same"
            skipped_views += 1
        } else {
            println "Updating view '" + view_name + "'" + dry_run_suffix
            println '    <<<'
            for (line in diff) {
                println '    ' + line
            }
            println '    >>>'

            if (!dry_run) {
                reader = new StringReader(view_config)
                source = new StreamSource(reader)
                v.updateByXml(source)
            }
            updated_views += 1
        }
        break
    }
    if (!found_view) {
        println "Creating view '" + view_name + "'" + dry_run_suffix
        if (!dry_run) {
            stream = new StringBufferInputStream(view_config)
            view = View.createViewFromXML(view_name, stream)
            Jenkins.instance.addView(view)
        }
        created_views += 1
    }
}

println 'Created ' + created_views + ' views, updated ' + updated_views + ' views, skipped ' + skipped_views + ' views' + dry_run_suffix + '.'
println '# END SUBSECTION'

@[end if]@
// reconfigure jobs
println '# BEGIN SUBSECTION: reconfigure @(expected_num_jobs) jobs'
created_jobs = 0
updated_jobs = 0
skipped_jobs = 0

job_config_dir = build.getWorkspace().toString() + '/reconfigure_jobs/job_configs'

def job_dir = new File(job_config_dir)
def jobs = job_dir.listFiles()
jobs.sort()

if (jobs.size() != @(expected_num_jobs)) {
    println "ERROR: Found different number of job configs than expected!! " + jobs.size() + " is not @(expected_num_jobs) as expected."
    // fail this build
    throw new AbortException("Wrong number of job configs")
}

def mergePullRequestData(job_name, current_file, job_config) {
    factory = DocumentBuilderFactory.newInstance()
    builder = factory.newDocumentBuilder()
    document = builder.parse(current_file)

    nodelist = document.getElementsByTagName("triggers")
    if (nodelist.getLength() != 1) return job_config
    trigger_node = nodelist.item(0)

    nodelist = trigger_node.getElementsByTagName("org.jenkinsci.plugins.ghprb.GhprbTrigger")
    if (nodelist.getLength() != 1) return job_config
    ghprb_trigger_node = nodelist.item(0)

    nodelist = ghprb_trigger_node.getElementsByTagName("pullRequests")
    if (nodelist.getLength() != 1) return job_config
    pull_requests_node = nodelist.item(0)

    builder2 = factory.newDocumentBuilder()
    stream = new StringBufferInputStream(job_config)
    document2 = builder2.parse(stream)

    nodelist = document2.getElementsByTagName("triggers")
    if (nodelist.getLength() != 1) return job_config
    trigger_node = nodelist.item(0)

    nodelist = trigger_node.getElementsByTagName("org.jenkinsci.plugins.ghprb.GhprbTrigger")
    if (nodelist.getLength() != 1) return job_config
    ghprb_trigger_node = nodelist.item(0)

    pull_requests_node = document2.importNode(pull_requests_node, true)
    ghprb_trigger_node.appendChild(pull_requests_node)

    println "Merged configuration with existing pull request job '" + job_name + "' to maintain pull request information"

    return format_xml(document2)
}

jobs.each{
    found_project = false
    job_name = it.getName()
    // remove leading serial number
    job_name = job_name[job_name.indexOf(' ') + 1..-1]
    job_config = new File(it.path).getText('UTF-8')
    for (p in Jenkins.instance.allItems) {
        if (p.name != job_name) continue
        found_project = true
        job_config_file = p.getConfigFile()

        if (p.name.substring(1, 5) == 'pr__') {
            job_config = mergePullRequestData(job_name, job_config_file.getFile(), job_config)
        }

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

            if (!dry_run) {
                reader = new StringReader(job_config)
                source = new StreamSource(reader)
                p.updateByXml(source)
                p.save()
            }
            updated_jobs += 1
        }
        break
    }
    if (!found_project) {
        println "Creating job '" + job_name + "'" + dry_run_suffix
        if (!dry_run) {
            stream = new StringBufferInputStream(job_config)
            p = Jenkins.instance.createProjectFromXML(job_name, stream)
            p.save()
        }
        created_jobs += 1
    }
}

println 'Created ' + created_jobs + ' jobs, updated ' + updated_jobs + ' jobs, skipped ' + skipped_jobs + ' jobs' + dry_run_suffix + '.'
println '# END SUBSECTION'

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

println '# END SECTION'

def diff_configs(current_config, new_config) {

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

    current_doc = builder.parse(current_config)

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

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

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

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

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

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

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


Fixing vcs snippet removing WORKDIR catching repos file name

@[if 'vcs' in locals()]@
@[if vcs]@
@[for i, (imports_name, imports) in enumerate(vcs.items())]@
RUN wget @(imports['repos']) \
    && vcs import @(ws) < @(imports['repos'].split('/')[-1])
@[end for]@
@[end if]@
@[end if]@

@[if 'vcs' in locals()]@
@[if vcs]@
WORKDIR @(ws)
@[for i, (imports_name, imports) in enumerate(vcs.items())]@
RUN wget @(imports['repos']) \
    && vcs import @(ws) < @(imports_name)
@[end for]@
@[end if]@
@[end if]@


Fix use of presence list in default GUI which isn't currently instantiated.

/*  Sirikata
 *  default.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('graphics.em');
system.require('undo.em');
system.require('std/movement/pursue.em');
system.require('std/script/scripter.em');
system.require('inputbinding.em');
system.require('defaultcamera.em');
system.require('drag/move.em');
system.require('drag/rotate.em');
system.require('drag/scale.em');
system.require('std/graphics/chat.em');
system.require('std/graphics/physics.em');
system.require('std/graphics/propertybox.em');
system.require('std/graphics/presenceList.em');
system.require('std/graphics/setMesh.em');
system.require('std/graphics/axes.em');
system.require('std/graphics/flatlandViewer.em');

(
function() {

    var ns = std.graphics;

    /** @namespace
     *  The DefaultGraphics class just contains some sane defaults for
     *  interaction, allowing you to get a decent, baseline client
     *  that only requires built-in functionality. You still define
     *  the presence and which underlying graphics system to use, but
     *  this class takes care of defining all other UI and interaction.
     */
    std.graphics.DefaultGraphics = function(pres, name, cb) {
        this._pres = pres;

        this._simulator = new std.graphics.Graphics(pres, name, std.core.bind(this.finishedGraphicsInit, this, cb), std.core.bind(this.finishedGraphicsUIReset, this));
    };

    std.graphics.DefaultGraphics.prototype.finishedGraphicsInit = function(cb, gfx, alreadyInitialized) {
        this._camera = new std.graphics.DefaultCamera(this._simulator, system.self);

        this._selected = null;
        this._loadingUIs = 0;

        this._alreadyInitialized = alreadyInitialized;
        if (! this._alreadyInitialized)
        {
            var ui_finish_cb = std.core.bind(this.finishedUIInit, this, cb);
            this._loadingUIs++; this._scripter = new std.script.Scripter(this, ui_finish_cb);
            //this._loadingUIs++; this._chat = new std.graphics.Chat(this._pres, this._simulator, ui_finish_cb);
            //this._loadingUIs++; this._physics = new std.graphics.PhysicsProperties(this._simulator, ui_finish_cb);
            //this._loadingUIs++; this._propertybox = new std.propertybox.PropertyBox(this, ui_finish_cb);
            //this._loadingUIs++; this._presenceList = new std.graphics.PresenceList(this._pres, this._simulator, this._scripter, ui_finish_cb);
            //this._loadingUIs++; this._setMesh = new std.graphics.SetMesh(this._simulator, ui_finish_cb);
            //this._loadingUIs++; this._flatland = new std.fl.FL(this, ui_finish_cb);
        }
        else
            this.finishedUIInit(cb);

    };

    std.graphics.DefaultGraphics.prototype.finishedGraphicsUIReset = function(gfx) {
        this._camera.reinit();

        var ui_finish_cb = std.core.bind(this.finishedUIInit, this);
        this._loadingUIs++; this._scripter.onReset(ui_finish_cb);
        //this._loadingUIs++; this._chat.onReset(ui_finish_cb);
        //this._loadingUIs++; this._physics.onReset(ui_finish_cb);
        //this._loadingUIs++; this._propertybox.onReset(ui_finish_cb);
        //this._loadingUIs++; this._presenceList.onReset(ui_finish_cb);
        //this._loadingUIs++; this._setMesh.onReset(ui_finish_cb);
        //this._loadingUIs++; this._flatland.onReset(ui_finish_cb);
    };

    /**
     this._alreadyInitialized is true or false.  If true, means that we
     already had a graphics viewer completely initialized before going
     through this initialization process.  If false, means that we
     are doing initialization for the first time.
     */
    std.graphics.DefaultGraphics.prototype.finishedUIInit = function(cb) {
        this._loadingUIs--;
        if (this._loadingUIs > 0) return;

        if (! this._alreadyInitialized)
            this._simulator.hideLoadScreen();

        this._moverot = new std.movement.MoveAndRotate(this._pres, std.core.bind(this.updateCameraOffset, this), 'rotation');

        this._draggers = {
            move: new std.graphics.MoveDragHandler(this._simulator),
            rotate: new std.graphics.RotateDragHandler(this._simulator),
            scale: new std.graphics.ScaleDragHandler(this._simulator)
        };

        this._binding = new std.graphics.InputBinding();
        this._simulator.inputHandler.onAnything = std.core.bind(this._binding.dispatch, this._binding);

        this._binding.addFloat2Action('pickObject', std.core.bind(this.pickObject, this));

        if (! this._alreadyInitialized)
        {
            this._binding.addAction('quit', std.core.bind(this._simulator.quit, this._simulator));
            this._binding.addAction('screenshot', std.core.bind(this._simulator.screenshot, this._simulator));
            this._binding.addAction('toggleSuspend', std.core.bind(this._simulator.toggleSuspend, this._simulator));
            this._binding.addAction('scriptSelectedObject', std.core.bind(this.scriptSelectedObject, this));
            this._binding.addAction('scriptSelf', std.core.bind(this.scriptSelf, this));

            this._binding.addAction('togglePropertyBox', std.core.bind(this.togglePropertyBox, this));
            this._binding.addAction('toggleChat', std.core.bind(this.toggleChat, this));
            //this._binding.addAction('togglePhysicsProperties', std.core.bind(this._physics.toggle, this._physics));
            //this._binding.addAction('togglePresenceList', std.core.bind(this._presenceList.toggle, this._presenceList));
            //this._binding.addAction('toggleSetMesh', std.core.bind(this._setMesh.toggle, this._setMesh));
            //this._binding.addFloat2Action('showFlatland', std.core.bind(this.showFlatland, this));
            //this._binding.addAction('hideFlatland', std.core.bind(this.hideFlatland, this));

            this._binding.addAction('toggleCameraMode', std.core.bind(this.toggleCameraMode, this));

            this._binding.addAction('actOnObject', std.core.bind(this.actOnObject, this));
            this._binding.addAction('teleportToObj', std.core.bind(this.teleportToObj, this));

            this._binding.addToggleAction('moveForward', std.core.bind(this.moveSelf, this, new util.Vec3(0, 0, -1)), 1, -1);
            this._binding.addToggleAction('moveBackward', std.core.bind(this.moveSelf, this, new util.Vec3(0, 0, 1)), 1, -1);
            this._binding.addToggleAction('moveLeft', std.core.bind(this.moveSelf, this, new util.Vec3(-1, 0, 0)), 1, -1);
            this._binding.addToggleAction('moveRight', std.core.bind(this.moveSelf, this, new util.Vec3(1, 0, 0)), 1, -1);
            this._binding.addToggleAction('moveUp', std.core.bind(this.moveSelf, this, new util.Vec3(0, 1, 0)), 1, -1);
            this._binding.addToggleAction('moveDown', std.core.bind(this.moveSelf, this, new util.Vec3(0, -1, 0)), 1, -1);

            this._binding.addToggleAction('rotateUp', std.core.bind(this.rotateSelf, this, new util.Vec3(1, 0, 0), "_rotate_up_handle_"), true, false);
            this._binding.addToggleAction('rotateDown', std.core.bind(this.rotateSelf, this, new util.Vec3(-1, 0, 0), "_rotate_down_handle_"), true, false);
            this._binding.addToggleAction('rotateLeft', std.core.bind(this.rotateSelf, this, new util.Vec3(0, 1, 0), "_rotate_left_handle_"), true, false);
            this._binding.addToggleAction('rotateRight', std.core.bind(this.rotateSelf, this, new util.Vec3(0, -1, 0), "_rotate_right_handle_"), true, false);

            this._binding.addFloat2Action('turnOffAxis', std.core.bind(this.turnOffAxis, this));

            this._binding.addAction('axesSnapLocal', std.core.bind(this.setAxesInheritOrient, this, true));
            this._binding.addAction('axesSnapGlobal', std.core.bind(this.setAxesInheritOrient, this, false));

            this._binding.addAction('updatePhysicsProperties', std.core.bind(this.updatePhysicsProperties, this));

            this._binding.addAction('startMoveDrag', std.core.bind(this.startDrag, this, this._draggers.move));
            this._binding.addAction('startRotateDrag', std.core.bind(this.startDrag, this, this._draggers.rotate));
            this._binding.addAction('startScaleDrag', std.core.bind(this.startDrag, this, this._draggers.scale));
            this._binding.addAction('forwardMousePressToDragger', std.core.bind(this.forwardMousePressToDragger, this));
            this._binding.addAction('forwardMouseDragToDragger', std.core.bind(this.forwardMouseDragToDragger, this));
            this._binding.addAction('updatePropertyBox', std.core.bind(this.updatePropertyBox, this));
            this._binding.addAction('forwardMouseReleaseToDragger', std.core.bind(this.forwardMouseReleaseToDragger, this));
            this._binding.addAction('stopDrag', std.core.bind(this.stopDrag, this));

            this._binding.addAction('startFreeRotate', std.core.bind(this.startFreeRotate, this));
            this._binding.addAction('freeRotateDrag', std.core.bind(this.freeRotateDrag, this));
            this._binding.addAction('freeRotateRelease', std.core.bind(this.freeRotateRelease, this));
            this._binding.addAction('undo', std.core.bind(this.undo, this));
            this._binding.addAction('redo', std.core.bind(this.redo, this));
        }

        /** Bindings are an *ordered* list of keys and actions. Keys
         *  are a combination of the type of event, the primary key
         *  for the event (key or mouse button), and modifiers.
         *  Modifiers are tricky to handle. You can specify a string
         *  indicating which to filter on. If you omit the string, it
         *  is equivalent to 'none'. The special values '*' and 'any'
         *  are equivalent and will match any modifier, i.e. the event
         *  will always be triggered. There isn't support
         *  for matching combinations of modifiers.
         */
        var bindings = [{ key: ['mouse-press', 1 ], action: 'pickObject' },
                        { key: ['mouse-click', 2], action: 'pickObject' }];

        if (!this._alreadyInitialized)
        {
            bindings = bindings.concat([{ key: ['button-pressed', 'escape'], action: 'quit' },
                                        { key: ['button-pressed', 'i'], action: 'screenshot' },
                                        { key: ['button-pressed', 'm'], action: 'toggleSuspend' },
                                        { key: ['button-pressed', 's', 'alt' ], action: 'scriptSelectedObject' },
                                        { key: ['button-pressed', 's', 'ctrl' ], action: 'scriptSelf' },
                                        { key: ['button-pressed', 'c', 'ctrl' ], action: 'toggleChat' },
                                        { key: ['button-pressed', 'p', 'ctrl' ], action: 'togglePhysicsProperties' },
                                        { key: ['button-pressed', 'p', 'alt' ], action: 'togglePropertyBox' },
                                        { key: ['button-pressed', 'l', 'ctrl' ], action: 'togglePresenceList' },
                                        { key: ['button-pressed', 'j', 'ctrl' ], action: 'toggleSetMesh' },

                                        { key: ['button-pressed', 'g', 'alt' ], action: 'axesSnapLocal' },
                                        { key: ['button-pressed', 'g', 'ctrl' ], action: 'axesSnapGlobal' },

                                        { key: ['button-pressed', 'z', 'ctrl' ], action: 'undo' },
                                        { key: ['button-pressed', 'y', 'ctrl' ], action: 'redo' },

                                        { key: ['mouse-click', 1, 'shift'], action: 'turnOffAxis' },
                                        { key: ['mouse-click', 2], action: 'scriptSelectedObject' },
                                        { key: ['button-pressed', 'return'], action: 'actOnObject' },
                                        { key: ['button-pressed', 't', 'ctrl' ], action: 'teleportToObj' },

                                        { key: ['button-pressed', 'c' ], action: 'toggleCameraMode' },

                                        { key: ['button', 'w' ], action: 'moveForward' },
                                        { key: ['button', 'up' ], action: 'moveForward' },
                                        { key: ['button', 's' ], action: 'moveBackward' },
                                        { key: ['button', 'down' ], action: 'moveBackward' },
                                        { key: ['button', 'a' ], action: 'moveLeft' },
                                        { key: ['button', 'd' ], action: 'moveRight' },
                                        { key: ['button', 'q' ], action: 'moveUp' },
                                        { key: ['button', 'z' ], action: 'moveDown' },

                                        { key: ['button', 'up', 'shift' ], action: 'rotateUp' },
                                        { key: ['button', 'down', 'shift' ], action: 'rotateDown' },
                                        { key: ['button', 'left' ], action: 'rotateLeft' },
                                        { key: ['button', 'right' ], action: 'rotateRight' },

                                        { key: ['mouse-press', 1 ], action: 'updatePhysicsProperties' },

                                        // Note that the ordering of registration here is critical.
                                        { key: ['mouse-press', 1, 'none' ], action: 'startMoveDrag' },
                                        { key: ['mouse-press', 1, 'ctrl' ], action: 'startRotateDrag' },
                                        { key: ['mouse-press', 1, 'alt' ], action: 'startScaleDrag' },
                                        { key: ['mouse-press', 1, '*'], action: 'forwardMousePressToDragger' },
                                        { key: ['mouse-press', 1, '*'], action: 'updatePropertyBox' },
                                        { key: ['mouse-drag', 1, '*'], action: 'forwardMouseDragToDragger' },
                                        { key: ['mouse-release', 1, '*'], action: 'forwardMouseReleaseToDragger' },
                                        { key: ['mouse-release', 1, '*'], action: 'stopDrag' },
                                        { key: ['mouse-press', 3, 'none'], action: 'showFlatland' },
                                        { key: ['mouse-press', 3, 'none' ], action: 'startFreeRotate' },
                                        { key: ['mouse-drag', 3, 'none'], action: 'freeRotateDrag' },
                                        { key: ['mouse-release', 3, 'none'], action: 'freeRotateRelease' }
                                       ]);
        }

        this._binding.addBindings(bindings);
        std.graphics.axes.init(this._simulator);
        this._axesInheritOrient = true;

        if (cb && typeof(cb) === "function")
            cb(this);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.simulator = function() {
        return this._simulator;
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.invoke = function() {
        // Just forward manual invoke commands directly
        return this._simulator.invoke.apply(this._simulator, arguments);
    };

    /** Request that the given URL be added as a module in the UI. */
    std.graphics.DefaultGraphics.prototype.addGUIModule = function(name, url, cb) {
        return this._simulator.addGUIModule(name, url, cb);
    };

    /** Request that the given script text be added as a module in the UI. */
    std.graphics.DefaultGraphics.prototype.addGUITextModule = function(name, js_text, cb) {
        return this._simulator.addGUITextModule(name, js_text, cb);
    };

    /** Get the GUI for a previously loaded GUI module. */
    std.graphics.DefaultGraphics.prototype.getGUIModule = function(name) {
        return this._simulator.getGUIModule(name);
    };

    /** Request that the given URL be presented as a widget. */
    std.graphics.DefaultGraphics.prototype.createBrowser = function(name, url, cb) {
        return this._simulator.createBrowser(name, url, cb);
    };

    /** Get a list of animations associated with this entity. */
    std.graphics.DefaultGraphics.prototype.getAnimationList = function(vis) {
        if (!vis)
          vis = system.self;

        return this._simulator.getAnimationList(vis);
    };

    /** Start the animation on this entity given by the specified animation name. */
    std.graphics.DefaultGraphics.prototype.startAnimation = function(vis, anim) {
        return this._simulator.startAnimation(vis, anim);
    };

    /** Stop the animation on this entity. */
    std.graphics.DefaultGraphics.prototype.stopAnimation = function(vis) {
        return this._simulator.stopAnimation(vis);
    };

    //by default how to scale translational velocity from keypresses.  (movement
    //is agonizingly slow if just set this to 1.  I really recommend 5.)
    /** @public */
    std.graphics.DefaultGraphics.prototype.defaultVelocityScaling = 5;
    //by default how to scale rotational velocity from keypresses
    /** @public */
    std.graphics.DefaultGraphics.prototype.defaultRotationalVelocityScaling = .5;

    /** @function */
    std.graphics.DefaultGraphics.prototype.toggleChat = function() {
        this._chat.toggle();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.scriptSelf = function() {
        this._scripter.script(system.self);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.togglePropertyBox = function() {
        this._propertybox.TogglePropertyBox();
    };

    std.graphics.DefaultGraphics.prototype.setAxesInheritOrient = function(inheritOrient) {
        if (this._axesInheritOrient === inheritOrient) {
            return;
        }

        this._axesInheritOrient = inheritOrient;

        if (this._selected) {
            std.graphics.axes.setInheritOrientAll(this._selected, inheritOrient);
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.scriptSelectedObject = function() {
        if (this._selected == null)
            return;
        //this._presenceList.addObject(this._selected.toString(), 'Scripted');
        this._scripter.script(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.toggleCameraMode = function(evt) {
        var newmode = this._camera.mode() == 'first' ? 'third' : 'first';
        this._camera.setMode(newmode);
        this.updateCameraOffset();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updateCameraOffset = function(evt) {
        if (this._camera.mode() == 'third') {
            var orient = this._pres.getOrientation();
            this._camera.setOffset(orient.mul(<0, 1.5, 4>));
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.moveSelf = function(dir, val) {
        this._moverot.move(dir, this.defaultVelocityScaling * val);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.rotateSelf = function(about, name, val) {
        if (val) {
            this[name] = this._moverot.rotate(about, this.defaultRotationalVelocityScaling);
        }
        else {
            this._moverot.cancelRotate(this[name]);
            delete this[name];
        }
    };

    std.graphics.DefaultGraphics.prototype.turnOffAxis = function(x, y) {
        if (!this._selected) {
            return;
        }
        var axis = std.graphics.axes.pick(this._selected, x, y);
        if (axis < 0) {
            return;
        } else {
            std.graphics.axes.setVisible(this._selected, axis, false);
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.pickObject = function(x, y)
    {
        var ignore_self = this._camera.mode() == 'first';
        var clicked = this._simulator.pick(x, y, ignore_self);
        if (clicked) {
            if (this._selected) {
                if (this._selected.toString() != clicked.toString()) {
                    if (!this._alreadyInitialized)
                    {
                        this._simulator.bbox(this._selected, false);
                        std.graphics.axes.setVisibleAll(this._selected, false);
                    }
                } else {
                    return;
                }
            }

            this._selected = clicked;
            if (!this._alreadyInitialized)
            {
                this._simulator.bbox(this._selected, true);
                std.graphics.axes.setInheritOrientAll(this._selected, this._axesInheritOrient);
                std.graphics.axes.setVisibleAll(this._selected, true);
            }
        } else if (this._selected) {
            if (!this._alreadyInitialized)
            {
                this._simulator.bbox(this._selected, false);
                std.graphics.axes.setVisibleAll(this._selected, false);
            }
            this._selected = null;
        }

    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.actOnObject = function(evt) {
        if (this._selected)
            { 'action' : 'touch' } >> this._selected >> [];
    }

    /** @function */
    std.graphics.DefaultGraphics.prototype.teleportToObj = function(evt) {
        if (this._selected) {
            var dir = this._selected.getPosition() - this._pres.getPosition();
            dir = dir.normal();
            var self = this;
            this._selected.loadMesh(function() {
                var hit = std.raytrace.raytrace(null, self._pres.getPosition(), dir, self._selected, null);
                if (hit) {
                    self._pres.setPosition(hit.sub(dir.scale(3)));
                } else {
                    self._pres.setPosition(this._selected.getPosition());
                }
                self._pres.setOrientation(util.Quaternion.fromLookAt(dir));
            });
        }
    }

    /** @function */
    std.graphics.DefaultGraphics.prototype.updatePhysicsProperties = function() {
        // Update even if not selected so display can be disabled
        //this._physics.update(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.startDrag = function(dragger, evt) {
        if (this._selected)
            this._dragger = dragger;
        if (this._dragger)
            this._dragger.selected(this._selected, this._simulator.pickedPosition(), evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMousePressToDragger = function(evt) {
        if (this._dragger) this._dragger.onMousePress(evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMouseDragToDragger = function(evt) {
        if (this._dragger) this._dragger.onMouseDrag(evt);
        //this._propertybox.HandleUpdateProperties(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updatePropertyBox = function(evt) {
        //this._propertybox.HandleUpdateProperties(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMouseReleaseToDragger = function(evt) {
        if (this._dragger) this._dragger.onMouseRelease(evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.stopDrag = function() {
        delete this._dragger;
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.startFreeRotate = function(evt) {
        this.startX = evt.x;
        this.startY = evt.y;
        this.startOrientation = this._pres.getOrientation();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.freeRotateDrag = function(evt) {
        if (this.startX == null || this.startY == null)
            return;

        var SCALE = 1;
        var dx = evt.x - this.startX;
        var dy = evt.y - this.startY;
        var dXAngle = dx * SCALE;
        var dYAngle = dy * SCALE;
        var newQuat = this.startOrientation
            .mul(new util.Quaternion(<0, 1, 0>, -dXAngle))
            .mul(new util.Quaternion(<1, 0, 0>, dYAngle));
        this._pres.setOrientation(newQuat);

        // Reorient self so up is up.
        this._pres.setOrientation(util.Quaternion.fromLookAt(
            this._pres.getOrientation().zAxis().scale(-1), <0, 1, 0>));
        this.updateCameraOffset();
        this._moverot.reeval();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.freeRotateRelease = function(evt) {
        this.startX = null;
        this.startY = null;
        this.startOrientation = null;
    };

    std.graphics.DefaultGraphics.prototype.undo = function(evt) {
        this._simulator.undo();
    };

    std.graphics.DefaultGraphics.prototype.redo = function(evt) {
        this._simulator.redo();
    };

    std.graphics.DefaultGraphics.prototype.orientDefault = function(evt) {
        var vis = this._selected;
        if(!vis)
            return;
        var orient = vis.orientation;
        var movable = new std.movement.MovableRemote(vis);
        movable.setOrientation(new util.Quaternion());
        this._simulator.addUndoAction({}, {
            undo: function(action) {
                movable.setOrientation(orient);
            },
            redo: function(action) {
                movable.setOrientation(new util.Quaternion());
            }
        });
    };

    std.graphics.DefaultGraphics.prototype.setMaxObjects = function(maxobjs) {
        this._simulator.setMaxObjects(maxobjs);
    };

    std.graphics.DefaultGraphics.prototype.showFlatland = function (x, y) {
        var ignore_self = this._camera.mode() == 'first';
        var clicked = this._simulator.pick(x, y, ignore_self);
        this._flatland.show(clicked, x, y);
    };

    std.graphics.DefaultGraphics.prototype.hideFlatland = function () {
        this._flatland.hide();
    };

})();

/*  Sirikata
 *  default.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('graphics.em');
system.require('undo.em');
system.require('std/movement/pursue.em');
system.require('std/script/scripter.em');
system.require('inputbinding.em');
system.require('defaultcamera.em');
system.require('drag/move.em');
system.require('drag/rotate.em');
system.require('drag/scale.em');
system.require('std/graphics/chat.em');
system.require('std/graphics/physics.em');
system.require('std/graphics/propertybox.em');
system.require('std/graphics/presenceList.em');
system.require('std/graphics/setMesh.em');
system.require('std/graphics/axes.em');
system.require('std/graphics/flatlandViewer.em');

(
function() {

    var ns = std.graphics;

    /** @namespace
     *  The DefaultGraphics class just contains some sane defaults for
     *  interaction, allowing you to get a decent, baseline client
     *  that only requires built-in functionality. You still define
     *  the presence and which underlying graphics system to use, but
     *  this class takes care of defining all other UI and interaction.
     */
    std.graphics.DefaultGraphics = function(pres, name, cb) {
        this._pres = pres;

        this._simulator = new std.graphics.Graphics(pres, name, std.core.bind(this.finishedGraphicsInit, this, cb), std.core.bind(this.finishedGraphicsUIReset, this));
    };

    std.graphics.DefaultGraphics.prototype.finishedGraphicsInit = function(cb, gfx, alreadyInitialized) {
        this._camera = new std.graphics.DefaultCamera(this._simulator, system.self);

        this._selected = null;
        this._loadingUIs = 0;

        this._alreadyInitialized = alreadyInitialized;
        if (! this._alreadyInitialized)
        {
            var ui_finish_cb = std.core.bind(this.finishedUIInit, this, cb);
            this._loadingUIs++; this._scripter = new std.script.Scripter(this, ui_finish_cb);
            //this._loadingUIs++; this._chat = new std.graphics.Chat(this._pres, this._simulator, ui_finish_cb);
            //this._loadingUIs++; this._physics = new std.graphics.PhysicsProperties(this._simulator, ui_finish_cb);
            //this._loadingUIs++; this._propertybox = new std.propertybox.PropertyBox(this, ui_finish_cb);
            //this._loadingUIs++; this._presenceList = new std.graphics.PresenceList(this._pres, this._simulator, this._scripter, ui_finish_cb);
            //this._loadingUIs++; this._setMesh = new std.graphics.SetMesh(this._simulator, ui_finish_cb);
            //this._loadingUIs++; this._flatland = new std.fl.FL(this, ui_finish_cb);
        }
        else
            this.finishedUIInit(cb);

    };

    std.graphics.DefaultGraphics.prototype.finishedGraphicsUIReset = function(gfx) {
        this._camera.reinit();

        var ui_finish_cb = std.core.bind(this.finishedUIInit, this);
        this._loadingUIs++; this._scripter.onReset(ui_finish_cb);
        //this._loadingUIs++; this._chat.onReset(ui_finish_cb);
        //this._loadingUIs++; this._physics.onReset(ui_finish_cb);
        //this._loadingUIs++; this._propertybox.onReset(ui_finish_cb);
        //this._loadingUIs++; this._presenceList.onReset(ui_finish_cb);
        //this._loadingUIs++; this._setMesh.onReset(ui_finish_cb);
        //this._loadingUIs++; this._flatland.onReset(ui_finish_cb);
    };

    /**
     this._alreadyInitialized is true or false.  If true, means that we
     already had a graphics viewer completely initialized before going
     through this initialization process.  If false, means that we
     are doing initialization for the first time.
     */
    std.graphics.DefaultGraphics.prototype.finishedUIInit = function(cb) {
        this._loadingUIs--;
        if (this._loadingUIs > 0) return;

        if (! this._alreadyInitialized)
            this._simulator.hideLoadScreen();

        this._moverot = new std.movement.MoveAndRotate(this._pres, std.core.bind(this.updateCameraOffset, this), 'rotation');

        this._draggers = {
            move: new std.graphics.MoveDragHandler(this._simulator),
            rotate: new std.graphics.RotateDragHandler(this._simulator),
            scale: new std.graphics.ScaleDragHandler(this._simulator)
        };

        this._binding = new std.graphics.InputBinding();
        this._simulator.inputHandler.onAnything = std.core.bind(this._binding.dispatch, this._binding);

        this._binding.addFloat2Action('pickObject', std.core.bind(this.pickObject, this));

        if (! this._alreadyInitialized)
        {
            this._binding.addAction('quit', std.core.bind(this._simulator.quit, this._simulator));
            this._binding.addAction('screenshot', std.core.bind(this._simulator.screenshot, this._simulator));
            this._binding.addAction('toggleSuspend', std.core.bind(this._simulator.toggleSuspend, this._simulator));
            this._binding.addAction('scriptSelectedObject', std.core.bind(this.scriptSelectedObject, this));
            this._binding.addAction('scriptSelf', std.core.bind(this.scriptSelf, this));

            this._binding.addAction('togglePropertyBox', std.core.bind(this.togglePropertyBox, this));
            this._binding.addAction('toggleChat', std.core.bind(this.toggleChat, this));
            //this._binding.addAction('togglePhysicsProperties', std.core.bind(this._physics.toggle, this._physics));
            //this._binding.addAction('togglePresenceList', std.core.bind(this._presenceList.toggle, this._presenceList));
            //this._binding.addAction('toggleSetMesh', std.core.bind(this._setMesh.toggle, this._setMesh));
            //this._binding.addFloat2Action('showFlatland', std.core.bind(this.showFlatland, this));
            //this._binding.addAction('hideFlatland', std.core.bind(this.hideFlatland, this));

            this._binding.addAction('toggleCameraMode', std.core.bind(this.toggleCameraMode, this));

            this._binding.addAction('actOnObject', std.core.bind(this.actOnObject, this));
            this._binding.addAction('teleportToObj', std.core.bind(this.teleportToObj, this));

            this._binding.addToggleAction('moveForward', std.core.bind(this.moveSelf, this, new util.Vec3(0, 0, -1)), 1, -1);
            this._binding.addToggleAction('moveBackward', std.core.bind(this.moveSelf, this, new util.Vec3(0, 0, 1)), 1, -1);
            this._binding.addToggleAction('moveLeft', std.core.bind(this.moveSelf, this, new util.Vec3(-1, 0, 0)), 1, -1);
            this._binding.addToggleAction('moveRight', std.core.bind(this.moveSelf, this, new util.Vec3(1, 0, 0)), 1, -1);
            this._binding.addToggleAction('moveUp', std.core.bind(this.moveSelf, this, new util.Vec3(0, 1, 0)), 1, -1);
            this._binding.addToggleAction('moveDown', std.core.bind(this.moveSelf, this, new util.Vec3(0, -1, 0)), 1, -1);

            this._binding.addToggleAction('rotateUp', std.core.bind(this.rotateSelf, this, new util.Vec3(1, 0, 0), "_rotate_up_handle_"), true, false);
            this._binding.addToggleAction('rotateDown', std.core.bind(this.rotateSelf, this, new util.Vec3(-1, 0, 0), "_rotate_down_handle_"), true, false);
            this._binding.addToggleAction('rotateLeft', std.core.bind(this.rotateSelf, this, new util.Vec3(0, 1, 0), "_rotate_left_handle_"), true, false);
            this._binding.addToggleAction('rotateRight', std.core.bind(this.rotateSelf, this, new util.Vec3(0, -1, 0), "_rotate_right_handle_"), true, false);

            this._binding.addFloat2Action('turnOffAxis', std.core.bind(this.turnOffAxis, this));

            this._binding.addAction('axesSnapLocal', std.core.bind(this.setAxesInheritOrient, this, true));
            this._binding.addAction('axesSnapGlobal', std.core.bind(this.setAxesInheritOrient, this, false));

            this._binding.addAction('updatePhysicsProperties', std.core.bind(this.updatePhysicsProperties, this));

            this._binding.addAction('startMoveDrag', std.core.bind(this.startDrag, this, this._draggers.move));
            this._binding.addAction('startRotateDrag', std.core.bind(this.startDrag, this, this._draggers.rotate));
            this._binding.addAction('startScaleDrag', std.core.bind(this.startDrag, this, this._draggers.scale));
            this._binding.addAction('forwardMousePressToDragger', std.core.bind(this.forwardMousePressToDragger, this));
            this._binding.addAction('forwardMouseDragToDragger', std.core.bind(this.forwardMouseDragToDragger, this));
            this._binding.addAction('updatePropertyBox', std.core.bind(this.updatePropertyBox, this));
            this._binding.addAction('forwardMouseReleaseToDragger', std.core.bind(this.forwardMouseReleaseToDragger, this));
            this._binding.addAction('stopDrag', std.core.bind(this.stopDrag, this));

            this._binding.addAction('startFreeRotate', std.core.bind(this.startFreeRotate, this));
            this._binding.addAction('freeRotateDrag', std.core.bind(this.freeRotateDrag, this));
            this._binding.addAction('freeRotateRelease', std.core.bind(this.freeRotateRelease, this));
            this._binding.addAction('undo', std.core.bind(this.undo, this));
            this._binding.addAction('redo', std.core.bind(this.redo, this));
        }

        /** Bindings are an *ordered* list of keys and actions. Keys
         *  are a combination of the type of event, the primary key
         *  for the event (key or mouse button), and modifiers.
         *  Modifiers are tricky to handle. You can specify a string
         *  indicating which to filter on. If you omit the string, it
         *  is equivalent to 'none'. The special values '*' and 'any'
         *  are equivalent and will match any modifier, i.e. the event
         *  will always be triggered. There isn't support
         *  for matching combinations of modifiers.
         */
        var bindings = [{ key: ['mouse-press', 1 ], action: 'pickObject' },
                        { key: ['mouse-click', 2], action: 'pickObject' }];

        if (!this._alreadyInitialized)
        {
            bindings = bindings.concat([{ key: ['button-pressed', 'escape'], action: 'quit' },
                                        { key: ['button-pressed', 'i'], action: 'screenshot' },
                                        { key: ['button-pressed', 'm'], action: 'toggleSuspend' },
                                        { key: ['button-pressed', 's', 'alt' ], action: 'scriptSelectedObject' },
                                        { key: ['button-pressed', 's', 'ctrl' ], action: 'scriptSelf' },
                                        { key: ['button-pressed', 'c', 'ctrl' ], action: 'toggleChat' },
                                        { key: ['button-pressed', 'p', 'ctrl' ], action: 'togglePhysicsProperties' },
                                        { key: ['button-pressed', 'p', 'alt' ], action: 'togglePropertyBox' },
                                        { key: ['button-pressed', 'l', 'ctrl' ], action: 'togglePresenceList' },
                                        { key: ['button-pressed', 'j', 'ctrl' ], action: 'toggleSetMesh' },

                                        { key: ['button-pressed', 'g', 'alt' ], action: 'axesSnapLocal' },
                                        { key: ['button-pressed', 'g', 'ctrl' ], action: 'axesSnapGlobal' },

                                        { key: ['button-pressed', 'z', 'ctrl' ], action: 'undo' },
                                        { key: ['button-pressed', 'y', 'ctrl' ], action: 'redo' },

                                        { key: ['mouse-click', 1, 'shift'], action: 'turnOffAxis' },
                                        { key: ['mouse-click', 2], action: 'scriptSelectedObject' },
                                        { key: ['button-pressed', 'return'], action: 'actOnObject' },
                                        { key: ['button-pressed', 't', 'ctrl' ], action: 'teleportToObj' },

                                        { key: ['button-pressed', 'c' ], action: 'toggleCameraMode' },

                                        { key: ['button', 'w' ], action: 'moveForward' },
                                        { key: ['button', 'up' ], action: 'moveForward' },
                                        { key: ['button', 's' ], action: 'moveBackward' },
                                        { key: ['button', 'down' ], action: 'moveBackward' },
                                        { key: ['button', 'a' ], action: 'moveLeft' },
                                        { key: ['button', 'd' ], action: 'moveRight' },
                                        { key: ['button', 'q' ], action: 'moveUp' },
                                        { key: ['button', 'z' ], action: 'moveDown' },

                                        { key: ['button', 'up', 'shift' ], action: 'rotateUp' },
                                        { key: ['button', 'down', 'shift' ], action: 'rotateDown' },
                                        { key: ['button', 'left' ], action: 'rotateLeft' },
                                        { key: ['button', 'right' ], action: 'rotateRight' },

                                        { key: ['mouse-press', 1 ], action: 'updatePhysicsProperties' },

                                        // Note that the ordering of registration here is critical.
                                        { key: ['mouse-press', 1, 'none' ], action: 'startMoveDrag' },
                                        { key: ['mouse-press', 1, 'ctrl' ], action: 'startRotateDrag' },
                                        { key: ['mouse-press', 1, 'alt' ], action: 'startScaleDrag' },
                                        { key: ['mouse-press', 1, '*'], action: 'forwardMousePressToDragger' },
                                        { key: ['mouse-press', 1, '*'], action: 'updatePropertyBox' },
                                        { key: ['mouse-drag', 1, '*'], action: 'forwardMouseDragToDragger' },
                                        { key: ['mouse-release', 1, '*'], action: 'forwardMouseReleaseToDragger' },
                                        { key: ['mouse-release', 1, '*'], action: 'stopDrag' },
                                        { key: ['mouse-press', 3, 'none'], action: 'showFlatland' },
                                        { key: ['mouse-press', 3, 'none' ], action: 'startFreeRotate' },
                                        { key: ['mouse-drag', 3, 'none'], action: 'freeRotateDrag' },
                                        { key: ['mouse-release', 3, 'none'], action: 'freeRotateRelease' }
                                       ]);
        }

        this._binding.addBindings(bindings);
        std.graphics.axes.init(this._simulator);
        this._axesInheritOrient = true;

        if (cb && typeof(cb) === "function")
            cb(this);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.simulator = function() {
        return this._simulator;
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.invoke = function() {
        // Just forward manual invoke commands directly
        return this._simulator.invoke.apply(this._simulator, arguments);
    };

    /** Request that the given URL be added as a module in the UI. */
    std.graphics.DefaultGraphics.prototype.addGUIModule = function(name, url, cb) {
        return this._simulator.addGUIModule(name, url, cb);
    };

    /** Request that the given script text be added as a module in the UI. */
    std.graphics.DefaultGraphics.prototype.addGUITextModule = function(name, js_text, cb) {
        return this._simulator.addGUITextModule(name, js_text, cb);
    };

    /** Get the GUI for a previously loaded GUI module. */
    std.graphics.DefaultGraphics.prototype.getGUIModule = function(name) {
        return this._simulator.getGUIModule(name);
    };

    /** Request that the given URL be presented as a widget. */
    std.graphics.DefaultGraphics.prototype.createBrowser = function(name, url, cb) {
        return this._simulator.createBrowser(name, url, cb);
    };

    /** Get a list of animations associated with this entity. */
    std.graphics.DefaultGraphics.prototype.getAnimationList = function(vis) {
        if (!vis)
          vis = system.self;

        return this._simulator.getAnimationList(vis);
    };

    /** Start the animation on this entity given by the specified animation name. */
    std.graphics.DefaultGraphics.prototype.startAnimation = function(vis, anim) {
        return this._simulator.startAnimation(vis, anim);
    };

    /** Stop the animation on this entity. */
    std.graphics.DefaultGraphics.prototype.stopAnimation = function(vis) {
        return this._simulator.stopAnimation(vis);
    };

    //by default how to scale translational velocity from keypresses.  (movement
    //is agonizingly slow if just set this to 1.  I really recommend 5.)
    /** @public */
    std.graphics.DefaultGraphics.prototype.defaultVelocityScaling = 5;
    //by default how to scale rotational velocity from keypresses
    /** @public */
    std.graphics.DefaultGraphics.prototype.defaultRotationalVelocityScaling = .5;

    /** @function */
    std.graphics.DefaultGraphics.prototype.toggleChat = function() {
        this._chat.toggle();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.scriptSelf = function() {
        this._scripter.script(system.self);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.togglePropertyBox = function() {
        this._propertybox.TogglePropertyBox();
    };

    std.graphics.DefaultGraphics.prototype.setAxesInheritOrient = function(inheritOrient) {
        if (this._axesInheritOrient === inheritOrient) {
            return;
        }

        this._axesInheritOrient = inheritOrient;

        if (this._selected) {
            std.graphics.axes.setInheritOrientAll(this._selected, inheritOrient);
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.scriptSelectedObject = function() {
        if (this._selected == null)
            return;
        this._presenceList.addObject(this._selected.toString(), 'Scripted');
        this._scripter.script(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.toggleCameraMode = function(evt) {
        var newmode = this._camera.mode() == 'first' ? 'third' : 'first';
        this._camera.setMode(newmode);
        this.updateCameraOffset();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updateCameraOffset = function(evt) {
        if (this._camera.mode() == 'third') {
            var orient = this._pres.getOrientation();
            this._camera.setOffset(orient.mul(<0, 1.5, 4>));
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.moveSelf = function(dir, val) {
        this._moverot.move(dir, this.defaultVelocityScaling * val);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.rotateSelf = function(about, name, val) {
        if (val) {
            this[name] = this._moverot.rotate(about, this.defaultRotationalVelocityScaling);
        }
        else {
            this._moverot.cancelRotate(this[name]);
            delete this[name];
        }
    };

    std.graphics.DefaultGraphics.prototype.turnOffAxis = function(x, y) {
        if (!this._selected) {
            return;
        }
        var axis = std.graphics.axes.pick(this._selected, x, y);
        if (axis < 0) {
            return;
        } else {
            std.graphics.axes.setVisible(this._selected, axis, false);
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.pickObject = function(x, y)
    {
        var ignore_self = this._camera.mode() == 'first';
        var clicked = this._simulator.pick(x, y, ignore_self);
        if (clicked) {
            if (this._selected) {
                if (this._selected.toString() != clicked.toString()) {
                    if (!this._alreadyInitialized)
                    {
                        this._simulator.bbox(this._selected, false);
                        std.graphics.axes.setVisibleAll(this._selected, false);
                    }
                } else {
                    return;
                }
            }

            this._selected = clicked;
            if (!this._alreadyInitialized)
            {
                this._simulator.bbox(this._selected, true);
                std.graphics.axes.setInheritOrientAll(this._selected, this._axesInheritOrient);
                std.graphics.axes.setVisibleAll(this._selected, true);
            }
        } else if (this._selected) {
            if (!this._alreadyInitialized)
            {
                this._simulator.bbox(this._selected, false);
                std.graphics.axes.setVisibleAll(this._selected, false);
            }
            this._selected = null;
        }

    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.actOnObject = function(evt) {
        if (this._selected)
            { 'action' : 'touch' } >> this._selected >> [];
    }

    /** @function */
    std.graphics.DefaultGraphics.prototype.teleportToObj = function(evt) {
        if (this._selected) {
            var dir = this._selected.getPosition() - this._pres.getPosition();
            dir = dir.normal();
            var self = this;
            this._selected.loadMesh(function() {
                var hit = std.raytrace.raytrace(null, self._pres.getPosition(), dir, self._selected, null);
                if (hit) {
                    self._pres.setPosition(hit.sub(dir.scale(3)));
                } else {
                    self._pres.setPosition(this._selected.getPosition());
                }
                self._pres.setOrientation(util.Quaternion.fromLookAt(dir));
            });
        }
    }

    /** @function */
    std.graphics.DefaultGraphics.prototype.updatePhysicsProperties = function() {
        // Update even if not selected so display can be disabled
        //this._physics.update(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.startDrag = function(dragger, evt) {
        if (this._selected)
            this._dragger = dragger;
        if (this._dragger)
            this._dragger.selected(this._selected, this._simulator.pickedPosition(), evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMousePressToDragger = function(evt) {
        if (this._dragger) this._dragger.onMousePress(evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMouseDragToDragger = function(evt) {
        if (this._dragger) this._dragger.onMouseDrag(evt);
        //this._propertybox.HandleUpdateProperties(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updatePropertyBox = function(evt) {
        //this._propertybox.HandleUpdateProperties(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMouseReleaseToDragger = function(evt) {
        if (this._dragger) this._dragger.onMouseRelease(evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.stopDrag = function() {
        delete this._dragger;
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.startFreeRotate = function(evt) {
        this.startX = evt.x;
        this.startY = evt.y;
        this.startOrientation = this._pres.getOrientation();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.freeRotateDrag = function(evt) {
        if (this.startX == null || this.startY == null)
            return;

        var SCALE = 1;
        var dx = evt.x - this.startX;
        var dy = evt.y - this.startY;
        var dXAngle = dx * SCALE;
        var dYAngle = dy * SCALE;
        var newQuat = this.startOrientation
            .mul(new util.Quaternion(<0, 1, 0>, -dXAngle))
            .mul(new util.Quaternion(<1, 0, 0>, dYAngle));
        this._pres.setOrientation(newQuat);

        // Reorient self so up is up.
        this._pres.setOrientation(util.Quaternion.fromLookAt(
            this._pres.getOrientation().zAxis().scale(-1), <0, 1, 0>));
        this.updateCameraOffset();
        this._moverot.reeval();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.freeRotateRelease = function(evt) {
        this.startX = null;
        this.startY = null;
        this.startOrientation = null;
    };

    std.graphics.DefaultGraphics.prototype.undo = function(evt) {
        this._simulator.undo();
    };

    std.graphics.DefaultGraphics.prototype.redo = function(evt) {
        this._simulator.redo();
    };

    std.graphics.DefaultGraphics.prototype.orientDefault = function(evt) {
        var vis = this._selected;
        if(!vis)
            return;
        var orient = vis.orientation;
        var movable = new std.movement.MovableRemote(vis);
        movable.setOrientation(new util.Quaternion());
        this._simulator.addUndoAction({}, {
            undo: function(action) {
                movable.setOrientation(orient);
            },
            redo: function(action) {
                movable.setOrientation(new util.Quaternion());
            }
        });
    };

    std.graphics.DefaultGraphics.prototype.setMaxObjects = function(maxobjs) {
        this._simulator.setMaxObjects(maxobjs);
    };

    std.graphics.DefaultGraphics.prototype.showFlatland = function (x, y) {
        var ignore_self = this._camera.mode() == 'first';
        var clicked = this._simulator.pick(x, y, ignore_self);
        this._flatland.show(clicked, x, y);
    };

    std.graphics.DefaultGraphics.prototype.hideFlatland = function () {
        this._flatland.hide();
    };

})();


always apt-get update in devel jobs

always apt-get update in devel jobs

# generated from @template_name

FROM ubuntu:@os_code_name
MAINTAINER Dirk Thomas dthomas+buildfarm@@osrfoundation.org

VOLUME ["/var/cache/apt/archives"]

ENV DEBIAN_FRONTEND noninteractive
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV TZ @timezone

RUN useradd -u @uid -m buildfarm

@(TEMPLATE(
    'snippet/add_distribution_repositories.Dockerfile.em',
    distribution_repository_keys=distribution_repository_keys,
    distribution_repository_urls=distribution_repository_urls,
    os_code_name=os_code_name,
    add_source=False,
))@

@(TEMPLATE(
    'snippet/add_wrapper_scripts.Dockerfile.em',
    wrapper_scripts=wrapper_scripts,
))@

# automatic invalidation once every day
RUN echo "@today_str"

@(TEMPLATE(
    'snippet/install_python3.Dockerfile.em',
    os_name=os_name,
    os_code_name=os_code_name,
))@

RUN python3 -u /tmp/wrapper_scripts/apt-get.py update-and-install -q -y git python3-apt python3-catkin-pkg python3-empy python3-rosdep python3-rosdistro wget

# always invalidate to actually have the latest apt and rosdep state
RUN echo "@now_str"
RUN python3 -u /tmp/wrapper_scripts/apt-get.py update

ENV ROSDISTRO_INDEX_URL @rosdistro_index_url

@(TEMPLATE(
    'snippet/rosdep_init.Dockerfile.em',
    custom_rosdep_urls=custom_rosdep_urls,
))@

USER buildfarm

ENTRYPOINT ["sh", "-c"]
@{
cmds = [
'rosdep update',
]
workspace_root = '/tmp/catkin_workspace'
if prerelease_overlay:
    workspace_root += ' /tmp/catkin_workspace_overlay'
cmd = \
    'PYTHONPATH=/tmp/ros_buildfarm:$PYTHONPATH python3 -u' + \
    ' /tmp/ros_buildfarm/scripts/devel/create_devel_task_generator.py' + \
    ' --rosdistro-name ' + rosdistro_name + \
    ' --workspace-root ' + workspace_root + \
    ' --os-name ' + os_name + \
    ' --os-code-name ' + os_code_name + \
    ' --arch ' + arch + \
    ' --distribution-repository-urls ' + ' '.join(distribution_repository_urls) + \
    ' --distribution-repository-key-files ' + ' ' .join(['/tmp/keys/%d.key' % i for i in range(len(distribution_repository_keys))])
cmds += [
    cmd +
    ' --dockerfile-dir /tmp/docker_build_and_install',
    cmd +
    ' --dockerfile-dir /tmp/docker_build_and_test' +
    ' --testing',
]
}@
CMD ["@(' && '.join(cmds))"]

# generated from @template_name

FROM ubuntu:@os_code_name
MAINTAINER Dirk Thomas dthomas+buildfarm@@osrfoundation.org

VOLUME ["/var/cache/apt/archives"]

ENV DEBIAN_FRONTEND noninteractive
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV TZ @timezone

RUN useradd -u @uid -m buildfarm

@(TEMPLATE(
    'snippet/add_distribution_repositories.Dockerfile.em',
    distribution_repository_keys=distribution_repository_keys,
    distribution_repository_urls=distribution_repository_urls,
    os_code_name=os_code_name,
    add_source=False,
))@

@(TEMPLATE(
    'snippet/add_wrapper_scripts.Dockerfile.em',
    wrapper_scripts=wrapper_scripts,
))@

# automatic invalidation once every day
RUN echo "@today_str"

@(TEMPLATE(
    'snippet/install_python3.Dockerfile.em',
    os_name=os_name,
    os_code_name=os_code_name,
))@

RUN python3 -u /tmp/wrapper_scripts/apt-get.py update-and-install -q -y git python3-apt python3-catkin-pkg python3-empy python3-rosdep python3-rosdistro wget

# always invalidate to actually have the latest rosdep state
RUN echo "@now_str"
ENV ROSDISTRO_INDEX_URL @rosdistro_index_url

@(TEMPLATE(
    'snippet/rosdep_init.Dockerfile.em',
    custom_rosdep_urls=custom_rosdep_urls,
))@

USER buildfarm

ENTRYPOINT ["sh", "-c"]
@{
cmds = [
'rosdep update',
]
workspace_root = '/tmp/catkin_workspace'
if prerelease_overlay:
    workspace_root += ' /tmp/catkin_workspace_overlay'
cmd = \
    'PYTHONPATH=/tmp/ros_buildfarm:$PYTHONPATH python3 -u' + \
    ' /tmp/ros_buildfarm/scripts/devel/create_devel_task_generator.py' + \
    ' --rosdistro-name ' + rosdistro_name + \
    ' --workspace-root ' + workspace_root + \
    ' --os-name ' + os_name + \
    ' --os-code-name ' + os_code_name + \
    ' --arch ' + arch + \
    ' --distribution-repository-urls ' + ' '.join(distribution_repository_urls) + \
    ' --distribution-repository-key-files ' + ' ' .join(['/tmp/keys/%d.key' % i for i in range(len(distribution_repository_keys))])
cmds += [
    cmd +
    ' --dockerfile-dir /tmp/docker_build_and_install',
    cmd +
    ' --dockerfile-dir /tmp/docker_build_and_test' +
    ' --testing',
]
}@
CMD ["@(' && '.join(cmds))"]


count nonexisting projects as skipped

count nonexisting projects as skipped

import hudson.model.Cause.UpstreamCause
import jenkins.model.Jenkins

job_names = []
@{
job_names = sorted(job_names)
group_size = 1000
}@
// group job names in chunks of @group_size to not exceed groovy limits
@[for i in range(0, len(job_names), group_size)]@
def add_job_names_@(int(i / group_size) + 1)(job_names) {
@[for j in range(i, min(i + group_size, len(job_names)))]@
job_names << '@(job_names[j])'
@[end for]@
}
add_job_names_@(int(i / group_size) + 1)(job_names)
@[end for]@

println "Triggering " + job_names.size + " jobs..."
triggered = 0
skipped = 0
for (job_name in job_names) {
    found_project = false
    for (p in Jenkins.instance.allItems) {
        if (p.name != job_name) continue
        found_project = true
        if (p.isDisabled()) {
            println "  " + job_name + " (skipped disabled project)"
            skipped += 1
            break
        }
        if (p.isBuilding()) {
            println "  " + job_name + " (skipped already building project)"
            skipped += 1
            break
        }
        if (p.isInQueue()) {
            println "  " + job_name + " (skipped already queued project)"
            skipped += 1
            break
        }
        println job_name
        p.scheduleBuild(new UpstreamCause(binding.variables["build"]))
        triggered += 1
        break
    }
    if (!found_project) {
        println "  " + job_name + " (skipped nonexisting project)"
        skipped += 1
    }
}
println "Triggered " + triggered + " jobs, skipped " + skipped + " jobs."

import hudson.model.Cause.UpstreamCause
import jenkins.model.Jenkins

job_names = []
@{
job_names = sorted(job_names)
group_size = 1000
}@
// group job names in chunks of @group_size to not exceed groovy limits
@[for i in range(0, len(job_names), group_size)]@
def add_job_names_@(int(i / group_size) + 1)(job_names) {
@[for j in range(i, min(i + group_size, len(job_names)))]@
job_names << '@(job_names[j])'
@[end for]@
}
add_job_names_@(int(i / group_size) + 1)(job_names)
@[end for]@

println "Triggering " + job_names.size + " jobs..."
triggered = 0
skipped = 0
for (job_name in job_names) {
    for (p in Jenkins.instance.allItems) {
        if (p.name != job_name) continue
        if (p.isDisabled()) {
            println "  " + job_name + " (skipped disabled project)"
            skipped += 1
            break
        }
        if (p.isBuilding()) {
            println "  " + job_name + " (skipped already building project)"
            skipped += 1
            break
        }
        if (p.isInQueue()) {
            println "  " + job_name + " (skipped already queued project)"
            skipped += 1
            break
        }
        println job_name
        p.scheduleBuild(new UpstreamCause(binding.variables["build"]))
        triggered += 1
        break
    }
}
println "Triggered " + triggered + " jobs, skipped " + skipped + " jobs."


Remove lexing test file

Remove lexing test file

#!dist/emi

var 🚀;

var 🍺;

var rolltide = "#ROLLTIDE🐘";

var 🇺🇸 = "USA";

var dash-var;
var snake_case;

var functio = "lol, not a function";
var functiono = "lol, not a function";

var multilineString = "This string spans
across multiple lines";

var num = -14123;

if(num > 0){
	num = 0;
}
else{
	num = -1;
}

var string = "This is a test string";

var stringWithQuotes = "he said \"hello\" to me";

--num;

var fancylètter;

var num2 = 1315;

# testing comments ;;;; { } [ ]
// testing comments ;;;; { } [ ]

var l = lambda(a, b)->{a * b;};

function testFunc(x, y){
	x + y;
}

while(true){
	num2 = num2 + 5;
}

var b = true;

do{
	num = num + 10;
} while(num < 0);