Skip to content

Commit

Permalink
Merge pull request #23 from AnilRedshift/docs
Browse files Browse the repository at this point in the history
Docs
  • Loading branch information
Anil Kulkarni committed Jul 1, 2018
2 parents 6a239f1 + 931faad commit 12b6633
Show file tree
Hide file tree
Showing 39 changed files with 592 additions and 285 deletions.
95 changes: 81 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,88 @@
# Wand
[![Coverage Status](https://coveralls.io/repos/github/AnilRedshift/wand/badge.svg?branch=master)](https://coveralls.io/github/AnilRedshift/wand?branch=master)[![CircleCI branch](https://img.shields.io/circleci/project/github/AnilRedshift/wand/master.svg)](circle)
# Wand [![Hex version badge](https://img.shields.io/hexpm/v/wand.svg)](https://hex.pm/packages/wand)

**wand** is a dependency manager that uses a _wand.json_ file to replace your deps() in mix.exs. This allows you to add, remove, and upgrade packages easily using the wand cli.

## Quickstart
**To install**: `mix archive.install hex wand --force && mix archive.install hex wand_core --force`

**To use wand in a project**: `wand init`

**Add a dependency**: `wand add poison`

**Remove a dependency**: `wand remove poison`

**TODO: Add description**
**Upgrade a dependency**: `wand upgrade poison --latest`

**help**: `wand --help`

# Installing wand

## Prerequisites
Wand requires [elixir](https://elixir-lang.org/install.html) before installing. You also need to have hex installed by running `mix local.hex`

## Installation
`mix archive.install hex wand --force && mix archive.install hex wand_core --force`

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `wand` to your list of dependencies in `mix.exs`:
After installation, you need to add the escript directory to your `PATH`. This is usually `~/.mix/escripts`

```elixir
def deps do
[
{:wand, "~> 0.1.0"}
]
end
You can verify this by typing in `mix escript` to see what path to add.

## Verify Installation
You can verify that wand was properly installed by typing `wand --version` to make sure wand is installed, and `wand core --version` to make sure that [wand_core](http://github.com/anilredshift/wand-core) is installed

### Usage
Get started by navigating to an existing elixir project and type `wand init`. This will generate a _wand.json_ file. You should check this file into your source control. From now on, your dependencies are controlled by _wand.json_ in conjunction with your _mix.lock_ file. Let's take a quick look at an example wand.json file:
```
{
"version": "1.0.0",
"dependencies": {
"ex_doc": [">= 0.0.0",{"only":":dev"}],
"excoveralls": ["~> 0.9.1",{"only":":test"}],
"junit_formatter": ["~> 2.2",{"only":":test"}],
"mox": ["~> 0.3.2",{"only":":test"}]
}
}
```
The dependencies key should look very similar to your deps() inside of mix.exs. The pattern of each entry is either `name: requirement` or `name: [requirement, {opts}]`. The options should look familiar, they exactly match the existing [allowed options](https://hexdocs.pm/mix/Mix.Tasks.Deps.html). It's possible to edit this by hand, but it's better to use the wand cli:

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/wand](https://hexdocs.pm/wand).
## CLI commands
```
add Add dependencies to your project
core Manage the related wand_core package
help Get detailed help
init Initialize wand for a project
outdated List packages that are out of date
remove Remove dependencies from your project
upgrade Upgrade a dependency in your project
version Get the version of wand installed on the system
Options
--verbose Detailed help for every command
--? Same as --verbose
```

Detailed help is available by typing wand help [command] or by clicking on the links below:

* `Wand.CLI.Commands.Add`
* `Wand.CLI.Commands.Core`
* `Wand.CLI.Commands.Help`
* `Wand.CLI.Commands.Init`
* `Wand.CLI.Commands.Outdated`
* `Wand.CLI.Commands.Remove`
* `Wand.CLI.Commands.Upgrade`
* `Wand.CLI.Commands.Version`

## CircleCI and other CI.
You need to have the wand_core archive added to your image before running mix deps.get. The command for CircleCI would be:
`- run: mix archive.install hex wand_core --force`

## Local development
1. `git clone git@github.com:AnilRedshift/wand.git`
2. `cd wand`
3. `mix deps.get`
4. `mix test`


# Build status
[![Coverage Status](https://coveralls.io/repos/github/AnilRedshift/wand/badge.svg?branch=master)](https://coveralls.io/github/AnilRedshift/wand?branch=master)[![CircleCI branch](https://img.shields.io/circleci/project/github/AnilRedshift/wand/master.svg)](circle)
5 changes: 5 additions & 0 deletions lib/cli.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
defmodule Wand.CLI do
@system Wand.Interfaces.System.impl()
@moduledoc """
The main entrypoint for the wand escript
See `Wand` for more information
"""
@spec main([String.t()]) :: :ok | no_return()
def main(args) do
Wand.CLI.ArgParser.parse(args)
|> route
Expand Down
15 changes: 2 additions & 13 deletions lib/cli/arg_parser.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
defmodule Wand.CLI.ArgParser do
@moduledoc false
alias Wand.CLI.Command

def parse(args) do
Expand All @@ -16,19 +17,7 @@ defmodule Wand.CLI.ArgParser do

defp parse_main(args, []), do: validate(:help, ["help"] ++ args)

@commands [
"add",
"a",
"core",
"help",
"init",
"outdated",
"remove",
"r",
"upgrade",
"u",
"version"
]
@commands Wand.CLI.Command.routes() ++ ["a", "r", "u"]
defp parse_main(args, [command | _rest]) when command in @commands do
%{
"a" => "add",
Expand Down
23 changes: 23 additions & 0 deletions lib/cli/command.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
defmodule Wand.CLI.Command do
@moduledoc """
The interface for each type of command that wand supports.
To add a new command, the following things must take place:
1. Add the name of the module to routes below
2. Create a module inside the lib/cli/commands folder that implements `Wand.CLI.Command`
3. Update `Wand.CLI.ArgParser` if you need to add a shorthand version
4. Update the help file in `Wand` with the appropriate text
"""

@callback execute(data :: any()) :: :ok | {:error, integer()}
@callback help(type :: any()) :: any()
@callback validate(args :: list) :: {:ok, any()} | {:error, any()}

def routes() do
[
"add",
"core",
"help",
"init",
"outdated",
"remove",
"upgrade",
"version"
]
end

def route(key, name, args) do
get_module(key)
|> Kernel.apply(name, args)
Expand Down
124 changes: 93 additions & 31 deletions lib/cli/commands/add.ex
Original file line number Diff line number Diff line change
@@ -1,64 +1,122 @@
defmodule Wand.CLI.Commands.Add do
@behaviour Wand.CLI.Command

@moduledoc """
# Add
Add elixir packages to wand.json
## Usage
### Usage
**wand** add [package] [package] ... [flags]
## Examples
<pre>
**wand** add ex_doc mox --test
**wand** add poison --git=https://github.com/devinus/poison.git
**wand** add poison@3.1 --exact
</pre>
Wand can be used to add packages from three different places: hex, git, or the local filesystem. [package] can either be the name, or name@version.
If a version is provided, the `--around` and `--exact` flags determine how the version is used.
### Hex.pm
Examples:
```
wand add poison
wand add poison@3.1
```
### Git
Include the `--git` flag to pass a URI. The URI can be one of two base formats, and can end with an optional hash of the branch, tag, or ref to use
Examples:
```
wand add poison --git="https://github.com/devinus/poison.git"
wand add poison --git="git@github.com:devinus/poison"
wand add poison@3.1 --git="https://github.com/devinus/poison.git#test"
wand add poison --git="https://github.com/devinus/poison.git#3.1.0"
```
### Local Path
Local packages are described by passing in the `--path` flag corresponding to the path location
OR, for an umbrella application, when you need to include a sibling dependency, pass the app name, along with the `--in-umbrella` flag.
Examples:
```
wand add poison --path="/absolute/path/to/poison"
wand add poison --path="../../relative/path/"
wand add sibling_dependency --in-umbrella
```
## Options
The available flags depend on if wand is being used to add a single package, or multiple packages. Flags that can only be used in single-package-mode are denoted with (s).
<pre>
--compile Run mix compile after adding (default: **true**)
--compile-env (s) The environment for the dependency (default: **prod**)
--dev Include the dependency in the dev environment
--download Run mix deps.get after adding (default: **true**)
--env Add the dependency to a specific environment
--exact Set the version to exactly match the version provided
--git (s) The Git URI to download the package from
--hex (s) The name of the package in hex to download
--optional Mark the dependency as optional
--organization Set the hex.pm organization to use
--path (s) The local directory to install the package from
--prod Include the dependency in the prod environment
--read-app-file (s) Read the app file of the dependency (default: **true**)
--repo The hex repo to use (default: **hexpm**)
--runtime Start the application automatically (default: **true**)
--sparse (s) Checkout a given directory inside git
--submodules (s) Initialize submodules for the repo
--test Include the dependency in the test environment
--tilde Stay within the minor version provided
--in-umbrella (s) Sets a path dependency pointing to ../app
</pre>
The following flags are provided. They are boolean flags unless specified.
### Hex flags
```
--hex=NAME means that the local name of the dependency is different from its name on hex
E.g. wand add mypoison --hex=poison
--organization=ORGANIZATION corresponds to the private org to pull the package(s) from.
--repo=REPO An alternative repository to use. Configure with mix hex.repo. Default: hexpm
```
### Git flags
```
--sparse=FOLDER git checkout only a single folder, and use that
--submodules tells git to also initialize submodules
```
### Environment flags
Setting these flags specifies which environments to install the dependency. If none are provided, all environments are included.
```
--env=ENVIRONMENT where ENVIRONMENT is the environment to add. This flag can be added multiple times. Example: --env=prod --env=test
--dev is shorthand for --env=dev
--test is shorthand for --env=test
--prod is shorthand for --env=prod
--compile-env=ENVIRONMENT doesnt affect which environments the dependency is loaded from. Instead, it says "when compiling the dependency, which environment to use?". Defaults to --compile-env=prod
--optional will include the project for THIS project, but not reuire it should the main project be a dependency of another project.
```
### Dependency configuration
These flags deal with what happens with the dependency once configured
```
--runtime determines whether to start the dependency. Defaults to true
--read-app-file determines if the app file for the dependency is read. Defaults to true.
--download determines if mix deps.get is run after adding the package to wand.json. Defaults to true. If set to false, this implies --compile=false as well.
--compile determines if mix.compile is run after adding the package to wand.json.
```
"""

defmodule Git do
@moduledoc false
defstruct git: nil,
ref: nil,
sparse: nil,
submodules: false
end

defmodule Hex do
@moduledoc false
defstruct hex: nil,
organization: nil,
repo: :hexpm
end

defmodule Path do
@moduledoc false
defstruct path: nil,
in_umbrella: false
end

defmodule Package do
@moduledoc false
@default_requirement Wand.Mode.get_requirement!(:caret, :latest)
defstruct compile: true,
compile_env: :prod,
Expand All @@ -73,10 +131,14 @@ defmodule Wand.CLI.Commands.Add do
runtime: true
end

@doc false
def moduledoc(), do: @moduledoc
@doc false
def help(type), do: Wand.CLI.Commands.Add.Help.help(type)

@doc false
def validate(args), do: Wand.CLI.Commands.Add.Validate.validate(args)

@doc false
def execute(packages), do: Wand.CLI.Commands.Add.Execute.execute(packages)
end
13 changes: 7 additions & 6 deletions lib/cli/commands/add/execute.ex
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
defmodule Wand.CLI.Commands.Add.Execute do
@moduledoc false
alias Wand.CLI.Commands.Add.Package
alias WandCore.WandFile
alias WandCore.WandFile.Dependency
alias Wand.CLI.WandFileWithHelp
alias Wand.CLI.Display
import Wand.CLI.Errors, only: [error: 1]
alias Wand.CLI.Error

def execute(packages) do
with :ok <- Wand.CLI.CoreValidator.require_core(),
Expand Down Expand Up @@ -139,7 +140,7 @@ defmodule Wand.CLI.Commands.Add.Execute do
"""
|> Display.error()

error(:package_not_found)
Error.get(:package_not_found)
end

defp handle_error(:dependency, {reason, _name})
Expand All @@ -153,7 +154,7 @@ defmodule Wand.CLI.Commands.Add.Execute do
"""
|> Display.error()

error(:hex_api_error)
Error.get(:hex_api_error)
end

defp handle_error(:add_dependency, {:already_exists, name}) do
Expand All @@ -166,7 +167,7 @@ defmodule Wand.CLI.Commands.Add.Execute do
"""
|> Display.error()

error(:package_already_exists)
Error.get(:package_already_exists)
end

defp handle_error(:download_failed, _reason) do
Expand All @@ -179,7 +180,7 @@ defmodule Wand.CLI.Commands.Add.Execute do
"""
|> Display.error()

error(:install_deps_error)
Error.get(:install_deps_error)
end

defp handle_error(:compile_failed, _reason) do
Expand All @@ -192,6 +193,6 @@ defmodule Wand.CLI.Commands.Add.Execute do
"""
|> Display.error()

error(:install_deps_error)
Error.get(:install_deps_error)
end
end

0 comments on commit 12b6633

Please sign in to comment.