def main():
    # global try
    try:

        # parse command line options
        (options, args) = get_options(['stack', 'rosdistro'], ['repeat', 'source-only'])
        if not options:
            return -1

        # set environment
        print "Setting up environment"
        env = get_environment()
        env['ROS_PACKAGE_PATH'] = '%s:%s:%s:/opt/ros/%s/stacks'%(env['INSTALL_DIR']+'/'+STACK_DIR,
                                                                 env['INSTALL_DIR']+'/'+DEPENDS_DIR,
                                                                 env['INSTALL_DIR']+'/'+DEPENDS_ON_DIR,
                                                                 options.rosdistro)
        if 'ros' in options.stack:
            env['ROS_ROOT'] = env['INSTALL_DIR']+'/'+STACK_DIR+'/ros'
            print "We're building ROS, so setting the ROS_ROOT to %s"%(env['ROS_ROOT'])
        else:
            env['ROS_ROOT'] = '/opt/ros/%s/ros'%options.rosdistro
        env['PYTHONPATH'] = env['ROS_ROOT']+'/core/roslib/src'
        env['PATH'] = '/opt/ros/%s/ros/bin:%s'%(options.rosdistro, os.environ['PATH'])
        print "Environment set to %s"%str(env)

        # Parse distro file
        rosdistro_obj = rosdistro.Distro(get_rosdistro_file(options.rosdistro))
        print 'Operating on ROS distro %s'%rosdistro_obj.release_name


        # Install the stacks to test from source
        print 'Installing the stacks to test from source'
        rosinstall = ''
        for stack in options.stack:
            rosinstall += stack_to_rosinstall(rosdistro_obj.stacks[stack], 'devel')
        rosinstall_file = '%s.rosinstall'%STACK_DIR
        print 'Generating rosinstall file [%s]'%(rosinstall_file)
        print 'Contents:\n\n'+rosinstall+'\n\n'
        with open(rosinstall_file, 'w') as f:
            f.write(rosinstall)
            print 'rosinstall file [%s] generated'%(rosinstall_file)
        call('rosinstall --rosdep-yes %s /opt/ros/%s %s'%(STACK_DIR, options.rosdistro, rosinstall_file), env,
             'Install the stacks to test from source.')


        # get all stack dependencies of stacks we're testing
        print "Computing dependencies of stacks we're testing"
        depends_all = []
        for stack in options.stack:    
            stack_xml = '%s/%s/stack.xml'%(STACK_DIR, stack)
            call('ls %s'%stack_xml, env, 'Checking if stack %s contains "stack.xml" file'%stack)
            with open(stack_xml) as stack_file:
                depends_one = [str(d) for d in stack_manifest.parse(stack_file.read()).depends]  # convert to list
                print 'Dependencies of stack %s: %s'%(stack, str(depends_one))
                for d in depends_one:
                    if not d in options.stack and not d in depends_all:
                        print 'Adding dependencies of stack %s'%d
                        get_depends_all(rosdistro_obj, d, depends_all)
                        print 'Resulting total dependencies of all stacks that get tested: %s'%str(depends_all)

        if len(depends_all) > 0:
            if options.source_only:
                # Install dependencies from source
                print 'Installing stack dependencies from source'
                rosinstall = stacks_to_rosinstall(depends_all, rosdistro_obj.released_stacks, 'release-tar')
                rosinstall_file = '%s.rosinstall'%DEPENDS_DIR
                print 'Generating rosinstall file [%s]'%(rosinstall_file)
                print 'Contents:\n\n'+rosinstall+'\n\n'
                with open(rosinstall_file, 'w') as f:
                    f.write(rosinstall)
                    print 'rosinstall file [%s] generated'%(rosinstall_file)
                call('rosinstall --rosdep-yes %s /opt/ros/%s %s'%(DEPENDS_DIR, options.rosdistro, rosinstall_file), env,
                     'Install the stack dependencies from source.')
            else:
                # Install Debian packages of stack dependencies
                print 'Installing debian packages of "%s" dependencies: %s'%(stack, str(depends_all))
                call('sudo apt-get update', env)
                call('sudo apt-get install %s --yes'%(stacks_to_debs(depends_all, options.rosdistro)), env)
        else:
            print 'Stack(s) %s do(es) not have any dependencies, not installing anything now'%str(options.stack)


        # Install system dependencies of stacks re're testing
        print "Installing system dependencies of stacks we're testing"
        call('rosmake rosdep', env)
        for stack in options.stack:
            call('rosdep install -y %s'%stack, env,
                 'Install system dependencies of stack %s'%stack)


        # Run hudson helper for stacks only
        print "Running Hudson Helper for stacks we're testing"
        res = 0
        for r in range(0, int(options.repeat)+1):
            env['ROS_TEST_RESULTS_DIR'] = env['ROS_TEST_RESULTS_DIR'] + '/' + STACK_DIR + '_run_' + str(r)
            helper = subprocess.Popen(('./hudson_helper --dir-test %s build'%STACK_DIR).split(' '), env=env)
            helper.communicate()
            if helper.returncode != 0:
                res = helper.returncode
        if res != 0:
            return res


        # parse debian repository configuration file to get stack dependencies
        arch = 'i386'
        if '64' in call('uname -mrs', env):
            arch = 'amd64'
        ubuntudistro = call('lsb_release -a', env).split('Codename:')[1].strip()
        print "Parsing apt repository configuration file to get stack dependencies, for %s machine running %s"%(arch, ubuntudistro)
        apt_deps = parse_apt(ubuntudistro, arch, options.rosdistro)
        if not apt_deps.has_debian_package(options.stack):
            print "Stack does not yet have a Debian package. No need to test dependenies"
            return 0

        # all stacks that depends on the tested stacks, excluding the tested stacks.
        depends_on_all = apt_deps.depends_on_all(options.stack)
        remove(depends_on_all, options.stack)

        # if tested stacks are all in a variant, then only test stacks that are also in a variant
        variant_stacks = []
        for name, v in rosdistro_obj.variants.iteritems():
            variant_stacks = variant_stacks + v.stack_names
        all_in_variant = True
        for s in options.stack:
            if not s in variant_stacks:
                all_in_variant = False
        if all_in_variant:
            print "Limiting test to stacks that are in a variant"
            for s in depends_on_all:
                if not s in variant_stacks:
                    depends_on_all.remove(s)

        # all stack dependencies of above stack list, except for the test stack dependencies
        depends_all_depends_on_all = apt_deps.depends_all(depends_on_all)
        remove(depends_all_depends_on_all, options.stack)
        remove(depends_all_depends_on_all, depends_all)


        # Install dependencies of depends_on_all stacks, excluding dependencies of test stacks.
        if len(depends_all_depends_on_all) > 0:
            print "Install dependencies of depends_on_all stacks, excluding dependencies of test stacks."
            if not options.source_only:
                # Install Debian packages of 'depends_all_depends_on_all' list
                print 'Installing Debian package of %s'%str(depends_all_depends_on_all)
                call('sudo apt-get install %s --yes'%(stacks_to_debs(depends_all_depends_on_all, options.rosdistro)), env)
            else:
                # Install source of 'depends_all_depends_on_all' list
                print 'Installing source of %s'%str(depends_all_depends_on_all)
                rosinstall = stacks_to_rosinstall(depends_all_depends_on_all, rosdistro_obj.released_stacks, 'release-tar')
                rosinstall_file = '%s_depends_all_depends_on_all.rosinstall'%DEPENDS_ON_DIR
                print 'Generating rosinstall file [%s]'%(rosinstall_file)
                print 'Contents:\n\n'+rosinstall+'\n\n'
                with open(rosinstall_file, 'w') as f:
                    f.write(rosinstall)
                    print 'rosinstall file [%s] generated'%(rosinstall_file)
                call('rosinstall --rosdep-yes %s /opt/ros/%s %s %s'%(DEPENDS_ON_DIR, options.rosdistro, STACK_DIR, rosinstall_file), env,
                     'Install dependencies of depends_on_all stacks, excluding dependencies of test stacks.')
        else:
            print "No dependencies of depends_on_all stacks"
            

        # Install all stacks that depend on this stack from source
        if len(depends_on_all) > 0:
            print 'Installing depends_on_all stacks from source: %s'%str(depends_on_all)
            rosinstall = stacks_to_rosinstall(depends_on_all, rosdistro_obj.released_stacks, 'release-tar')
            rosinstall_file = '%s.rosinstall'%DEPENDS_ON_DIR
            print 'Generating rosinstall file [%s]'%(rosinstall_file)
            print 'Contents:\n\n'+rosinstall+'\n\n'
            with open(rosinstall_file, 'w') as f:
                f.write(rosinstall)
                print 'rosinstall file [%s] generated'%(rosinstall_file)
            call('rosinstall --rosdep-yes %s /opt/ros/%s %s %s'%(DEPENDS_ON_DIR, options.rosdistro, STACK_DIR, rosinstall_file), env,
                 'Install the stacks that depend on the stacks that are getting tested from source.')

            # Run hudson helper for all stacks
            print 'Running Hudson Helper'
            env['ROS_TEST_RESULTS_DIR'] = env['ROS_TEST_RESULTS_DIR'] + '/' + DEPENDS_ON_DIR
            helper = subprocess.Popen(('./hudson_helper --dir-test %s build'%DEPENDS_ON_DIR).split(' '), env=env)
            helper.communicate()
            return helper.returncode
        else:
            print "No stacks depends on this stack. Tests finished"


    # global except
    except Exception, ex:
        print "Global exception caught. Generating email"
        generate_email("%s. Check the console output for test failure details."%ex, env)
        traceback.print_exc(file=sys.stdout)
        raise ex
def main():
    # global try
    try:
        # parse command line options
        (options, args) = get_options(['stack', 'rosdistro', 'githubuser', 'email'], ['repeat', 'source-only'])
        if not options:
            return -1

        # set environment
        env = get_environment()
        env['ROS_PACKAGE_PATH'] = '%s:%s:/opt/ros/%s/stacks'%(env['INSTALL_DIR']+'/'+STACK_DIR,
                                                                 env['INSTALL_DIR']+'/'+DEPENDS_DIR,
                                                                 options.rosdistro) # env['INSTALL_DIR']+'/'+DEPENDS_ON_DIR,

        if 'ros' in options.stack:
            env['ROS_ROOT'] = env['INSTALL_DIR']+'/'+STACK_DIR+'/ros'
            print "We're building ROS, so setting the ROS_ROOT to %s"%(env['ROS_ROOT'])
        else:
            env['ROS_ROOT'] = '/opt/ros/%s/ros'%options.rosdistro
        env['PYTHONPATH'] = env['ROS_ROOT']+'/core/roslib/src'
        env['PATH'] = '/opt/ros/%s/ros/bin:%s'%(options.rosdistro, os.environ['PATH'])
        print "HOME: %s"%(env['HOME'])


        # Parse distro file
        rosdistro_obj = rosdistro.Distro(get_rosdistro_file(options.rosdistro))
        print 'Operating on ROS distro %s'%rosdistro_obj.release_name


        # Install the stacks to test from source
        print 'Installing the stacks to test from source'
        rosinstall = ''
        for stack in options.stack:
            if not stack_forked(options.githubuser, stack):
                print "Stack %s is not forked for user %s" %(stack, options.githubuser)
                print "Using 'ipa320' stack instead"
                options.githubuser = "******"
            if stack in FHG_STACKS_PUBLIC: # create rosinstall file for public stacks
                rosinstall += '- git: {local-name: %s, uri: "git://github.com/%s/%s.git", branch-name: master}\n'%(stack, options.githubuser, stack)
            elif stack in FHG_STACKS_PRIVATE: # clone private stacks
                call('git clone [email protected]:%s/%s.git %s/%s'%(options.githubuser, stack, STACK_DIR, stack), env, 'Clone private stack [%s] to test'%(stack))
            else:
                rosinstall += stack_to_rosinstall(rosdistro_obj.stacks[stack], 'devel')

        if rosinstall != '': # call rosinstall command
            rosinstall_file = '%s.rosinstall'%STACK_DIR
            print 'Generating rosinstall file [%s]'%(rosinstall_file)
            print 'Contents:\n\n'+rosinstall+'\n\n'
            with open(rosinstall_file, 'w') as f:
                f.write(rosinstall)
            print 'rosinstall file [%s] generated'%(rosinstall_file)
            print STACK_DIR
            print options.rosdistro
            call('rosinstall --rosdep-yes %s /opt/ros/%s %s'%(STACK_DIR, options.rosdistro, rosinstall_file), env,
                 'Install the stacks to test from source.')
            
        
        # get all stack dependencies of stacks we're testing

        depends_all = {"public" : [], "private" : [], "other" : []}
        for stack in options.stack:
            if stack == "cob3_intern":
                COB3_STACKS = get_cob3_intern_stacks(STACK_DIR+'/cob3_intern')
                COB3_PACKAGES = get_cob3_intern_stacks(STACK_DIR+'/cob3_intern', packages=True)
#            stack_xml = '%s/%s/stack.xml'%(STACK_DIR, stack)
#            call('ls %s'%stack_xml, env, 'Checking if stack %s contains "stack.xml" file'%stack)
#            with open(stack_xml) as stack_file:
#                depends_one = [str(d) for d in stack_manifest.parse(stack_file.read()).depends]  # convert to list
            depends_one = get_depends_one(stack, options.githubuser)
            #print 'Dependencies of stack %s: %s'%(stack, str(depends_one))
            for d in depends_one:
                if not d in options.stack and not d in depends_all:
                    if stack == "cob3_intern":
                        if not d in COB3_PACKAGES and not d in COB3_STACKS:
                            print 'Adding dependencies of stack %s'%d
                            get_depends_all(d, depends_all, options.githubuser, 1)
                            print 'Resulting total dependencies of all stacks that get tested: %s'%str(depends_all)
                    else:
                        print 'Adding dependencies of stack %s'%d
                        get_depends_all(d, depends_all, options.githubuser, 1)
                        print 'Resulting total dependencies of all stacks that get tested: %s'%str(depends_all) 
        
        print 'Dependencies of %s:'%str(options.stack)
        print str(depends_all)

        if len(depends_all["private"]) > 0:
            print 'Cloning private github fork(s)'
            downloaded = False
            for stack in depends_all["private"]:
                if stack in COB3_INTERN_STACKS:
                    if not downloaded:
                        if not stack_forked(options.githubuser, "cob3_intern", "/blob/master/%s/Makefile"%stack):
                            options.githubuser = "******"
                        call('git clone [email protected]:%s/cob3_intern.git %s'%(options.githubuser, "/tmp/cob3_intern"), env, 'Clone private stack cob3_intern')
                        downloaded = True
                        
                    call('mv /tmp/cob3_intern/%s %s'%(stack, DEPENDS_DIR), env, 'Move required stack %s to %s'%(stack, DEPENDS_DIR))
                    
                else:
                    if not stack_forked(options.githubuser, stack):
                        options.githubuser = "******"
                    call('git clone [email protected]:%s/%s.git %s'%(options.githubuser, stack, DEPENDS_DIR), env, 'Clone private stack [%s] to test'%(stack))
                    

        if len(depends_all["public"]) > 0:
            for stack in depends_all["public"]:
                if not stack_forked(options.githubuser, stack):
                    options.githubuser = "******"
                rosinstall += '- git: {local-name: %s, uri: "git://github.com/%s/%s.git", branch-name: master}\n'%(stack, options.githubuser, stack)
            
            print 'Installing stack dependencies from public github fork'
            rosinstall_file = '%s.rosinstall'%DEPENDS_DIR
            with open(rosinstall_file, 'w') as f:
                f.write(rosinstall)
            call('rosinstall --rosdep-yes %s /opt/ros/%s %s'%(DEPENDS_DIR, options.rosdistro, rosinstall_file), env,
                 'Install the stack dependencies from source.')
     
        if len(depends_all["other"]) > 0:
            # Install Debian packages of stack dependencies
            print 'Installing debian packages of "%s" dependencies: %s'%(str(options.stack), str(depends_all["other"]))
            call('sudo apt-get update', env)
            call('sudo apt-get install %s --yes'%(stacks_to_debs(depends_all["other"], options.rosdistro)), env)
 
        depends_no = 0
        for i in iter(depends_all): depends_no += len(depends_all[i])
        if depends_no == 0:
            print 'Stack(s) %s do(es) not have any dependencies, not installing anything now'%str(options.stack)
        
      
        # Install system dependencies of stacks we're testing
        print "Installing system dependencies of stacks we're testing"
        call('rosmake rosdep', env)
        for stack in options.stack:
            if stack == "cob3_intern":
                call('make -f /tmp/install_dir/%s/cob3_intern/Makefile ros-install-%s'%(STACK_DIR, options.rosdistro), env, 'ros-install')
                call('make -f /tmp/install_dir/%s/cob3_intern/Makefile ros-skip-blacklist'%STACK_DIR, env, 'ros-skip-blacklist')
            else:
                call('rosdep install -y %s'%stack, env,
                     'Install system dependencies of stack %s'%stack)
                 
        # Run hudson helper for stacks only
        print 'Running Hudson Helper'
        res = 0
        for r in range(0, int(options.repeat)+1):
            env['ROS_TEST_RESULTS_DIR'] = env['ROS_TEST_RESULTS_DIR'] + '/' + STACK_DIR + '_run_' + str(r)
            helper = subprocess.Popen(('./ros_release/hudson/src/hudson_helper_fhg.py --dir-test %s --email %s build'%(STACK_DIR, options.email)).split(' '), env=env)
            helper.communicate()
            if helper.returncode != 0:
                res = helper.returncode
        if res != 0:
            return res
        
        build_failures = os.path.join(os.environ['WORKSPACE'], 'build_output', 'buildfailures.txt')
        build_failures_context = os.path.join(os.environ['WORKSPACE'], 'build_output', 'buildfailures-with-context.txt')
        test_failures = os.path.join(os.environ['WORKSPACE'], 'test_output', 'testfailures.txt')
        body = ''
        if os.path.exists(build_failures):
            body += open(build_failures).read()
            body += '\n\n'
        if os.path.exists(test_failures):
            body += open(test_failures).read()
            body += '\n\n'
        if os.path.exists(build_failures_context):
            body += open(build_failures_context).read()
            body += '\n\n'
        print "\n******************************************************************"
        print "***                   BUILD AND TEST FAILURES                  ***"
        print "******************************************************************\n"
        print body
        print "******************************************************************"
        
        # parse debian repository configuration file to get stack dependencies
        arch = 'i386'
        if '64' in call('uname -mrs', env):
            arch = 'amd64'
        ubuntudistro = call('lsb_release -a', env).split('Codename:')[1].strip()
        print "Parsing apt repository configuration file to get stack dependencies, for %s machine running %s"%(arch, ubuntudistro)
        apt_deps = parse_apt(ubuntudistro, arch, options.rosdistro)
        # all stacks that depends on the tested stacks, excluding the tested stacks.
        depends_on_all = apt_deps.depends_on_all(options.stack)
        remove(depends_on_all, options.stack)
        # all stack dependencies of above stack list, except for the test stack dependencies
        depends_all_depends_on_all = apt_deps.depends_all(depends_on_all)
        remove(depends_all_depends_on_all, options.stack)
        remove(depends_all_depends_on_all, depends_all)
        
    # global except
    except Exception, ex:
        print "Global exception caught. Generating email"
        generate_email("%s. Check the console output for test failure details."%ex, env)
        traceback.print_exc(file=sys.stdout)
        raise ex
def main():
    # global try
    try:
        print "Parsing arguments"

        # parse command line options
        (options, args) = get_options(['stack', 'rosdistro'],
                                      ['repeat', 'source-only'])
        print "options", options, "args", args
        if not options:
            return -1

        # set environment
        print "Setting up environment"
        env = get_environment()
        env['ROS_PACKAGE_PATH'] = '%s:%s:%s:/opt/ros/%s/stacks' % (
            env['INSTALL_DIR'] + '/' + STACK_DIR,
            env['INSTALL_DIR'] + '/' + DEPENDS_DIR,
            env['INSTALL_DIR'] + '/' + DEPENDS_ON_DIR, options.rosdistro)
        if 'ros' in options.stack:
            env['ROS_ROOT'] = env['INSTALL_DIR'] + '/' + STACK_DIR + '/ros'
            print "We're building ROS, so setting the ROS_ROOT to %s" % (
                env['ROS_ROOT'])
            ros_tested_ignore_return = True
        else:
            env['ROS_ROOT'] = '/opt/ros/%s/ros' % options.rosdistro
            ros_tested_ignore_return = False
        env['PYTHONPATH'] = env['ROS_ROOT'] + '/core/roslib/src'
        env['PATH'] = '/opt/ros/%s/ros/bin:%s' % (options.rosdistro,
                                                  os.environ['PATH'])
        print "Environment set to %s" % str(env)

        # Parse distro file
        rosdistro_obj = rosdistro.Distro(get_rosdistro_file(options.rosdistro))
        print 'Operating on ROS distro %s' % rosdistro_obj.release_name

        # Install the stacks to test from source
        print 'Installing the stacks to test from source'
        rosinstall = ''
        for stack in options.stack:
            rosinstall += stack_to_rosinstall(rosdistro_obj.stacks[stack],
                                              'devel')
        rosinstall_file = '%s.rosinstall' % STACK_DIR
        print 'Generating rosinstall file [%s]' % (rosinstall_file)
        print 'Contents:\n\n' + rosinstall + '\n\n'
        with open(rosinstall_file, 'w') as f:
            f.write(rosinstall)
            print 'rosinstall file [%s] generated' % (rosinstall_file)

        call('rosinstall --rosdep-yes %s /opt/ros/%s %s' %
             (STACK_DIR, options.rosdistro, rosinstall_file),
             env,
             'Install the stacks to test from source.',
             ignore_fail=ros_tested_ignore_return)

        # get all stack dependencies of stacks we're testing
        print "Computing dependencies of stacks we're testing"
        depends_all = []
        for stack in options.stack:
            stack_xml = '%s/%s/stack.xml' % (STACK_DIR, stack)
            call('ls %s' % stack_xml, env,
                 'Checking if stack %s contains "stack.xml" file' % stack)
            with open(stack_xml) as stack_file:
                depends_one = [
                    str(d)
                    for d in stack_manifest.parse(stack_file.read()).depends
                ]  # convert to list
                print 'Dependencies of stack %s: %s' % (stack,
                                                        str(depends_one))
                for d in depends_one:
                    if not d in options.stack and not d in depends_all:
                        print 'Adding dependencies of stack %s' % d
                        get_depends_all(rosdistro_obj, d, depends_all)
                        print 'Resulting total dependencies of all stacks that get tested: %s' % str(
                            depends_all)

        if len(depends_all) > 0:
            if options.source_only:
                # Install dependencies from source
                print 'Installing stack dependencies from source'
                rosinstall = stacks_to_rosinstall(
                    depends_all, rosdistro_obj.released_stacks, 'release-tar')
                rosinstall_file = '%s.rosinstall' % DEPENDS_DIR
                print 'Generating rosinstall file [%s]' % (rosinstall_file)
                print 'Contents:\n\n' + rosinstall + '\n\n'
                with open(rosinstall_file, 'w') as f:
                    f.write(rosinstall)
                    print 'rosinstall file [%s] generated' % (rosinstall_file)
                call('rosinstall --rosdep-yes %s /opt/ros/%s %s' %
                     (DEPENDS_DIR, options.rosdistro, rosinstall_file),
                     env,
                     'Install the stack dependencies from source.',
                     ignore_fail=ros_tested_ignore_return)
            else:
                # Install Debian packages of stack dependencies
                print 'Installing debian packages of "%s" dependencies: %s' % (
                    stack, str(depends_all))
                call('sudo apt-get update', env)
                call(
                    'sudo apt-get install %s --yes' %
                    (stacks_to_debs(depends_all, options.rosdistro)), env)
        else:
            print 'Stack(s) %s do(es) not have any dependencies, not installing anything now' % str(
                options.stack)

        # Install system dependencies of stacks re're testing
        print "Installing system dependencies of stacks we're testing"
        call('rosmake rosdep', env)
        for stack in options.stack:
            call('rosdep install -y %s' % stack, env,
                 'Install system dependencies of stack %s' % stack)

        # Run hudson helper for stacks only
        print "Running Hudson Helper for stacks we're testing"
        res = 0
        for r in range(0, int(options.repeat) + 1):
            env['ROS_TEST_RESULTS_DIR'] = env[
                'ROS_TEST_RESULTS_DIR'] + '/' + STACK_DIR + '_run_' + str(r)
            helper = subprocess.Popen(
                ('./hudson_helper --dir-test %s build' % STACK_DIR).split(' '),
                env=env)
            helper.communicate()
            if helper.returncode != 0:
                res = helper.returncode
        if res != 0:
            return res

        # parse debian repository configuration file to get stack dependencies
        (arch, ubuntudistro) = get_sys_info()
        print "Parsing apt repository configuration file to get stack dependencies, for %s machine running %s" % (
            arch, ubuntudistro)
        apt_deps = parse_apt(ubuntudistro, arch, options.rosdistro)
        if not apt_deps.has_debian_package(options.stack):
            print "Stack does not yet have a Debian package. No need to test dependenies"
            return 0

        # all stacks that depends on the tested stacks, excluding the tested stacks.
        depends_on_all = apt_deps.depends_on_all(options.stack)
        remove(depends_on_all, options.stack)

        # if tested stacks are all in a variant, then only test stacks that are also in a variant
        variant_stacks = []
        for name, v in rosdistro_obj.variants.iteritems():
            variant_stacks = variant_stacks + v.stack_names
        all_in_variant = True
        for s in options.stack:
            if not s in variant_stacks:
                all_in_variant = False
        if all_in_variant:
            print "Limiting test to stacks that are in a variant"
            for s in depends_on_all:
                if not s in variant_stacks:
                    depends_on_all.remove(s)

        # all stack dependencies of above stack list, except for the test stack dependencies
        depends_all_depends_on_all = apt_deps.depends_all(depends_on_all)
        remove(depends_all_depends_on_all, options.stack)
        remove(depends_all_depends_on_all, depends_all)

        # Install dependencies of depends_on_all stacks, excluding dependencies of test stacks.
        if len(depends_all_depends_on_all) > 0:
            print "Install dependencies of depends_on_all stacks, excluding dependencies of test stacks."
            if not options.source_only:
                # Install Debian packages of 'depends_all_depends_on_all' list
                print 'Installing Debian package of %s' % str(
                    depends_all_depends_on_all)
                call(
                    'sudo apt-get install %s --yes' % (stacks_to_debs(
                        depends_all_depends_on_all, options.rosdistro)), env)
            else:
                # Install source of 'depends_all_depends_on_all' list
                print 'Installing source of %s' % str(
                    depends_all_depends_on_all)
                rosinstall = stacks_to_rosinstall(
                    depends_all_depends_on_all, rosdistro_obj.released_stacks,
                    'release-tar')
                rosinstall_file = '%s_depends_all_depends_on_all.rosinstall' % DEPENDS_ON_DIR
                print 'Generating rosinstall file [%s]' % (rosinstall_file)
                print 'Contents:\n\n' + rosinstall + '\n\n'
                with open(rosinstall_file, 'w') as f:
                    f.write(rosinstall)
                    print 'rosinstall file [%s] generated' % (rosinstall_file)
                call(
                    'rosinstall --rosdep-yes %s /opt/ros/%s %s %s' %
                    (DEPENDS_ON_DIR, options.rosdistro, STACK_DIR,
                     rosinstall_file),
                    env,
                    'Install dependencies of depends_on_all stacks, excluding dependencies of test stacks.',
                    ignore_fail=ros_tested_ignore_return)
        else:
            print "No dependencies of depends_on_all stacks"

        # Install all stacks that depend on this stack from source
        if len(depends_on_all) > 0:
            print 'Installing depends_on_all stacks from source: %s' % str(
                depends_on_all)
            rosinstall = stacks_to_rosinstall(depends_on_all,
                                              rosdistro_obj.released_stacks,
                                              'release-tar')
            rosinstall_file = '%s.rosinstall' % DEPENDS_ON_DIR
            print 'Generating rosinstall file [%s]' % (rosinstall_file)
            print 'Contents:\n\n' + rosinstall + '\n\n'
            with open(rosinstall_file, 'w') as f:
                f.write(rosinstall)
                print 'rosinstall file [%s] generated' % (rosinstall_file)
            call(
                'rosinstall --rosdep-yes %s /opt/ros/%s %s %s' %
                (DEPENDS_ON_DIR, options.rosdistro, STACK_DIR,
                 rosinstall_file),
                env,
                'Install the stacks that depend on the stacks that are getting tested from source.',
                ignore_fail=ros_tested_ignore_return)

            # Run hudson helper for all stacks
            print 'Running Hudson Helper'
            env['ROS_TEST_RESULTS_DIR'] = env[
                'ROS_TEST_RESULTS_DIR'] + '/' + DEPENDS_ON_DIR
            helper = subprocess.Popen(('./hudson_helper --dir-test %s build' %
                                       DEPENDS_ON_DIR).split(' '),
                                      env=env)
            helper.communicate()
            return helper.returncode
        else:
            print "No stacks depends on this stack. Tests finished"

    # global except
    except Exception, ex:
        print "Global exception caught. Generating email.  Exception:", ex
        generate_email(
            "%s. Check the console output for test failure details." % ex, env)
        traceback.print_exc(file=sys.stdout)
        raise ex
def main():
    # global try
    try:
        print "Starting run_auto_stack_devel script"

        # parse command line options
        print "Parsing command line options"
        (options, args) = get_options(['stack', 'rosdistro'], ['repeat', 'source-only'])
        if not options:
            return -1
        if len(options.stack) > 1:
            print "You can only provide one stack at a time"
            return -1
        options.stack = options.stack[0]
        print "parsed options: %s"%str(options)

        # set environment
        print "Setting up environment"
        env = get_environment()
        if options.source_only or options.stack == 'ros':
            ros_path = env['WORKSPACE']
        else:
            ros_path = '/opt/ros/%s'%options.rosdistro
        print "Working in %s"%ros_path
        env['ROS_PACKAGE_PATH'] = '%s:%s'%(env['WORKSPACE'], ros_path)
        env['ROS_ROOT'] = '%s/ros'%ros_path
        env['PYTHONPATH'] = env['ROS_ROOT']+'/core/roslib/src'
        env['PATH'] = '%s/ros/bin:%s'%(ros_path, os.getenv('PATH'))
        stack_dir = env['WORKSPACE']+'/'+options.stack
        print("Environment set to %s"%str(env))

        # Parse distro file
        rosdistro_obj = rosdistro.Distro(get_rosdistro_file(options.rosdistro))
        print 'Operating on ROS distro %s'%rosdistro_obj.release_name

        # get all stack dependencies of the stack we're testing
        depends = []
        stack_xml = '%s/stack.xml'%stack_dir
        call('ls %s'%stack_xml, env, 'Checking if stack %s contains "stack.xml" file'%options.stack)
        with open(stack_xml) as stack_file:
            depends_one = [str(d) for d in stack_manifest.parse(stack_file.read()).depends]  # convert to list
            print 'Dependencies of stack %s: %s'%(options.stack, str(depends_one))
            for d in depends_one:
                if not d == options.stack and not d in depends:
                    print 'Adding dependencies of stack %s'%d
                    get_depends_all(rosdistro_obj, d, depends)
                    print 'Resulting total dependencies: %s'%str(depends)

        if len(depends) > 0:
            if not options.source_only:
                # check if Debian packages of stack exist
                (arch, ubuntudistro) = get_sys_info()
                print "Parsing apt repository configuration file to get stack dependencies, for %s machine running %s"%(arch, ubuntudistro)
                apt_deps = parse_apt(ubuntudistro, arch, options.rosdistro)
                for d in depends:
                    if not apt_deps.has_debian_package(d):
                        print "Stack %s does not have Debian package yet. Stopping this test." %d
                        generate_email("Stack %s does not have Debian package yet. Stopping this test."%d, env)
                        return 0

                # Install Debian packages of stack dependencies
                print 'Installing debian packages of stack dependencies from stacks %s'%str(options.stack)
                call('sudo apt-get update', env)
                print 'Installing debian packages of "%s" dependencies: %s'%(options.stack, str(depends))
                call('sudo apt-get install %s --yes'%(stacks_to_debs(depends, options.rosdistro)), env)
            else:
                # Install stack dependencies from source
                print 'Installing stack dependencies from source'
                rosinstall = stacks_to_rosinstall(depends, rosdistro_obj.released_stacks, 'release-tar')
                print 'Using rosinstall yaml: %s'%rosinstall
                rosinstall_file = '%s.rosinstall'%options.stack
                with open(rosinstall_file, 'w') as f:
                    f.write(rosinstall)
                call('rosinstall --delete-changed-uris --rosdep-yes %s %s'%(env['WORKSPACE'], rosinstall_file), env,
                     'Install the stack dependencies from source.')
        else:
            print 'Stack %s does not have any dependencies, not installing anything now'%str(options.stack)

        # Install system dependencies of stack itself
        print 'Installing system dependencies of stack %s'%options.stack
        call('rosmake rosdep', env)
        call('rosdep install -y %s'%options.stack, env,
             'Install system dependencies of stack %s'%options.stack)

        # Start Hudson Helper
        print 'Running Hudson Helper in folder %s'%stack_dir
        res = 0
        test_results = env['ROS_TEST_RESULTS_DIR']
        for r in range(0, options.repeat+1):
            env['ROS_TEST_RESULTS_DIR'] = test_results + '/run_'+str(r)
            #res_one = subprocess.call(('./hudson_helper --dir-test %s build'%stack_dir).split(' '), env=env)
            res_one = subprocess.call(('./hudson_helper --pkg-test %s build'%options.stack).split(' '), env=env)
            if res_one != 0:
                res = res_one
        return res

    # global except
    except Exception, ex:
        print "Global exception caught. Generating email with exception text %s"%str(ex)
        generate_email("%s. Check the console output for test failure details."%str(ex), env)
        traceback.print_exc(file=sys.stdout)
        raise ex