Beispiel #1
0
    def do(cls, _, args):
        '''Executes the remove command.'''
        ws_dir = get_ws_dir(args.root, args.remove_ws)
        if not os.path.exists(ws_dir):
            raise WSError('workspace %s does not exist' % args.remove_ws)

        if args.default is not None:
            default_ws_dir = get_ws_dir(args.root, args.default)
            if not os.path.exists(default_ws_dir):
                raise WSError('workspace %s does not exist' % args.default)

        default_link = get_default_ws_link(args.root)
        is_default = (os.readlink(default_link) == args.remove_ws)
        if is_default:
            # If the deleted workspace is the default, force the user to choose
            # a new one.
            if args.default is None:
                raise WSError('trying to remove the default workspace; must '
                              'specify a new default via -d/--default')
        elif args.default:
            raise WSError('-d/--default is not applicable unless you are '
                          'removing the default workspace')

        # We are good to go.
        rmtree(ws_dir)
        if is_default:
            remove(default_link)
            symlink(args.default, default_link)
Beispiel #2
0
    def do(cls, ws, args):
        '''Executes the rename command.'''
        if args.old_ws == 'default':
            raise WSError('cannot rename the default workspace; please use ws '
                          'default if you want to change it')

        old_ws_dir = get_ws_dir(args.root, args.old_ws)
        if not os.path.exists(old_ws_dir):
            raise WSError('workspace %s does not exist' % args.old_ws)

        d = parse_manifest(args.root)
        for proj in d:
            build_dir = get_build_dir(old_ws_dir, proj)
            if os.path.exists(build_dir):
                raise WSError('cannot rename a workspace that contains build '
                              'artifacts, as some builds contain absolute '
                              'paths and are thus not relocatable. Please '
                              'force-clean this workspace first and then '
                              'rename it.')

        new_ws_dir = get_ws_dir(args.root, args.new_ws)
        if os.path.exists(new_ws_dir):
            raise WSError('workspace %s already exists; please delete it '
                          'first if you want to do this rename' % args.new_ws)

        rename(old_ws_dir, new_ws_dir)
        default_link = get_default_ws_link(args.root)
        if os.readlink(default_link) == args.old_ws:
            remove(default_link)
            symlink(args.new_ws, default_link)
Beispiel #3
0
    def do(cls, ws, args):
        '''Executes the build subcmd.'''
        ws_config = get_ws_config(get_ws_dir(args.root, ws))
        d = parse_manifest(args.root)

        # Validate.
        for project in args.projects:
            if project not in d:
                raise WSError('unknown project %s' % project)

        if len(args.projects) == 0:
            projects = d.keys()
        else:
            projects = args.projects

        # Build in reverse-dependency order.
        order = dependency_closure(d, projects)

        # Get all checksums; since this is a nop build bottle-neck, do it in
        # parallel. On my machine, this produces a ~20% speedup on a nop
        # "build-all".
        pool = multiprocessing.Pool(multiprocessing.cpu_count())
        src_dirs = [get_source_dir(args.root, d, proj) for proj in order]
        checksums = pool.map(calculate_checksum, src_dirs)

        for i, proj in enumerate(order):
            log('building %s' % proj)
            checksum = checksums[i]
            success = _build(args.root, ws, proj, d, checksum, ws_config,
                             args.force)
            if not success:
                raise WSError('%s build failed' % proj)
Beispiel #4
0
    def do(cls, _, args):
        '''Executes the default command.'''
        link = get_default_ws_link(args.root)
        if args.default_ws is None:
            # Just report what the default currently is.
            dest = os.path.basename(os.path.realpath(link))
            print(dest)
            return

        ws_dir = get_ws_dir(args.root, args.default_ws)

        remove(link)
        if not os.path.exists(ws_dir):
            raise WSError('Cannot make non-existent workspace %s the default' %
                          args.default_ws)

        symlink(args.default_ws, link)
Beispiel #5
0
    def do(cls, _, args):
        '''Executes the init command.'''
        if args.root is None:
            root = '.ws'
        else:
            root = args.root

        if args.init_ws is None:
            ws = 'ws'
        else:
            reserved = (get_default_ws_name(), get_manifest_link_name())
            for name in reserved:
                if args.init_ws == name:
                    raise WSError('%s is a reserved name; please choose a '
                                  'different name' % name)
            ws = args.init_ws
            if '.' in ws or '/' in ws:
                raise WSError('Workspace name "%s" contains an illegal '
                              'character (. or /). Please use a different '
                              'name.' % ws)
        ws_dir = get_ws_dir(root, ws)

        if os.path.exists(ws_dir):
            raise WSError('Cannot initialize already existing workspace %s' %
                          ws)

        if args.manifest_source == 'repo':
            parent = os.path.join(root, os.pardir)
            repo_manifest = os.path.realpath(
                os.path.join(parent, '.repo', 'manifest.xml'))
            base = os.path.dirname(repo_manifest)
        elif args.manifest_source == 'fs':
            base = '.'
        else:
            raise NotImplementedError('Manifest source %s should be '
                                      'implemented' % args.manifest_source)
        manifest = os.path.join(base, args.manifest)
        if os.path.isdir(manifest):
            # If -m points to a directory instead of a file, assume there is a
            # file with the default manifest name inside.
            manifest = os.path.join(manifest, get_default_manifest_name())

        # Use a relative path for anything inside the parent of .ws and an
        # absolute path for anything outside. This is to maximize
        # relocatability for groups of git repos (e.g. using submodules,
        # repo-tool, etc.).
        manifest = os.path.abspath(manifest)
        parent = os.path.realpath(os.path.join(root, os.pardir))
        if _is_subdir(manifest, parent):
            manifest = os.path.relpath(manifest, root)
        else:
            manifest = os.path.abspath(manifest)

        # Make sure the given manifest is sane.
        if os.path.isabs(manifest):
            abs_manifest = manifest
        else:
            abs_manifest = os.path.abspath(os.path.join(root, manifest))
        d = parse_manifest_file(root, abs_manifest)

        try:
            mkdir(root)
            new_root = True
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise
            new_root = False

        try:
            mkdir(ws_dir)
            new_ws = True
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise
            new_ws = False

        if new_ws:
            # This is a brand-new workspace, so populate the initial workspace
            # directories.
            mkdir(get_toplevel_build_dir(ws_dir))
            mkdir(get_checksum_dir(ws_dir))

            proj_map = dict((proj, {}) for proj in d)
            for proj in proj_map:
                proj_map[proj] = get_new_config(proj)

            config = {'type': args.type, 'projects': proj_map}

            write_config(ws_dir, config)

        if new_root:
            # This is a brand new root .ws directory, so populate the initial
            # symlink defaults.
            symlink(ws, get_default_ws_link(root))
            symlink(manifest, get_manifest_link(root))