Example #1
0
File: cli.py Project: Leopardob/be
def in_(ctx, topics, yes, as_, enter):
    """Set the current topics to `topics`

    Environment:
        BE_PROJECT: First topic
        BE_CWD: Current `be` working directory
        BE_TOPICS: Arguments to `in`
        BE_DEVELOPMENTDIR: Absolute path to current development directory
        BE_PROJECTROOT: Absolute path to current project
        BE_PROJECTSROOT: Absolute path to where projects are located
        BE_ACTIVE: 0 or 1, indicates an active be environment
        BE_USER: Current user, overridden with `--as`
        BE_SCRIPT: User-supplied shell script
        BE_PYTHON: User-supplied python script
        BE_ENTER: 0 or 1 depending on whether the topic was entered
        BE_GITHUB_API_TOKEN: Optional GitHub API token
        BE_ENVIRONMENT: Space-separated list of user-added
            environment variables
        BE_TEMPDIR: Directory in which temporary files are stored
        BE_PRESETSDIR: Directory in which presets are searched
        BE_ALIASDIR: Directory in which aliases are written
        BE_BINDING: Binding between template and item in inventory

    \b
    Usage:
        $ be in project topics

    """

    topics = map(str, topics)  # They enter as unicode

    if self.isactive():
        lib.echo("ERROR: Exit current project first")
        sys.exit(lib.USER_ERROR)

    # Determine topic syntax
    if len(topics[0].split("/")) == 3:
        topic_syntax = lib.FIXED
        project = topics[0].split("/")[0]
    else:
        topic_syntax = lib.POSITIONAL
        project = topics[0]

    project_dir = _format.project_dir(_extern.cwd(), project)
    if not os.path.exists(project_dir):
        lib.echo("Project \"%s\" not found. " % project)
        lib.echo("\nAvailable:")
        ctx.invoke(ls)
        sys.exit(lib.USER_ERROR)

    # Boot up
    context = lib.context(project)

    be = _extern.load_be(project)
    templates = _extern.load_templates(project)
    inventory = _extern.load_inventory(project)
    context.update({
        "BE_PROJECT": project,
        "BE_USER": str(as_),
        "BE_ENTER": "1" if enter else "",
        "BE_TOPICS": " ".join(topics)
    })

    # Remap topic syntax, for backwards compatibility
    # In cases where the topic is entered in a way that
    # differs from the template, remap topic to template.
    if any(re.findall("{\d+}", pattern) for pattern in templates.values()):
        template_syntax = lib.POSITIONAL
    else:
        template_syntax = lib.FIXED

    if topic_syntax & lib.POSITIONAL and not template_syntax & lib.POSITIONAL:
        topics = ["/".join(topics)]
    if topic_syntax & lib.FIXED and not template_syntax & lib.FIXED:
        topics[:] = topics[0].split("/")

    try:
        key = be.get("templates", {}).get("key") or "{1}"
        item = _format.item_from_topics(key, topics)
        binding = _format.binding_from_item(inventory, item)
        context["BE_BINDING"] = binding
    except IndexError as exc:
        lib.echo("At least %s topics are required" % str(exc))
        sys.exit(lib.USER_ERROR)

    except KeyError as exc:
        lib.echo("\"%s\" not found" % item)
        if exc.bindings:
            lib.echo("\nAvailable:")
            for item_ in sorted(exc.bindings,
                                key=lambda a: (exc.bindings[a], a)):
                lib.echo("- %s (%s)" % (item_, exc.bindings[item_]))
        sys.exit(lib.USER_ERROR)

    # Finally, determine a development directory
    # based on the template-, not topic-syntax.
    if template_syntax & lib.POSITIONAL:
        try:
            development_dir = _format.pos_development_directory(
                templates=templates,
                inventory=inventory,
                context=context,
                topics=topics,
                user=as_,
                item=item)
        except KeyError as exc:
            lib.echo("\"%s\" not found" % item)
            if exc.bindings:
                lib.echo("\nAvailable:")
                for item_ in sorted(exc.bindings,
                                    key=lambda a: (exc.bindings[a], a)):
                    lib.echo("- %s (%s)" % (item_, exc.bindings[item_]))
            sys.exit(lib.USER_ERROR)

    else:  # FIXED topic_syntax
        development_dir = _format.fixed_development_directory(
            templates,
            inventory,
            topics,
            as_)

    context["BE_DEVELOPMENTDIR"] = development_dir

    tempdir = (tempfile.mkdtemp()
               if not os.environ.get("BE_TEMPDIR")
               else os.environ["BE_TEMPDIR"])
    context["BE_TEMPDIR"] = tempdir

    # Should it be entered?
    if enter and not os.path.exists(development_dir):
        create = False
        if yes:
            create = True
        else:
            sys.stdout.write("No development directory found. Create? [Y/n]: ")
            if raw_input().lower() in ("", "y", "yes"):
                create = True
        if create:
            ctx.invoke(mkdir, dir=development_dir)
        else:
            sys.stdout.write("Cancelled")
            sys.exit(lib.NORMAL)

    # Parse be.yaml
    if "script" in be:
        context["BE_SCRIPT"] = _extern.write_script(
            be["script"], tempdir)

    if "python" in be:
        script = "\n".join(be["python"])
        context["BE_PYTHON"] = script
        try:
            exec script in {"__name__": __name__}
        except Exception as e:
            lib.echo("ERROR: %s" % e)

    invalids = [v for v in context.values() if not isinstance(v, str)]
    assert all(isinstance(v, str) for v in context.values()), invalids

    # Create aliases
    aliases_dir = _extern.write_aliases(
        be.get("alias", {}), tempdir)

    context["PATH"] = (aliases_dir
                       + os.pathsep
                       + context.get("PATH", ""))
    context["BE_ALIASDIR"] = aliases_dir

    # Parse redirects
    _format.parse_redirect(
        be.get("redirect", {}), topics, context)

    # Override inherited context
    # with that coming from be.yaml.
    if "environment" in be:
        parsed = _format.parse_environment(
            fields=be["environment"],
            context=context,
            topics=topics)
        context["BE_ENVIRONMENT"] = " ".join(parsed.keys())
        context.update(parsed)

    if "BE_TESTING" in context:
        os.chdir(development_dir)
        os.environ.update(context)
    else:
        parent = lib.parent()
        cmd = lib.cmd(parent)

        # Store reference to calling shell
        context["BE_SHELL"] = parent

        try:
            sys.exit(subprocess.call(cmd, env=context))
        finally:
            import shutil
            shutil.rmtree(tempdir)
Example #2
0
File: cli.py Project: Leopardob/be
def new(preset, name, silent, update):
    """Create new default preset

    \b
    Usage:
        $ be new ad
        "blue_unicorn" created
        $ be new film --name spiderman
        "spiderman" created

    """

    if self.isactive():
        lib.echo("Please exit current preset before starting a new")
        sys.exit(lib.USER_ERROR)

    if not name:
        count = 0
        name = lib.random_name()
        while name in _extern.projects():
            if count > 10:
                lib.echo("ERROR: Couldn't come up with a unique name :(")
                sys.exit(lib.USER_ERROR)
            name = lib.random_name()
            count += 1

    project_dir = _format.project_dir(_extern.cwd(), name)
    if os.path.exists(project_dir):
        lib.echo("\"%s\" already exists" % name)
        sys.exit(lib.USER_ERROR)

    username, preset = ([None] + preset.split("/", 1))[-2:]
    presets_dir = _extern.presets_dir()
    preset_dir = os.path.join(presets_dir, preset)

    # Is the preset given referring to a repository directly?
    relative = False if username else True

    try:
        if not update and preset in _extern.local_presets():
            _extern.copy_preset(preset_dir, project_dir)

        else:
            lib.echo("Finding preset for \"%s\".. " % preset, silent)
            time.sleep(1 if silent else 0)

            if relative:
                # Preset is relative, look it up from the Hub
                presets = _extern.github_presets()

                if preset not in presets:
                    sys.stdout.write("\"%s\" not found" % preset)
                    sys.exit(lib.USER_ERROR)

                time.sleep(1 if silent else 0)
                repository = presets[preset]

            else:
                # Absolute paths are pulled directly
                repository = username + "/" + preset

            lib.echo("Pulling %s.. " % repository, silent)
            repository = _extern.fetch_release(repository)

            # Remove existing preset
            if preset in _extern.local_presets():
                _extern.remove_preset(preset)

            try:
                _extern.pull_preset(repository, preset_dir)
            except IOError as e:
                lib.echo("ERROR: Sorry, something went wrong.\n"
                         "Use be --verbose for more")
                lib.echo(e)
                sys.exit(lib.USER_ERROR)

            try:
                _extern.copy_preset(preset_dir, project_dir)
            finally:
                # Absolute paths are not stored locally
                if not relative:
                    _extern.remove_preset(preset)

    except IOError as exc:
        if self.verbose:
            lib.echo("ERROR: %s" % exc)
        else:
            lib.echo("ERROR: Could not write, do you have permission?")
        sys.exit(lib.PROGRAM_ERROR)

    lib.echo("\"%s\" created" % name, silent)