summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2015-02-27 03:43:33 +0000
committerFred Hebert <mononcqc@ferd.ca>2015-02-27 03:43:33 +0000
commitc8023cee0bb940da586e3195aafdfdad386b8670 (patch)
treeef8b1b8a55ca646090ffc89d227b3667acd1874c
parent1ac54972a9c14ac5dddbe463b0c93e5d799d36e0 (diff)
Documentation is maintained on www.rebar3.org
-rw-r--r--README.md2
-rw-r--r--doc/configuration.md7
-rw-r--r--doc/faq.md3
-rw-r--r--doc/guide.md121
-rw-r--r--doc/plugins.md272
-rw-r--r--doc/templates.md192
6 files changed, 2 insertions, 595 deletions
diff --git a/README.md b/README.md
index bd0763c..1314702 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,8 @@ locations (git, hg, etc).
3.0 Pre-Alpha
====
+[DOCUMENTATION](http://www.rebar3.org/v3.0/docs)
+
This is an experimental branch, considered to be pre-alpha, and still
very unstable. Use at your own risk, and expect no support. See
[the related announcement](http://lists.basho.com/pipermail/rebar_lists.basho.com/2014-November/002087.html).
diff --git a/doc/configuration.md b/doc/configuration.md
deleted file mode 100644
index 0f3d672..0000000
--- a/doc/configuration.md
+++ /dev/null
@@ -1,7 +0,0 @@
-## Configuration
-
-Sample config file:
-
-```erlang
-
-```
diff --git a/doc/faq.md b/doc/faq.md
deleted file mode 100644
index eaf6c5e..0000000
--- a/doc/faq.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## Why a Rebar3?
-
-Rebar was a great step forward for Erlang development but with time has proven to be fragile to change. Rebar3 builds on certain components of rebar which have benefited from years of community collaboration within a new core which is more extendable.
diff --git a/doc/guide.md b/doc/guide.md
deleted file mode 100644
index 32226e2..0000000
--- a/doc/guide.md
+++ /dev/null
@@ -1,121 +0,0 @@
-## Why Rebar3?
-
-Rebar was a great step forward for Erlang development but with time has proven to be fragile to change. Rebar3 builds on certain components of rebar which have benefited from years of community collaboration within a new core which is more extendable.
-
-## Creating a New Project
-
-```shell
-$ rebar3 new release myrelease
-===> Writing apps/myrelease/src/myrelease_app.erl
-===> Writing apps/myrelease/src/myrelease_sup.erl
-===> Writing apps/myrelease/src/myrelease.app.src
-===> Writing rebar.config
-===> Writing relx.config
-===> Writing config/sys.config
-===> Writing config/vm.args
-===> Writing .gitignore
-===> Writing LICENSE
-===> Writing README.md
-```
-
-## Working on an Existing Rebar3 Project
-
-First, checkout the project and change directories to the project root.
-
-```shell
-$ git clone git://github.com/tsloughter/minasan.git
-$ cd minansan
-```
-
-Now we can use rebar3 to fetch all dependencies and build both the dependencies and the project app or apps.
-
-```shell
-$ rebar3 compile
-===> Fetching gproc
-===> Fetching ranch
-===> Fetching cowboy
-===> Fetching cowlib
-===> Compiling gproc
-/home/tristan/Devel/minasan/_deps/gproc/src/gproc_dist.erl:23: Warning: behaviour gen_leader undefined
-===> Compiling cowlib
-===> Compiling ranch
-===> Compiling cowboy
-===> Compiling minasan
-```
-
-## Adding Dependencies
-
-Dependencies are listed in `rebar.config` file under the `deps` key:
-
-```erlang
-{deps, [
- {cowboy, ".*", {git, "git://github.com/ninenines/cowboy.git", {tag, "1.0.0"}}}
- ]}.
-```
-
-Now you can add the dep to one of your project's application's `.app.src` file under applications:
-
-```erlang
-{application, <APPNAME>,
- [{description, ""},
- {vsn, "<APPVSN>"},
- {registered, []},
- {modules, []},
- {applications, [
- kernel
- ,stdlib
- ,cowboy
- ]},
- {mod, {<APPNAME>_app, []}},
- {env, []}
- ]}.
-```
-
-## Rebar3 Conventions
-
-Rebar3 is entirely based on building OTP applications and releases.
-
-* Directories starting with underscores, e.g. `_deps`, are expected to not be checked in version control.
-* Project apps you are working on exist under `apps/` or `lib/`, or is a single app project with `src/` in the root directory.
-* `rebar.lock` and `rebar.config` go in the root of the project.
-* Tests go in `tests/`.
-
-## rebar.config vs rebar.lock
-
-`rebar.lock` contains the exact reference id to a commit that was used to build the project. Committing this file allows you to specify a branch in `rebar.config` for a dependency and still have reproducable builds because if the `rebar.lock` file exists when a rebar3 project is being built the contents of deps in rebar.config are ignored.
-
-## Checkout Dependencies
-
-Often while developing you find yourself working on mulitple applications from separate repos together. To simplify this process `rebar3` will look in the directory `_checkouts` for applications to override a dependency.
-
-For example, you are working on project `app1` which depends on `app2`. You want to have your modifications to `app2` used by `app1`:
-
-```shell
-[app1] $ pwd
-/home/user/code/app1
-[app1] $ cat rebar.config
-{deps, [
- {app2, "", {git, "git://github.com:user/app2.git", {branch, "master"}}}
-]}.
-[app1] $ ls -l _checkouts
-lrwxrwxrwx app2 -> /home/user/code/app2
-```
-
-Since a symlink to `app2` exists in `_checkouts` there will not be a fetch of `app2` by `rebar3` when the project is built.
-
-## Tests
-
-Rebar3 has the concept of test dependencies. These dependencies will only be fetched when a rebar3 command that runs tests is run by the user.
-
-```erlang
-{test_deps, [
- {meck, ".*", {git, "https://github.com/eproxus/meck.git", {tag, "0.8"}}}
- ]}.
-```
-
-```shell
-$ rebar ct
-===> Fetching meck
-===> Compiling meck
-===> Compiling minasan
-```
diff --git a/doc/plugins.md b/doc/plugins.md
deleted file mode 100644
index c8afc91..0000000
--- a/doc/plugins.md
+++ /dev/null
@@ -1,272 +0,0 @@
-# Plugins #
-
-Rebar3's system is based on the concept of *[providers](https://github.com/tsloughter/providers)*. A provider has three callbacks:
-
-- `init(State) -> {ok, NewState}`, which helps set up the state required, state dependencies, etc.
-- `do(State) -> {ok, NewState} | {error, Error}`, which does the actual work.
-- `format_error(Error) -> String`, which allows to print errors when they happen, and to filter out sensitive elements from the state.
-
-A provider should also be an OTP Library application, which can be fetched as any other Erlang dependency, except for Rebar3 rather than your own system or application.
-
-This document contains the following elements:
-
-- [Using a Plugin](#using-a-plugin)
-- [Reference](#reference)
- - [Provider Interface](#provider-interface)
- - [List of Possible Dependencies](#list-of-possible-dependencies)
- - [Rebar State Manipulation](#rebar-state-manipulation)
-- [Tutorial](#tutorial)
-
-## Using a Plugin ##
-
-To use the a plugin, add it to the rebar.config:
-
-```erlang
-{plugins, [
- {plugin_name, ".*", {git, "git@host:user/name-of-plugin.git", {tag, "v1.0.0"}}}
-]}.
-```
-
-Then you can just call it directly:
-
-```
-→ rebar3 plugin_name
-===> Fetching plugin_name
-===> Compiling plugin_name
-<PLUGIN OUTPUT>
-```
-
-## Reference ##
-
-TODO
-
-### Provider Interface ###
-
-TODO
-
-### List of Possible Dependencies ###
-
-TODO
-
-### Rebar State Manipulation ###
-
-TODO
-
-
-## Tutorial ##
-
-### First version ###
-
-In this tutorial, we'll show how to start from scratch, and get a basic plugin written. The plugin will be quite simple: it will look for instances of 'TODO:' lines in comments and report them as warnings. The final code for the plugin can be found on [bitbucket](https://bitbucket.org/ferd/rebar3-todo-plugin).
-
-The first step is to create a new OTP Application that will contain the plugin:
-
- → rebar3 new plugin provider_todo desc="example rebar3 plugin"
- ...
- → cd provider_todo
- → git init
- Initialized empty Git repository in /Users/ferd/code/self/provider_todo/.git/
-
-Open up the `src/provider_todo.erl` file and make sure you have the following skeleton in place:
-
-```erlang
--module(provider_todo).
--behaviour(provider).
-
--export([init/1, do/1, format_error/1]).
-
--define(PROVIDER, todo).
--define(DEPS, [app_discovery]).
-
-%% ===================================================================
-%% Public API
-%% ===================================================================
--spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
-init(State) ->
- Provider = providers:create([
- {name, ?PROVIDER}, % The 'user friendly' name of the task
- {module, ?MODULE}, % The module implementation of the task
- {bare, true}, % The task can be run by the user, always true
- {deps, ?DEPS}, % The list of dependencies
- {example, "rebar provider_todo"}, % How to use the plugin
- {opts, []} % list of options understood by the plugin
- {short_desc, "example rebar3 plugin"},
- {desc, ""}
- ]),
- {ok, rebar_state:add_provider(State, Provider)}.
-
-
--spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
-do(State) ->
- {ok, State}.
-
--spec format_error(any()) -> iolist().
-format_error(Reason) ->
- io_lib:format("~p", [Reason]).
-```
-
-This shows all the basic content needed. Note that we leave the `DEPS` macro to the value `app_discovery`, used to mean that the plugin should at least find the project's source code (excluding dependencies).
-
-In this case, we need to change very little in `init/1`. Here's the new provider description:
-
-```erlang
- Provider = providers:create([
- {name, ?PROVIDER}, % The 'user friendly' name of the task
- {module, ?MODULE}, % The module implementation of the task
- {bare, true}, % The task can be run by the user, always true
- {deps, ?DEPS}, % The list of dependencies
- {example, "rebar todo"}, % How to use the plugin
- {opts, []}, % list of options understood by the plugin
- {short_desc, "Reports TODOs in source code"},
- {desc, "Scans top-level application source and find "
- "instances of TODO: in commented out content "
- "to report it to the user."}
- ]),
-```
-
-Instead, most of the work will need to be done directly in `do/1`. We'll use the `rebar_state` module to fetch all the applications we need. This can be done by calling the `project_apps/1` function, which returns the list of the project's top-level applications.
-
-```erlang
-do(State) ->
- lists:foreach(fun check_todo_app/1, rebar_state:project_apps(State)),
- {ok, State}.
-```
-
-This, on a high level, means that we'll check each top-level app one at a time (there may often be more than one top-level application when working with releases)
-
-The rest is filler code specific to the plugin, in charge of reading each app path, go read code in there, and find instances of 'TODO:' in comments in the code:
-
-```erlang
-check_todo_app(App) ->
- Path = filename:join(rebar_app_info:dir(App),"src"),
- Mods = find_source_files(Path),
- case lists:foldl(fun check_todo_mod/2, [], Mods) of
- [] -> ok;
- Instances -> display_todos(rebar_app_info:name(App), Instances)
- end.
-
-find_source_files(Path) ->
- [filename:join(Path, Mod) || Mod <- filelib:wildcard("*.erl", Path)].
-
-check_todo_mod(ModPath, Matches) ->
- {ok, Bin} = file:read_file(ModPath),
- case find_todo_lines(Bin) of
- [] -> Matches;
- Lines -> [{ModPath, Lines} | Matches]
- end.
-
-find_todo_lines(File) ->
- case re:run(File, "%+.*(TODO:.*)", [{capture, all_but_first, binary}, global, caseless]) of
- {match, DeepBins} -> lists:flatten(DeepBins);
- nomatch -> []
- end.
-
-display_todos(_, []) -> ok;
-display_todos(App, FileMatches) ->
- io:format("Application ~s~n",[App]),
- [begin
- io:format("\t~s~n",[Mod]),
- [io:format("\t ~s~n",[TODO]) || TODO <- TODOs]
- end || {Mod, TODOs} <- FileMatches],
- ok.
-```
-
-Just using `io:format/2` to output is going to be fine.
-
-To test the plugin, push it to a source repository somewhere. Pick one of your projects, and add something to the rebar.config:
-
-```erlang
-{plugins, [
- {provider_todo, ".*", {git, "git@bitbucket.org:ferd/rebar3-todo-plugin.git", {branch, "master"}}}
-]}.
-```
-
-Then you can just call it directly:
-
-```
-→ rebar3 todo
-===> Fetching provider_todo
-===> Compiling provider_todo
-Application merklet
- /Users/ferd/code/self/merklet/src/merklet.erl
- todo: consider endianness for absolute portability
-```
-
-Rebar3 will download and install the plugin, and figure out when to run it. Once compiled, it can be run at any time again.
-
-### Optionally Search Deps ###
-
-Let's extend things a bit. Maybe from time to time (when cutting a release), we'd like to make sure none of our dependencies contain 'TODO:'s either.
-
-To do this, we'll need to go parse command line arguments a bit, and change our execution model. The `?DEPS` macro will now need to specify that the `todo` provider can only run *after* dependencies have been installed:
-
-```erlang
--define(DEPS, [install_deps]).
-```
-
-We can add the option to the list we use to configure the provider in `init/1`:
-
-```erlang
-{opts, [ % list of options understood by the plugin
- {deps, $d, "deps", undefined, "also run against dependencies"}
-]},
-```
-
-Meaning that deps can be flagged in by using the option `-d` (or `--deps`), and if it's not defined, well, we get the default value `undefined`. The last element of the 4-tuple is documentation for the option.
-
-And then we can implement the switch to figure out what to search:
-
-```erlang
-do(State) ->
- Apps = case discovery_type(State) of
- project -> rebar_state:project_apps(State);
- deps -> rebar_state:project_apps(State) ++ rebar_state:all_deps(State)
- end,
- lists:foreach(fun check_todo_app/1, Apps),
- {ok, State}.
-
-[...]
-
-discovery_type(State) ->
- {Args, _} = rebar_state:command_parsed_args(State),
- case proplists:get_value(deps, Args) of
- undefined -> project;
- _ -> deps
- end.
-```
-
-The `deps` option is found using `rebar_state:command_parsed_args(State)`, which will return a proplist of terms on the command-line after 'todo', and will take care of validating whether the flags are accepted or not. The rest can remain the same.
-
-Push the new code for the plugin, and try it again on a project with dependencies:
-
-```
-→ rebar3 todo --deps
-===> Fetching provider_todo
-===> Compiling provider_todo
-===> Fetching bootstrap
-===> Fetching file_monitor
-===> Fetching recon
-[...]
-Application dirmon
- /Users/ferd/code/self/figsync/apps/dirmon/src/dirmon_tracker.erl
- TODO: Peeranha should expose the UUID from a node.
-Application meck
- /Users/ferd/code/self/figsync/_deps/meck/src/meck_proc.erl
- TODO: What to do here?
- TODO: What to do here?
-```
-
-Rebar3 will now go pick dependencies before running the plugin on there.
-
-you can also see that the help will be completed for you:
-
-```
-→ rebar3 help todo
-Scans top-level application source and find instances of TODO: in commented out content to report it to the user.
-
-Usage: rebar todo [-d]
-
- -d, --deps also run against dependencies
-```
-
-That's it, the todo plugin is now complete! It's ready to ship and be included in other repositories.
diff --git a/doc/templates.md b/doc/templates.md
deleted file mode 100644
index 598a689..0000000
--- a/doc/templates.md
+++ /dev/null
@@ -1,192 +0,0 @@
-# Templates #
-
-- [Default Variables](#default-variables)
-- [Global Variables](#global-variables)
-- [Batteries-Included Templates](#batteries-included-templates)
-- [Custom Templates](#custom-templates)
-
-## Default Variables
-
-- `date`: defaults to today's date, under universal time, printed according to RFC 8601 (for example, `"2014-03-11"`)
-- `datetime`: defaults to today's date and time, under universal time, printed according to RFC 8601 (for example, `"2014-03-11T16:06:02+00:00"`).
-- `author_name`: Defaults to `"Anonymous"`
-- `author_email`: Defaults to `"anonymous@example.org"`
-- `apps_dir`: Directory where OTP applications should be created in release projects. Defaults to `"apps/"`.
-- `copyright_year`: Defaults to the current year, under universal time.
-
-
-## Global Variables
-
-Global variables can be set by editing the file at `$HOME/.config/rebar3/templates/globals`:
-
- {variables, [
- {author_name, "My Name Is A String"},
- {copyright_year, "2014-2022", "The year or range of years for copyright"},
- {my_custom_var, "hello there"}
- ]}.
-
-This will let you define variables for all templates.
-
-Variables left undefined will be ignored and revert to the default value.
-
-The override order for these variables will be: Defaults < $HOME/.config/rebar3/templates/globals < command line invocation.
-
-## Batteries-Included Templates ##
-
-Rebar3 ships with a few templates installed, which can be listed by calling `rebar3 new`:
-
- → ./rebar3 new
- app (built-in): OTP Application
- lib (built-in): OTP Library application (no processes)
- release (built-in): OTP Release structure for executable programs
- plugin (built-in): Rebar3 plugin
-
-Any custom plugins would be followed as `<plugin_name> (custom): <description>`.
-
-Details for each individual plugin can be obtained by calling `rebar3 new help <plugin>`:
-
- → ./rebar3 new help plugin
- plugin:
- built-in template
- Description: Rebar3 plugin
- Variables:
- name="myplugin" (Name of the plugin)
- desc="A rebar plugin" (Short description of the plugin's purpose)
- date="2014-11-10"
- datetime="2014-11-10T18:29:41+00:00"
- author_name="Anonymous"
- author_email="anonymous@example.org"
- copyright_year="2014"
- apps_dir="apps/" (Directory where applications will be created if needed)
-
-All the variables there have their default values shown, and an optional explanation in parentheses.
-
-The variables can also be [overriden globally](#global-variables).
-
-A template can be run by calling:
-
- → ./rebar3 new plugin name=demo author_name="Fred H."
- ...
-
-Alternatively, the `name` variable is special -- if the first argument to a template has no key associated with it, `name` is automatically added. The call above is therefore equivalent to:
-
- → ./rebar3 new plugin demo author_name="Fred H."
- ...
-
-Then go to the directory created for the project by rebar3.
-
-## Custom Templates ##
-
-Custom templates can be added in `$HOME/.config/rebar3/templates/`. Each template is at least two files:
-
-- `my_template.dtl`: There can be many of these files. They are regular Erlang files using the django template syntax for variable replacements.
-- `my_template.template`; Called the *template index*, there is one per template callable from `rebar3`. This one will be visible when calling `rebar3 new my_template`. This file regroups the different \*.dtl files into a more cohesive template.
-
-### File Syntax ###
-
-#### Template Index ####
-
-The following options are available:
-
- {description, "This template does a thing"}.
- {variables, [
- {var1, "default value"},
- {var2, "default", "explain what this does in help files"},
- {app_dir, ".", "The directory where the application goes"}
- ]}.
- {dir, "{{appdir}}/src"}.
- {file, "mytemplate_README", "README"}.
- {chmod, "README", 8#644}.
- {template, "myapp/myapp.app.src.dtl", "{{appdir}}/src/{{name}}.app.src"}.
-
-Specifically:
-
-- `description`: takes a string explaining what the template is for.
-- `variables`: takes a list of variables in two forms:
- - `{Name, DefaultString, HelpString}`;
- - `{Name, DefaultString}`.
-- `{dir, TemplatablePathString}`: creates a given directory. Variable names can be used in the path name.
-- `{file, FilePath, DestFilePath}`: copies a file literally to its destination.
-- `{template, DtlFilePath, TemplatablePathString}`: evaluates a given template. The `DtlFilePath` is relative to the template index.
-- `{chmod, FilePath, Int}`: changes the permission of a file, using the integer value specified. Octal values can be entered by doing `8#640`.
-
-### Example ###
-
-As an example, we'll create a template for Common Test test suites. Create the directory structure `~/.config/rebar/templates/` and then go in there.
-
-We'll start with an index for our template, called `ct_suite.template`:
-
-```erlang
-{description, "A basic Common Test suite for an OTP application"}.
-{variables, [
- {name, "suite", "Name of the suite, prepended to the standard _SUITE suffix"}
-]}.
-
-{dir, "test"}.
-{template, "ct_suite.erl.dtl", "test/{{name}}_SUITE.erl"}.
-```
-
-This tells rebar3 to create the test directory and to evaluate an [ErlyDTL](https://github.com/erlydtl/erlydtl) template. All the paths are relative to the current working directory.
-
-Let's create the template file:
-
-```erlang
--module({{name}}_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("eunit/include/eunit.hrl"). % Eunit macros for convenience
-
--export([all/0
- ,groups/0
- %,init_per_suite/1, end_per_suite/1
- %,init_per_group/2, end_per_group/2
- ,init_per_testcase/2, end_per_testcase/2
- ]).
-
--export([fail/1]).
-
-all() -> [fail].
-
-groups() -> [].
-
-init_per_testcase(_Name, Config) -> Config.
-
-end_per_testcase(_Name, _Config) -> ok.
-
-fail(_Config) ->
- ?assert(false).
-```
-
-This one does very simple variable substitution for the name (using `{{name}}`) and that's all it needs.
-
-Let's get to any existing project you have and try it:
-
- → ./rebar3 new
- app (built-in): OTP Application
- ct_suite (custom): A basic Common Test suite for an OTP application
- lib (built-in): OTP Library application (no processes)
- release (built-in): OTP Release structure for executable programs
- plugin (built-in): Rebar3 plugin
-
-The first line shows that our `ct_suite` temlate has been detected and is usable.
-Let's look at the details:
-
- → ./rebar3 new help ct_suite
- ct_suite:
- custom template (/home/ferd/.config/rebar3/templates/ct_suite.template)
- Description: A basic Common Test suite for an OTP application
- Variables:
- name="suite" (Name of the suite, prepended to the standard _SUITE suffix)
- date="2014-11-10"
- datetime="2014-11-10T18:46:33+00:00"
- author_name="Anonymous"
- author_email="anonymous@example.org"
- copyright_year="2014"
- apps_dir="apps/" (Directory where applications will be created if needed)
-
-The documentation from variables and the description are well in place. To apply the template, go to any of your OTP application's top-level directory:
-
- → ./rebar3 new ct_suite demo
- ===> Writing test/demo_SUITE.erl
-
-And you will see the code in place.