# `raw` Resource Provider for Rebar3

[Rebar3][rebar3] requires that all dependencies be structured as OTP applications.
There are, however, lots of cases when you just want to include a dependency in your project from which to pull unstructured resources, whether source code, graphics, text, or any number of other possibilities.
This `rebar3` plugin allows you to do just that.

## What It Does

This resource provider does two things:

 * Wraps dependency specifications for other resource providers, leveraging their abilities to retrieve and provide information about their target dependencies.

 * Creates a minimal OTP application structure in retrieved dependencies that satisfies rebar's structure requirements.

## How to Use It

Everything the plugin does is configured in your project's `rebar.config` file.

What you do with the dependency once you get it into rebar's build tree is up to you, but `rebar3` has a _(somewhat)_ documented set of environment variables that allow you to find it so you can do with it what you need. The variable `$REBAR_DEPS_DIR`, in particular, points to the directory under which you'll find the downloaded dependency.

_You'll find some information in the [rebar3 configuration][rebar3cfg] documentation, but you may need to run `rebar3` with `DEBUG` set and/or review the [source][rebar3src] to find all of the accessible information._

### Add The Plugin

The following addition to `rebar.config` makes the plugin available for use with your dependencies:

{plugins, [
        {git, "git://",
        {branch, "master"}}}

### Add Raw Dependencies

The `raw` resource type is simply a wrapper around another type, so the basic structure of a raw dependency is:

{deps, [
    . . .
    {mydep1, {raw, {mydep1-resource-specification} }},
    {mydep2, {raw, {mydep2-resource-specification}, [raw-options] }},
    . . .

In the above, the _resource-specification_ tuples are as described in Rebar's [documentation][depdocs], and might look like this:

    {git, "git://some/git/repo.git", {branch, "master"}}
    {hg,  "https://some/mercurial/repo"}

The `raw` resource doesn't know anything about other resource types, it just uses their specifications to call into other resource providers to fetch and report on the dependencies.

#### Dependency Options

You can optionally include a description and/or version in a `raw` dependency specification which will affect the generated `.app` file.
By default, for a dependency named `foo` that has neither a `src/` or `ebin/` file, a `ebin/` file will be written that looks like this:

%% Generated by rebar_raw_resource
{application,   foo,
    {description,   "foo"},
    {vsn,           "some-version-string"},
    {modules,       []},
    {registered,    []},
    {applications,  [kernel, stdlib]}

The `description` field is simply the dependency's name, and the `vsn` field is whatever the underlying resource provider returns from the downloaded dependency. You can override these values by providing your own as in the following:

{deps, [
    . . .
    {snappy,  {raw, {git, "git://", {branch, "master"}},
                    [ {description, "Google's Snappy compression library"},
                      {vsn, "probably-not-a-good-idea-to-override-this"} ] }}
    . . .

##### A Note About Dependency Options

There are probably very few, if any, legitimate use cases for these dependency options.
If the dependency is going to be included in your project as an OTP application, you should almost certainly craft a more appropriate `.app` or `.app.src` file.

## Caveats

###Scope of Dependency Names and Locations

At present, I don't discriminate between scopes, assuming a given dependency location always maps to the same name.
Including the dependency's version selector and profile would allow complete uniqueness of mappings, but subsequent operations may alter the version selector, resulting in matches not being found.
Overall, I think it's reasonable to have a constraint saying _"You **MUST** use the same name for a given dependency URL across profiles"_ - in fact, that constraint may also be implicit in rebar3 itself, though it doesn't appear to be formally declared.

Because the nested resource specifiers (rightly) don't have a specified schema, we treat them as relatively opaque tuples where the first element is the type and the second element is the location.

Old-style dependencies with a version regex immediately following the dependency name SHOULD be accommodated but ignored, though this aspect hasn't been, and isn't likely to be, rigorously tested as it's moot in rebar3.

### Dependency Source Tree Modification

Currently, we satisfy rebar's need for an OTP application by scribbling a minimal app config file in `dep-path/ebin/` if there's neither such a file already, nor its equivalent source in the `dep-path/src` directory. If anything that will satisfy rebar3's OTP application requirement is found, the plugin won't write any file.

It would be preferable to build the `rebar_app_info` record dynamically and insert it into the state so we didn't have to leave droppings in the dependency's filesystem, but it's unclear whether there's a reliable place to hook that functionality into the processing sequence or whether rebar would accept it if we did without an actual file to check for changes.

Note that the above means that if you go into the dependency's source directory and check its status it will appear to have pending changes, but you probably don't want to commit the generated file.

## Enhancements

If you find a bug, please report an [issue][issues], or better yet, fix it and submit a [pull request][pulls].

## License

Everything here is covered by this [license][license].

  [license]:    LICENSE