DevContext (dx)

This repo contains dx (dev_context), a script for managing developer context across repository directories and branches.

Note: this Ruby implementation now lives in implementations/ruby within the multi-language dev_context monorepo.

A context is one (repo_dir, branch) pair. Context names can be explicit, or implicit as <repo_basename>:<branch> (stored lowercase), and resolved with exact then FSF-style fuzzy matching.

Installation

gem install -n ~/bin dev_context

Install the gem in the current ruby gem path, with executables installed as:

  • ~/bin/dev_context (launcher, honors DX_IMPL)
  • ~/bin/dev_context-ruby (Ruby implementation entrypoint)

To clone from the github repo:

cd ~/src/github    # or wherever you keep github repos
git clone https://github.com/aks/dev_context.git
cd dev_context/implementations/ruby
bundle install
bundle exec rake install

Usage

Current model (authoritative)

  • A context is exactly one repo+branch pair (not a multi-repo aggregate).
  • dx cd and dx activate both activate the target context and change CWD via shell integration.
  • Activation attempts branch checkout + pull; on pull failure, CWD remains in the target repo for investigation and the command exits non-zero.
  • Defaults:
    • DX_AUTO_CREATE_LOCAL_BRANCH=true
    • DX_GIT_REMOTE_NAME=USE-REPO (or explicit like origin)

Shell integration

To support cd, dx should be wrapped by a shell function that evaluates shell output for stateful commands.

dx() {
  case "$1" in
    cd|activate|pushd|popd|pu|po)
      local out
      out="$(DX_SHELL_WRAPPED=1 command dev_context "$@")" || return $?
      case "$out" in
        "# DX_SHELL_EVAL"*) eval "$out" ;;
        *) printf "%s\n" "$out" ;;
      esac
      ;;
    *)
      command dev_context "$@"
      ;;
  esac
}

In the descriptions below, the following terms are used consistently:

  • NAME: the context NAME (which can match a PATH)

  • PATH: the file system path to a single repository directory.

  • URL: a standard http/https/git scheme URL that leads to a git-based repository.

  • CONTEXT: a context name, a PATH, or URL that identifies one context. Implicit naming uses <repo_basename>:<branch>.

Common Options

These options are currently supported on dx add, dx clone, and dx create:

  • -c, --context NAME: explicit context name
  • -n, --norun: preview actions without changing state
  • -v, --verbose: print extra command details

Examples:

dx add -c api:main ~/src/github/api
dx clone -n https://github.com/acme/tooling.git
dx create -v feature:abc-123 ~/src/github/dev_context feature/abc-123

Context stack commands

  • dx pushd [CONTEXT|PATH|URL|+N|-N]: activate/push context, or rotate indexed stack entry to top
  • dx popd [CONTEXT|+N|-N]: pop selected entry; with no args, same as dx popd +0

DX_PATH repo lookup

DX_PATH can be used as a list of parent directories that contain repositories.

  • Format: path-separated directories (same separator as shell PATH)
  • Example:
export DX_PATH="$HOME/src/github:$HOME/src/work"
dx add dev_context

Lookup behavior for relative repo targets:

  1. check current directory-relative path
  2. check each DX_PATH root and DX_CLONE_BASE_DIR as <root>/<target>
  3. if needed, run FSF subsequence search across repo directory names in those roots
  4. if one match is found, use it
  5. if multiple matches are found, fail and list candidates

Initialization and Adding Directories

dx [init | help]
dx init
dx help

The first thing to do is to initialize dx with one or more repo directories. They do not need to be added but, they can be discovered automatically with dx add PATH.

When initialized, a ~/.dxcf file will exist with the current dx settings.

When dx is invoked without any arguments (or options), and ~/.dxcf does not exist, then dx init is performed. dx init returns exit code 0 (success) when it actually succeeds in performing the initialization; it returns 1 (fail) otherwise.

When dx is invoked without any arguments or options, and ~/.dxcf already exists, dx defaults to dx status.

dx command ~/.dxcf? action
dx no dx init
dx yes dx status

Note: some command examples below were written before the current context model was finalized. The authoritative behavior is defined in the "Current model (authoritative)" section above and in DESIGN.md.

Command reference (v1)

dx init
dx add PATH|URL ...
dx clone URL [PATH]
dx create NAME [PATH] [BRANCH]
dx remove CONTEXT|PATH
dx active
dx activate CONTEXT|PATH|URL
dx cd CONTEXT|PATH|URL
dx deactivate CONTEXT
dx pushd [CONTEXT|PATH|URL|+N|-N]
dx popd [CONTEXT|+N|-N]
dx status|wip [--all] [--dirty] [-b BRANCHPATTERN] [-p PATHPATTERN]
dx repos [-b BRANCHPATTERN] [-p PATHPATTERN] [PATTERN]
dx stashes [--list] [PATTERN]
dx find [--stashes|--branches|--paths] <pattern>
dx find --all
dx branches|br [CONTEXT|PATTERN]
dx checkout|co [-b] FEATURE [CONTEXT]
dx diff [CONTEXT]

Notes:

  • dx add accepts one or more PATH/URL targets; there is no trailing aggregate context argument.
  • dx add URL behaves like clone+register for that repo.
  • dx stashes [PATTERN], dx repos [PATTERN], and dx branches [PATTERN] are focused find-style shortcuts.
  • dx <pattern> is shorthand for dx find <pattern> when the first token is not a command.
  • dx wip is dx status --dirty by default.
  • dx status/dx wip show stash count as s:<count> when non-zero.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/aks/dev_context. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

MIT License — see LICENSE.txt.

Code of Conduct

Please adhere to our code of conduct.