예제 #1
0
def package_install(path, package, batch=False, pkgrepo=None, pkglist=None):
    """
    Install a package or roll back to last coherent state upon failure.
    If batch is True, do not update package list (caller will update).
    Returns True on success, else (error or already installed) False.
    """
    pkgpath = package_dir_path(path)
    if pkgrepo is None:
        pkgrepo = package_repo_open(pkgpath)
    if pkglist is None:
        pkglist = package_list_read(pkgpath)
    pkgnames = list(map(lambda x: x['name'], pkglist))
    try:
        _package_install_unsafe(path, package, pkgrepo, pkglist, pkgnames)
        pkgrepo.index.add(['.gitmodules', package.name])
        pkgrepo.index.commit('Installed ' + package.name)
        if not batch:
            package_list_add_many(pkgpath, [package])
    except AlreadyInstalledException as e:
        return e.link_updated
    except Exception as e:  # Installation failed, roll back
        try:
            sm = pkgrepo.submodule(package.name)
            sm.remove()
        except Exception:
            pass
        pkgrepo.git.clean('-fdX')  # Remove all untracked files
        writeln('Install aborted.')
        writeln(str(e))
        return False
    return True
예제 #2
0
def verify_path(path):
    """check if the project path is correct"""

    if not os.path.exists(path) or not os.path.isdir(path):
        writeln(
            '\nPath specified for project creation does not exist or is not a directory',
            color=Fore.RED)
        quit(2)
예제 #3
0
def package_update_all(path):
    """Update all installed packages"""
    repo = package_repo_open(package_dir_path(path))
    for sm in repo.submodules:
        write('Updating %s... ' % sm.name)
        remote = sm.module().remotes[0]
        remote.pull('-f')  # sm.update is defective; use this instead.
        writeln('Done.')
        if repo.is_dirty():  # Something has changed
            repo.index.commit('Updated ' + sm.name)
예제 #4
0
def update_wcosa(path, board, ide):
    """Updates existing WCosa project"""

    path = str(path)

    write('Updating work environment - ', color=Fore.CYAN)
    verify_path(path)

    templates_path = helper.linux_path(helper.get_wcosa_path() + '/templates')
    user_config_path = path + '/config.json'
    internal_config_path = path + '/wcosa/internal-config.json'
    general_cmake_path = path + '/wcosa/CMakeLists.txt'

    # create src, lib, and wcosa folders
    create_folders(path)

    # copy all then CMakeLists templates and configuration templates
    copyfile(templates_path + '/cmake/CMakeLists.txt.tpl', general_cmake_path)
    copyfile(templates_path + '/config/internal-config.json.tpl',
             internal_config_path)

    # recopy any missing files
    if not os.path.exists(path + '/config.json'):
        copyfile(templates_path + '/config/config.json.tpl', user_config_path)

    writeln('done')
    write('Updating configurations with new changes - ', color=Fore.CYAN)

    user_data = config.fill_user_config(user_config_path, board, Port(None),
                                        ide)
    project_data = config.fill_internal_config(internal_config_path, path,
                                               user_data)
    cmake.parse_update(general_cmake_path, project_data)

    if user_data['ide'] == 'clion':
        copyfile(templates_path + '/ide/clion/CMakeListsPrivate.txt.tpl',
                 path + '/CMakeListsPrivate.txt')

        # recopy any missing files
        if not os.path.exists(path + '/CMakeLists.txt'):
            copyfile(templates_path + '/ide/clion/CMakeLists.txt.tpl',
                     path + '/CMakeLists.txt')

        if not os.path.exists(path + '/.gitignore-files'):
            copyfile(templates_path + '/gitignore-files/.gitignore-clion',
                     path + '/.gitignore')

        cmake.parse_update(path + '/CMakeLists.txt', project_data)
        cmake.parse_update(path + '/CMakeListsPrivate.txt', project_data)
    elif not os.path.exists(path + '/.gitignore'):
        copyfile(templates_path + '/gitignore-files/.gitignore-general',
                 path + '/.gitignore')

    writeln('done')
예제 #5
0
파일: objects.py 프로젝트: waterloop/wcosa
    def verify(self):
        # verify the port
        ports = list(serial.tools.list_ports.comports())
        devices = []

        for p in ports:
            devices.append(p.device)

        if self.name not in devices:
            output.writeln('There is no device connected to this port',
                           Fore.RED)
            quit(2)
예제 #6
0
파일: wcosa.py 프로젝트: waterloop/wcosa
def print_boards():
    """Print all the available boards and their name"""

    boards = board_parser.get_all_board(helper.get_wcosa_path() +
                                        '/wcosa/boards.json')

    output.writeln('Boards compatible with this project are: ', Fore.CYAN)

    for curr_board in boards:
        name = board_parser.get_board_properties(
            curr_board,
            helper.get_wcosa_path() + '/wcosa/boards.json')['name']
        output.writeln('{:15s} --->\t{}'.format(curr_board, name))
예제 #7
0
def serial_monitor(port, baud):
    """
    Open serial monitor to the specified port with the given baud rate.
    """
    write('Serial Monitor ', Fore.CYAN)
    write(port, Fore.YELLOW)
    write(' @ ', Fore.CYAN)
    writeln(baud, Fore.YELLOW)

    sys.argv = ['monitor', '--exit-char', '3']
    try:
        miniterm.main(default_port=port or serial_ports(),
                      default_baudrate=baud or 9600)
    except KeyboardInterrupt:
        writeln('\nExiting serial monitor', Fore.CYAN)
예제 #8
0
def package_repo_init(pkgpath):
    """Initialize package repo"""
    write('Initializing package repository... ')
    sys.stdout.flush()
    pkgrepo = git.Repo.init(pkgpath)

    pkglist_exists = os.path.exists(PACKAGE_LIST_FILE)
    if not pkglist_exists:
        with open(PACKAGE_LIST_FILE, 'w+') as pkglist:
            pkglist.write('[]')  # Start with empty package list

    pkgrepo.index.commit('Initialized repository')
    writeln('Done')

    return pkgrepo
예제 #9
0
파일: objects.py 프로젝트: waterloop/wcosa
    def __init__(self, name):
        if name is None:
            self.same = True
            self.name = None
        else:
            self.name = name

            # verify the board
            boards = board_parser.get_all_board(helper.get_wcosa_path() +
                                                '/wcosa/boards.json')

            if name not in boards:
                output.writeln(
                    'Board Invalid. Run wcosa script with boards option to see all the valid boards',
                    Fore.RED)
                quit(2)

            self.same = False
예제 #10
0
def package_uninstall(path, package, batch=False, pkgrepo=None, pkglist=None):
    """
    Uninstall a package or unlink from given location if linked to multiple.
    If batch is True, do not update package list (caller will update).
    Returns True on success, else (on error) False.
    """
    pkgpath = package_dir_path(path)
    if pkgrepo is None:
        pkgrepo = package_repo_open(pkgpath)
    if pkglist is None:
        pkglist = package_list_read(pkgpath)
    pkgnames = list(map(lambda x: x['name'], pkglist))

    write('Uninstalling %s... ' % package.name)
    sys.stdout.flush()
    if package.name not in pkgnames:
        writeln('Not installed.')
        return False
    try:
        paths = pkglist[pkgnames.index(package.name)]['paths']  # Get paths
        try:
            os.unlink(path + '/' + package.path)
        except Exception:
            writeln('%s not linked at %s.' % (package.name, package.path))
            return False
        if len(paths) > 1:  # Installed in multiple locations
            writeln('Unlinked from %s.' % package.path)
            if not batch:
                package_list_remove_many(pkgpath, [package])
            return True
        else:
            sm = pkgrepo.submodule(package.name)
            sm.remove(force=True)  # Remove even if there are local changes
            pkgrepo.index.add(['.gitmodules'])
            pkgrepo.index.remove([package.name], r=True)  # Remove recursively
            pkgrepo.index.commit('Uninstalled ' + package.name)
        if not batch:
            package_list_remove_many(pkgpath, [package])
    except Exception as e:
        writeln('Failed to uninstall %s: %s' % (package.name, e))
        return False
    else:
        writeln('Uninstalled.')
        return True
예제 #11
0
def serial_ports():
    """Returns the serial port by scanning all of them"""

    ports = list(serial.tools.list_ports.comports())

    if not ports:
        output.writeln('No device is connected at the moment', Fore.RED)
        quit(2)

    for p in ports:
        test_str = str(p.description).lower()
        if 'arduino' in test_str or 'Arduino' in test_str:
            return p.device

    # if no arduino port is found choose the first port
    output.writeln(
        'No Arduino port found, choosing the first available one. Specify the port if you want another port',
        Fore.YELLOW)

    return ports[0].device
예제 #12
0
def clean_wcosa(path):
    """cleans the bin folder, deleting all the build files"""

    path = str(path)

    # confirm if bin folder/path exists
    if os.path.exists(helper.linux_path(path + '/wcosa/bin')):
        os.chdir(helper.linux_path(path + '/wcosa/bin'))
    else:
        output.writeln('\nNot a valid WCosa project', Fore.RED)
        quit(2)

    # check if the current build files are for the current board
    # clean and build if boards are different
    try:
        output.write('Cleaning build files - ', Fore.GREEN)

        for folder in helper.get_dirs(helper.get_working_directory()):
            shutil.rmtree(folder)

        for file in helper.get_files(helper.get_working_directory()):
            os.unlink(file)
    except IOError:
        output.writeln('Error while cleaning build files', Fore.RED)

    output.writeln('done')
예제 #13
0
파일: wcosa.py 프로젝트: waterloop/wcosa
def main():
    options = parse()

    path = Path(options.path)
    # based on the action call scripts
    if options.action == 'version':
        output.writeln(__version__)
    if options.action == 'boards':
        print_boards()
    elif options.action == 'create':
        handle.create_wcosa(path, Board(options.board), IDE(options.ide))
    elif options.action == 'update':
        handle.update_wcosa(path, Board(options.board), IDE(options.ide))
    elif options.action == 'build':
        use.build_wcosa(path, Generator(options.generator), options.make,
                        options.cmake)
    elif options.action == 'make':
        use.build_wcosa(path, make=options.make, needs_cmake=False)
    elif options.action == 'upload':
        use.upload_wcosa(path, Port(options.port))
    elif options.action == 'clean':
        use.clean_wcosa(path)
    elif options.action == 'monitor':
        monitor.serial_monitor(options.port, options.baud)
    elif options.action == 'package':
        if options.package_command == 'install':
            if not options.package:
                package_manager.package_install_pkglist(options.path)
            else:
                package_manager.package_install_many(
                    options.path, ' '.join(options.package).split(', '))
        elif options.package_command == 'update':
            package_manager.package_update_all(options.path)
        elif options.package_command == 'remove':
            package_manager.package_uninstall_many(
                options.path, ' '.join(options.package).split(', '))
예제 #14
0
def _package_install_unsafe(path, package, pkgrepo, pkglist, pkgnames):
    """
    NOT A PUBLIC INTERFACE: use package_install[_many] instead.

    Try to install a package and forward exceptions to the caller.
    Will leave package repository in dirty state.
    Returns
    """
    write('Installing %s... ' % package.name)
    sys.stdout.flush()
    repo_path = package_repo_path(path, package)
    if package.name in pkgnames and os.path.exists(repo_path):
        index = pkgnames.index(package.name)
        link_path = package_link_path(path, package)
        if package.path in pkglist[index]['paths'] and os.path.lexists(
                link_path):
            writeln('Already installed.')
            raise AlreadyInstalledException(link_updated=False)
        else:
            write('Already installed, linking to %s... ' % package.path)
            sys.stdout.flush()
            package_link(path, package)
            writeln('Linked.')
            raise AlreadyInstalledException(link_updated=True)
    # If the above did not return, we need to actually install the package
    try:
        if package.branch:
            pkgrepo.create_submodule(package.name,
                                     package.name,
                                     url=package.url,
                                     branch=package.branch)
        else:
            pkgrepo.create_submodule(package.name,
                                     package.name,
                                     url=package.url)
    except Exception:  # Default message is cryptic
        raise GitFetchException(package)
    package_link(path, package)
    writeln('Installed.')
예제 #15
0
def build_wcosa(path, generator=None, make=None, cmake=None, needs_cmake=True):
    """build wcosa project, cmake and make"""

    path = str(path)

    output.writeln('Wcosa project build started', Fore.GREEN)
    output.write('Verifying the project structure - ', Fore.GREEN)

    # check if path is valid
    if not os.path.exists(path):
        output.write('Project path is invalid: ' + path, Fore.RED)
        quit(2)

    # confirm if bin folder/path exists
    if os.path.exists(helper.linux_path(path + '/wcosa/bin')):
        os.chdir(helper.linux_path(path + '/wcosa/bin'))
    else:
        output.writeln('\nNot a valid WCosa project', Fore.RED)
        quit(2)

    output.writeln('done')

    cmake_program = cmake or get_cmake_program()
    make_program = make or get_make_program()

    output.write('Verifying cmake and make installs - ', Fore.GREEN)

    # check if cmake is in environment paths (unix/linux based systems)
    if not cmake_program:
        output.writeln(
            '\ncmake does not exist, please install it or make sure it is in your environment PATH',
            Fore.RED)
        quit(2)

    # check if make is in environment paths (unix/linux based systems)
    if not make_program:
        output.writeln(
            '\nmake does not exist, please install it or make sure it is in your environment PATH',
            Fore.RED)
        quit(2)

    output.writeln('done')

    if not generator or not str(generator):
        generator = Generator(get_generator_for(make_program))

    # check if path is valid and get build information from the user config
    if not os.path.exists(path + '/config.json'):
        output.write(
            'Project user configuration file does not exist, recreate or update the project',
            Fore.RED)
        quit(2)
    else:
        with open(path + '/config.json') as f:
            data = json.load(f, object_pairs_hook=OrderedDict)
            board = data['board']

    # check if the current build files are for the current board
    # clean and build if boards are different
    if os.path.exists(helper.get_working_directory() + '/Makefile'):
        with open(helper.get_working_directory() + '/Makefile') as f:
            makefile_str = ''.join(f.readlines())

        if '\n' + board not in makefile_str:
            output.writeln(
                'Since a new board is detected, full build will be triggered',
                Fore.GREEN)
            clean_wcosa(path)

    if needs_cmake:
        output.writeln('Running the build using cmake and ' + str(generator),
                       Fore.GREEN)
        cmake_code = subprocess.call(['cmake', '-G', str(generator), '..'])
        if cmake_code != 0:
            output.writeln(
                'Project build unsuccessful, cmake exited with error code ' +
                str(cmake_code), Fore.RED)
            quit(2)

    make_code = subprocess.call([make_program])
    # make returns 2 if the project has not been configured
    if make_code == 2 or make_code == '2':
        output.writeln('No Makefiles present, run wcosa build', Fore.RED)
        quit(2)
    if make_code != 0:
        output.writeln(
            'Project build unsuccessful, make exited with error code ' +
            str(make_code), Fore.RED)
        quit(2)

    output.writeln('Project successfully built', Fore.GREEN)
예제 #16
0
def upload_wcosa(path, port):
    """upload wcosa project to the port specified or an automatically selected one"""

    path = str(path)

    output.writeln('Wcosa project upload started', Fore.GREEN)
    output.write('Verifying build files - ', Fore.GREEN)

    # confirm if bin folder/path exists
    if os.path.exists(helper.linux_path(path + '/wcosa/bin')):
        os.chdir(helper.linux_path(path + '/wcosa/bin'))
    else:
        output.writeln('\nNot a valid WCosa project', Fore.RED)

    # if project has not been built right
    if not os.path.exists(helper.get_working_directory() + '/Makefile'):
        output.writeln('\nNo Makefile, build the project first ', Fore.RED)
        quit(2)

    output.writeln('done')

    # check if path is valid and get the user config
    if not os.path.exists(path + '/config.json'):
        output.write(
            'Project user configuration file does not exist, recreate or update the project',
            Fore.RED)
        quit(2)
        user_port = None
        data = None
    else:
        with open(path + '/config.json') as f:
            data = json.load(f, object_pairs_hook=OrderedDict)
            user_port = data['port'].strip(' ')

    if not port.use_same():
        output.write('Using the port provided - ' + str(port), Fore.GREEN)
    else:
        # if port is defined in the config file, then use that port
        if user_port.lower() != 'None'.lower() and user_port != '':
            port = user_port

            output.writeln('Using the port from the config file: ' + user_port,
                           Fore.GREEN)
            # check if the port is valid
            if port not in get_serial_devices():
                output.writeln(
                    '\nPort provided does not have a valid device connected to it',
                    Fore.RED)
                quit(2)
        else:
            output.writeln('Automatically selecting a port', Fore.GREEN)
            port = serial_ports()
            output.writeln('Port chosen: ' + port, Fore.GREEN)

    # save the port in the config file so that update can update the project based on that
    temp_data = copy.copy(data)
    temp_data['port'] = str(port)
    with open(path + '/config.json', 'w') as f:
        json.dump(temp_data,
                  f,
                  indent=settings.get_settings_value('json-indent'))

    # do not print the updating logs
    output.output_status(False)

    # reset the port in the user config to the port that was there
    with open(path + '/config.json', 'w') as f:
        json.dump(data, f, indent=settings.get_settings_value('json-indent'))

    output.writeln('Upload triggered on ' + str(port), Fore.GREEN)

    upload_code = subprocess.call([get_make_program(), 'upload'])

    if upload_code != 0:
        output.writeln(
            'Project upload unsuccessful, make exited with error code ' +
            str(upload_code), Fore.RED)
        quit(2)

    output.writeln('Project upload successful', Fore.GREEN)
예제 #17
0
def create_wcosa(path, board, ide):
    """Creates WCosa project from scratch"""

    path = str(path)

    write('Creating work environment - ', color=Fore.CYAN)
    verify_path(path)

    templates_path = helper.linux_path(helper.get_wcosa_path() + '/templates')
    user_config_path = helper.linux_path(path + '/config.json')
    internal_config_path = helper.linux_path(path +
                                             '/wcosa/internal-config.json')
    general_cmake_path = helper.linux_path(path + '/wcosa/CMakeLists.txt')
    src_path = helper.linux_path(path + '/src/main.cpp')

    # check if there are already src and lib folders. We do not want to delete those folders
    if len(helper.get_dirs(path)) > 0 and (os.path.exists(path + '/src')
                                           or os.path.exists(path + '/lib')):
        writeln(
            '\nThere is already a src and/or lib folder in this directory. Use wcosa update instead',
            color=Fore.RED)
        quit(2)

    # create src, lib, and wcosa folders
    create_folders(path, True)

    # copy all then CMakeLists templates and configuration templates
    copyfile(templates_path + '/cmake/CMakeLists.txt.tpl', general_cmake_path)
    copyfile(templates_path + '/config/internal-config.json.tpl',
             internal_config_path)
    copyfile(templates_path + '/config/config.json.tpl', user_config_path)
    copyfile(templates_path + '/examples/main.cpp', src_path)

    writeln('done')
    write('Updating configurations based on the system - ', color=Fore.CYAN)

    user_data = config.fill_user_config(user_config_path, board, Port(None),
                                        ide)
    project_data = config.fill_internal_config(internal_config_path, path,
                                               user_data)

    cmake.parse_update(general_cmake_path, project_data)

    if user_data['ide'] == 'clion':
        copyfile(templates_path + '/ide/clion/CMakeLists.txt.tpl',
                 path + '/CMakeLists.txt')
        copyfile(templates_path + '/ide/clion/CMakeListsPrivate.txt.tpl',
                 path + '/CMakeListsPrivate.txt')
        copyfile(templates_path + '/gitignore-files/.gitignore-clion',
                 path + '/.gitignore')

        cmake.parse_update(path + '/CMakeLists.txt', project_data)
        cmake.parse_update(path + '/CMakeListsPrivate.txt', project_data)
    else:
        copyfile(templates_path + '/gitignore-files/.gitignore-general',
                 path + '/.gitignore')

    writeln('done')
    writeln('Project Created and structure:', color=Fore.YELLOW)
    writeln('src    ->    All source files go here:', color=Fore.YELLOW)
    writeln('lib    ->    All custom libraries go here', color=Fore.YELLOW)
    writeln('wcosa  ->    All the build files are here (do no modify)',
            color=Fore.YELLOW)