def list_projects(): projects = list() for project in sorted(os.listdir(_extern.cwd())): abspath = os.path.join(_extern.cwd(), project) if not isproject(abspath): continue projects.append(project) return projects
def context(project=""): """Produce the be environment The environment is an exact replica of the active environment of the current process, with a few additional variables, all of which are listed below. The `be` environment are considered "defaults" that may be overwritten by the incoming environment, with the exception of BE_CWD which must always be the real current working directory. """ environment = os.environ.copy() environment.update({ "BE_PROJECT": project, "BE_PROJECTROOT": ( os.path.join(_extern.cwd(), project).replace("\\", "/") if project else ""), "BE_PROJECTSROOT": _extern.cwd(), "BE_ALIASDIR": "", "BE_CWD": _extern.cwd(), "BE_CD": "", "BE_ROOT": "", "BE_TOPICS": "", "BE_DEVELOPMENTDIR": "", "BE_ACTIVE": "1", "BE_USER": "", "BE_SCRIPT": "", "BE_PYTHON": "", "BE_ENTER": "", "BE_TEMPDIR": "", "BE_PRESETSDIR": "", "BE_GITHUB_API_TOKEN": "", "BE_ENVIRONMENT": "", "BE_BINDING": "", "BE_TABCOMPLETION": "" }) return environment
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)
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)