Rebar3 support (no elixir for now)
diff --git a/Makefile b/Makefile
index 82c2b33..0397ad9 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 
 include version.mk
 
-REBAR?=$(shell echo `pwd`/bin/rebar)
+REBAR3?=$(shell echo `pwd`/bin/rebar3)
 ERLFMT?=$(shell echo `pwd`/bin/erlfmt)
 
 # Handle the following scenarios:
@@ -27,13 +27,13 @@
 #      tarball itself.
 #   4. When not on a clean tag, use version.mk + git sha + dirty status.
 
-COUCHDB_GIT_SHA=$(git_sha)
+# COUCHDB_GIT_SHA=$(git_sha)
 
 IN_RELEASE = $(shell if [ ! -d .git ]; then echo true; fi)
 ifeq ($(IN_RELEASE), true)
 
 # 1. Building from tarball, use version.mk.
-COUCHDB_VERSION = $(vsn_major).$(vsn_minor).$(vsn_patch)
+export COUCHDB_VERSION = $(vsn_major).$(vsn_minor).$(vsn_patch)
 
 else
 
@@ -52,15 +52,15 @@
 # DIRTY identifies if we're not on a commit
 DIRTY = $(shell git describe --dirty | grep -Eo -- '-dirty' 2>/dev/null)
 # COUCHDB_GIT_SHA is our current git hash.
-COUCHDB_GIT_SHA=$(shell git rev-parse --short=7 --verify HEAD)
+export COUCHDB_GIT_SHA=$(shell git rev-parse --short=7 --verify HEAD)
 
 ifeq ($(ON_TAG),)
 # 4. Not on a tag.
 COUCHDB_VERSION_SUFFIX = $(COUCHDB_GIT_SHA)$(DIRTY)
-COUCHDB_VERSION = $(vsn_major).$(vsn_minor).$(vsn_patch)-$(COUCHDB_VERSION_SUFFIX)
+export COUCHDB_VERSION = $(vsn_major).$(vsn_minor).$(vsn_patch)-$(COUCHDB_VERSION_SUFFIX)
 else
 # 2 and 3. On a tag.
-COUCHDB_VERSION = $(REL_TAG)$(DIRTY)
+export COUCHDB_VERSION = $(REL_TAG)$(DIRTY)
 endif
 endif
 
@@ -71,24 +71,6 @@
 
 DESTDIR=
 
-# Rebar options
-apps=
-skip_deps=folsom,meck,mochiweb,triq,proper,snappy,bcrypt,hyper,ibrowse
-suites=
-tests=
-
-COMPILE_OPTS=$(shell echo "\
-	apps=$(apps) \
-	" | sed -e 's/[a-z_]\{1,\}= / /g')
-EUNIT_OPTS=$(shell echo "\
-	skip_deps=$(skip_deps) \
-	suites=$(suites) \
-	tests=$(tests) \
-	" | sed -e 's/[a-z]\{1,\}= / /g')
-DIALYZE_OPTS=$(shell echo "\
-	apps=$(apps) \
-	skip_deps=$(skip_deps) \
-	" | sed -e 's/[a-z]\{1,\}= / /g')
 EXUNIT_OPTS=$(subst $(comma),$(space),$(tests))
 
 TEST_OPTS="-c 'startup_jitter=0' -c 'default_security=admin_local'"
@@ -120,7 +102,8 @@
 .PHONY: couch
 # target: couch - Build CouchDB core, use ERL_COMPILER_OPTIONS to provide custom compiler's options
 couch: config.erl
-	@COUCHDB_VERSION=$(COUCHDB_VERSION) COUCHDB_GIT_SHA=$(COUCHDB_GIT_SHA) $(REBAR) compile $(COMPILE_OPTS)
+	@# FIXME
+	@[ -e bin/couchjs ] || COUCHDB_VERSION=$(COUCHDB_VERSION) COUCHDB_GIT_SHA=$(COUCHDB_GIT_SHA) $(REBAR3) compile
 	@cp src/couch/priv/couchjs bin/
 
 
@@ -140,8 +123,8 @@
 .PHONY: escriptize
 # target: escriptize - Build CLI tools
 escriptize: couch
-	@$(REBAR) -r escriptize apps=weatherreport
-	@cp src/weatherreport/weatherreport bin/weatherreport
+	@[ -e bin/weatherreport ] || COUCHDB_VERSION=$(COUCHDB_VERSION) COUCHDB_GIT_SHA=$(COUCHDB_GIT_SHA) $(REBAR3) escriptize -a weatherreport
+	@cp _build/default/bin/weatherreport bin/weatherreport
 
 
 ################################################################################
@@ -158,51 +141,43 @@
 	@$(MAKE) elixir-suite
 	@$(MAKE) weatherreport-test
 
-ifdef apps
-subdirs = $(apps)
-else
-subdirs=$(shell ls src)
-endif
-
 .PHONY: eunit
 # target: eunit - Run EUnit tests, use EUNIT_OPTS to provide custom options
 eunit: export BUILDDIR = $(shell pwd)
 eunit: export ERL_AFLAGS = -config $(shell pwd)/rel/files/eunit.config
 eunit: export COUCHDB_QUERY_SERVER_JAVASCRIPT = $(shell pwd)/bin/couchjs $(shell pwd)/share/server/main.js
 eunit: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1
-eunit: couch
-	@COUCHDB_VERSION=$(COUCHDB_VERSION) COUCHDB_GIT_SHA=$(COUCHDB_GIT_SHA) $(REBAR) setup_eunit 2> /dev/null
-	@for dir in $(subdirs); do \
-            COUCHDB_VERSION=$(COUCHDB_VERSION) COUCHDB_GIT_SHA=$(COUCHDB_GIT_SHA) $(REBAR) -r eunit $(EUNIT_OPTS) apps=$$dir || exit 1; \
-        done
-
+eunit: couch setup-eunit
+	echo ${COUCH_VERSION}
+	$(REBAR3) eunit $(addprefix --app ,$(apps)) || exit 1
 
 .PHONY: exunit
 # target: exunit - Run ExUnit tests
 exunit: export BUILDDIR = $(shell pwd)
 exunit: export MIX_ENV=test
-exunit: export ERL_LIBS = $(shell pwd)/src
+exunit: export ERL_LIBS = $(shell pwd)/_build/default/lib
 exunit: export ERL_AFLAGS = -config $(shell pwd)/rel/files/eunit.config
 exunit: export COUCHDB_QUERY_SERVER_JAVASCRIPT = $(shell pwd)/bin/couchjs $(shell pwd)/share/server/main.js
 exunit: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1
 exunit: couch elixir-init setup-eunit elixir-check-formatted elixir-credo
 	@mix test --trace $(EXUNIT_OPTS)
 
+.PHONY: setup-eunit
 setup-eunit: export BUILDDIR = $(shell pwd)
 setup-eunit: export ERL_AFLAGS = -config $(shell pwd)/rel/files/eunit.config
 setup-eunit:
-	@$(REBAR) setup_eunit 2> /dev/null
+	@$(REBAR3) ic setup_eunit 2> /dev/null
 
 just-eunit: export BUILDDIR = $(shell pwd)
 just-eunit: export ERL_AFLAGS = -config $(shell pwd)/rel/files/eunit.config
-just-eunit:
-	@$(REBAR) -r eunit $(EUNIT_OPTS)
+just-eunit: setup_eunit
+	@$(REBAR3) -r eunit $(EUNIT_OPTS)
 
 .PHONY: soak-eunit
 soak-eunit: export BUILDDIR = $(shell pwd)
 soak-eunit: export ERL_AFLAGS = -config $(shell pwd)/rel/files/eunit.config
-soak-eunit: couch
-	@$(REBAR) setup_eunit 2> /dev/null
+soak-eunit: couch setup_eunit
+	@$(REBAR3) setup_eunit 2> /dev/null
 	while [ $$? -eq 0 ] ; do $(REBAR) -r eunit $(EUNIT_OPTS) ; done
 
 erlfmt-check:
@@ -335,31 +310,12 @@
 # Developing
 ################################################################################
 
-
-.PHONY: build-plt
-# target: build-plt - Build project-specific PLT
-build-plt:
-	@$(REBAR) -r build-plt $(DIALYZE_OPTS)
-
-
-.PHONY: check-plt
-# target: check-plt - Check the PLT for consistency and rebuild it if it is not up-to-date
-check-plt:
-	@$(REBAR) -r check-plt $(DIALYZE_OPTS)
-
-
-.PHONY: dialyze
+.PHONY: dialyzer
 # target: dialyze - Analyze the code for discrepancies
-dialyze: .rebar
-	@$(REBAR) -r dialyze $(DIALYZE_OPTS)
+dialyzer: .rebar
+	@$(REBAR3) -r dialyzer $(DIALYZE_OPTS)
 
 
-.PHONY: introspect
-# target: introspect - Check for commits difference between rebar.config and repository
-introspect:
-	@$(REBAR) -r update-deps
-	@build-aux/introspect
-
 ################################################################################
 # Distributing
 ################################################################################
@@ -387,28 +343,21 @@
 release: all
 	@echo "Installing CouchDB into rel/couchdb/ ..."
 	@rm -rf rel/couchdb
-	@$(REBAR) generate # make full erlang release
-	@cp bin/weatherreport rel/couchdb/bin/weatherreport
+	@$(REBAR3) release # make full erlang release
 
 ifeq ($(with_fauxton), 1)
-	@mkdir -p rel/couchdb/share/
-	@cp -R share/www rel/couchdb/share/
+	@mkdir -p _build/default/rel/couchdb/share/
+	@cp -R share/www _build/default/rel/couchdb/share/
 endif
 
 ifeq ($(with_docs), 1)
 ifeq ($(IN_RELEASE), true)
-	@mkdir -p rel/couchdb/share/www/docs/
-	@mkdir -p rel/couchdb/share/docs/
-	@cp -R share/docs/html/* rel/couchdb/share/www/docs/
-	@cp share/docs/man/apachecouchdb.1 rel/couchdb/share/docs/couchdb.1
-else
-	@mkdir -p rel/couchdb/share/www/docs/
-	@mkdir -p rel/couchdb/share/docs/
-	@cp -R src/docs/build/html/ rel/couchdb/share/www/docs
-	@cp src/docs/build/man/apachecouchdb.1 rel/couchdb/share/docs/couchdb.1
+	@mkdir -p _build/default/rel/couchdb/share/www/docs/
+	@mkdir -p _build/default/rel/couchdb/share/docs/
+	@cp -R share/docs/html/* _build/default/rel/couchdb/share/www/docs/
+	@cp share/docs/man/apachecouchdb.1 _build/default/rel/couchdb/share/docs/couchdb.1
 endif
 endif
-
 	@echo "... done"
 	@echo
 	@echo "    You can now copy the rel/couchdb directory anywhere on your system."
@@ -434,23 +383,15 @@
 .PHONY: clean
 # target: clean - Remove build artifacts
 clean:
-	@$(REBAR) -r clean
-	@rm -rf .rebar/
+	@$(REBAR3) clean
+	@rm -rf _build
 	@rm -f bin/couchjs
 	@rm -f bin/weatherreport
-	@rm -rf src/*/ebin
-	@rm -rf src/*/.rebar
-	@rm -rf src/*/priv/*.so
-	@rm -rf src/couch/priv/{couchspawnkillable,couchjs}
 	@rm -rf share/server/main.js share/server/main-coffee.js
 	@rm -rf tmp dev/data dev/lib dev/logs
-	@rm -rf src/mango/.venv
-	@rm -f src/couch/priv/couchspawnkillable
-	@rm -f src/couch/priv/couch_js/config.h
 	@rm -f dev/*.beam dev/devnode.* dev/pbkdf2.pyc log/crash.log
 	@rm -f dev/erlserver.pem dev/couch_ssl_dist.conf
 
-
 .PHONY: distclean
 # target: distclean - Remove build and release artifacts
 distclean: clean
diff --git a/_checkouts/ic/priv/setup_eunit.template b/_checkouts/ic/priv/setup_eunit.template
new file mode 100644
index 0000000..fbb567c
--- /dev/null
+++ b/_checkouts/ic/priv/setup_eunit.template
@@ -0,0 +1,21 @@
+{variables, [
+    {package_author_name, "The Apache Software Foundation"},
+    {cluster_port, 5984},
+    {backend_port, 5986},
+    {prometheus_port, 17986},
+    {node_name, "-name couchdbtest@127.0.0.1"},
+
+    {data_dir, "/tmp"},
+    {prefix, "/tmp"},
+    {view_index_dir, "/tmp"},
+    {state_dir, "/tmp"}
+]}.
+{dir, "tmp"}.
+{dir, "tmp/etc"}.
+{dir, "tmp/data"}.
+{dir, "tmp/tmp_data"}.
+
+{template, "../../../rel/overlay/etc/default.ini", "tmp/etc/default_eunit.ini"}.
+{template, "../../../rel/overlay/etc/local.ini", "tmp/etc/local_eunit.ini"}.
+{template, "../../../rel/files/eunit.ini", "tmp/etc/eunit.ini"}.
+{template, "../../../rel/overlay/etc/vm.args", "tmp/etc/vm.args"}.
diff --git a/_checkouts/ic/src/ic.app.src b/_checkouts/ic/src/ic.app.src
new file mode 100644
index 0000000..cbc56fc
--- /dev/null
+++ b/_checkouts/ic/src/ic.app.src
@@ -0,0 +1,7 @@
+{application, ic, [
+    {description, "rebar3 ic plugin"},
+    {vsn, "0.1.0"},
+    {registered, []},
+    {applications, [kernel, stdlib]},
+    {env, []}
+]}.
diff --git a/_checkouts/ic/src/ic.erl b/_checkouts/ic/src/ic.erl
new file mode 100644
index 0000000..f808b7d
--- /dev/null
+++ b/_checkouts/ic/src/ic.erl
@@ -0,0 +1,8 @@
+-module(ic).
+
+-export([init/1]).
+
+-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
+init(State) ->
+    {ok, State1} = ic_prv_setup_eunit:init(State),
+    {ok, State1}.
diff --git a/_checkouts/ic/src/ic_prv_setup_eunit.erl b/_checkouts/ic/src/ic_prv_setup_eunit.erl
new file mode 100644
index 0000000..16cbde3
--- /dev/null
+++ b/_checkouts/ic/src/ic_prv_setup_eunit.erl
@@ -0,0 +1,81 @@
+-module(ic_prv_setup_eunit).
+
+-behaviour(provider).
+
+-export([init/1, do/1, format_error/1]).
+
+-define(PROVIDER, setup_eunit).
+-define(NAMESPACE, ic).
+-define(CWD, filename:absname(rebar_dir:get_cwd())).
+-define(TEMPLATE, "setup_eunit").
+-define(DEPS, []).
+
+%% ===================================================================
+%% Public API
+%% ===================================================================
+-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
+init(State) ->
+    Provider = providers:create([
+        {namespace, ?NAMESPACE},
+        {name, ?PROVIDER},
+        {module, ?MODULE},
+        {bare, true},
+        {deps, ?DEPS},
+        {example, "rebar3 ic setup_eunit"},
+        {opts, [{force, $f, "force", undefined, "overwrite existing files"}]},
+        {short_desc, "Setup eunit from template"},
+        {desc, "Setup eunit from template"}
+    ]),
+    {ok, rebar_state:add_provider(State, Provider)}.
+
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
+do(State) ->
+    build_eunit_config(State),
+    {ok, State}.
+
+-spec format_error(any()) -> iolist().
+format_error(Reason) ->
+    io_lib:format("~p", [Reason]).
+
+%% ===================================================================
+%% Internal functions
+%% ===================================================================
+build_eunit_config(State) ->
+    Force = is_forced(State),
+    DataDir = ?CWD ++ "/tmp/data",
+    TmpDataDir = ?CWD ++ "/tmp/tmp_data",
+    cleanup_dirs([DataDir, TmpDataDir]),
+    AllOpts = [
+        {template, ?TEMPLATE},
+        {prefix, ?CWD},
+        {data_dir, DataDir},
+        {view_index_dir, DataDir},
+        {geo_index_dir, DataDir},
+        {state_dir, TmpDataDir}
+    ],
+    StateNew = lists:foldl(
+        fun({Key, Value}, StateAcc) ->
+            rebar_state:set(StateAcc, Key, Value)
+        end,
+        State,
+        AllOpts
+    ),
+    ok = rebar_templater:new(?TEMPLATE, [], Force, StateNew).
+
+is_forced(State) ->
+    {Args, _} = rebar_state:command_parsed_args(State),
+    case proplists:get_value(force, Args) of
+        undefined -> false;
+        _ -> true
+    end.
+
+cleanup_dirs(Dirs) ->
+    [del_dir(Dir) || Dir <- Dirs, filelib:is_dir(Dir)].
+
+del_dir(Dir) ->
+    All = filelib:wildcard(Dir ++ "/**"),
+    {Dirs, Files} = lists:partition(fun filelib:is_dir/1, All),
+    lists:foreach(fun file:delete/1, Files),
+    SortedDirs = lists:sort(fun(A, B) -> length(A) > length(B) end, Dirs),
+    lists:foreach(fun file:del_dir/1, SortedDirs),
+    file:del_dir(Dir).
diff --git a/configure b/configure
index 9f8cb68..504a8a8 100755
--- a/configure
+++ b/configure
@@ -55,7 +55,6 @@
   --dev                       alias for --disable-docs --disable-fauxton
   --spidermonkey-version VSN  specify the version of SpiderMonkey to use (defaults to $SM_VSN)
   --skip-deps                 do not update erlang dependencies
-  --rebar=PATH                use rebar by specified path (version >=2.6.0 && <3.0 required)
   --generate-tls-dev-cert     generate a cert for TLS distribution (To enable TLS, change the vm.args file.)
   --rebar3=PATH               use rebar3 by specified path
   --erlfmt=PATH               use erlfmt by specified path
@@ -126,22 +125,6 @@
                 continue
                 ;;
 
-            --rebar)
-                if [ -x "$2" ]; then
-                    version=`$2 --version 2> /dev/null | grep -o "2\.[6-9]\.[0-9]"`
-                    if [ $? -ne 0 ]; then
-                        printf 'Rebar >=2.6.0 and <3.0.0 required' >&2
-                        exit 1
-                    fi
-                    eval REBAR=$2
-                    shift 2
-                    continue
-                else
-                    printf 'ERROR: "--rebar" requires valid path to executable.\n' >&2
-                    exit 1
-                fi
-                ;;
-
             --rebar3)
                 if [ -x "$2" ]; then
                     eval REBAR3=$2
@@ -291,27 +274,14 @@
 {spidermonkey_version, "$SM_VSN"}.
 EOF
 
-install_local_rebar() {
-    if [ ! -x "${rootdir}/bin/rebar" ]; then
-        if [ ! -d "${rootdir}/src/rebar" ]; then
-            # git clone --depth 1 https://github.com/apache/couchdb-rebar.git ${rootdir}/src/rebar
-            git clone https://github.com/apache/couchdb-rebar.git ${rootdir}/src/rebar
-        fi
-        make -C ${rootdir}/src/rebar
-        mv ${rootdir}/src/rebar/rebar ${rootdir}/bin/rebar
-        make -C ${rootdir}/src/rebar clean
-    fi
-}
-
 install_local_rebar3() {
     if [ ! -x "${rootdir}/bin/rebar3" ]; then
         if [ ! -d "${rootdir}/src/rebar3" ]; then
-            git clone --depth 1 --branch ${REBAR3_BRANCH} https://github.com/erlang/rebar3.git ${rootdir}/src/rebar3
+            #git clone --depth 1 --branch 82-rebar3 https://github.com/jiahuili430/rebar3.git ${rootdir}/apps/rebar3
+            git clone --depth 1 https://github.com/erlang/rebar3 ${rootdir}/src/rebar3
         fi
-        cd src/rebar3
-        ./bootstrap
-        mv ${rootdir}/src/rebar3/rebar3 ${rootdir}/bin/rebar3
-        cd ../..
+        cd ${rootdir}/src/rebar3 && ./bootstrap && mv rebar3 ${rootdir}/bin/rebar3
+        cd ${rootdir}
     fi
 }
 
@@ -328,11 +298,6 @@
     fi
 }
 
-if [ -z "${REBAR}" ]; then
-    install_local_rebar
-    REBAR=${rootdir}/bin/rebar
-fi
-
 if [ -z "${REBAR3}" ]; then
     install_local_rebar3
     REBAR3=${rootdir}/bin/rebar3
@@ -346,7 +311,7 @@
 # only update dependencies, when we are not in a release tarball
 if [ -d .git  -a $SKIP_DEPS -ne 1 ]; then
     echo "==> updating dependencies"
-    ${REBAR} get-deps update-deps
+    ${REBAR3} get-deps
 fi
 
 # External repos frequently become integrated with the primary repo,
diff --git a/mix.exs b/mix.exs
index 4dda326..608283a 100644
--- a/mix.exs
+++ b/mix.exs
@@ -52,7 +52,7 @@
       version: "0.1.0",
       elixir: "~> 1.13",
       lockfile: Path.expand("mix.lock", __DIR__),
-      deps_path: Path.expand("src", __DIR__),
+      deps_path: Path.expand("_build/default/lib", __DIR__),
       build_path: Path.expand("_build", __DIR__),
       compilers: [:elixir, :app],
       start_permanent: Mix.env() == :prod,
@@ -72,7 +72,7 @@
   # Run "mix help compile.app" to learn about applications.
   def application do
     [
-      extra_applications: [:logger],
+      extra_applications: [:logger, :couch_log, :config],
       applications: [:httpotion]
     ]
   end
@@ -90,14 +90,14 @@
       {:excoveralls, "~> 0.12", only: :test},
       {:b64url, path: path("b64url")},
       {:jiffy, path: path("jiffy")},
-      {:jwtf, path: path("jwtf")},
+      {:jwtf, path: Path.expand("src/jwtf", __DIR__)},
       {:ibrowse, path: path("ibrowse"), override: true},
       {:credo, "~> 1.6.4", only: [:dev, :test, :integration], runtime: false}
     ]
   end
 
   defp path(app) do
-    lib_dir = Path.expand("src", __DIR__)
+    lib_dir = Path.expand("_build/default/lib", __DIR__)
     Path.expand(app, lib_dir)
   end
 
@@ -148,7 +148,7 @@
       "folsom"
     ]
 
-    deps |> Enum.map(fn app -> "src/#{app}" end)
+    deps |> Enum.map(fn app -> "_build/default/lib/#{app}" end)
   end
 
   defp get_coverage_paths() do
@@ -158,7 +158,7 @@
         MapSet.put(set, "#{x}/ebin")
       end)
 
-    Path.wildcard("src/*/ebin")
+    Path.wildcard("_build/default/lib/*/ebin")
     |> Enum.filter(&File.dir?/1)
     |> Enum.filter(fn path -> not MapSet.member?(deps, path) end)
   end
diff --git a/rebar.config.script b/rebar.config.script
index 1aa1630..322963b 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -104,62 +104,6 @@
 
 os:putenv("COUCHDB_APPS_CONFIG_DIR", filename:join([COUCHDB_ROOT, "rel/apps"])).
 
-SubDirs = [
-    %% must be compiled first as it has a custom behavior
-    "src/couch_epi",
-    "src/couch_log",
-    "src/chttpd",
-    "src/couch",
-    "src/couch_event",
-    "src/mem3",
-    "src/couch_index",
-    "src/couch_mrview",
-    "src/couch_replicator",
-    "src/couch_plugins",
-    "src/couch_pse_tests",
-    "src/couch_stats",
-    "src/couch_peruser",
-    "src/couch_tests",
-    "src/couch_dist",
-    "src/custodian",
-    "src/ddoc_cache",
-    "src/dreyfus",
-    "src/fabric",
-    "src/global_changes",
-    "src/ioq",
-    "src/jwtf",
-    "src/ken",
-    "src/mango",
-    "src/rexi",
-    "src/setup",
-    "src/smoosh",
-    "src/weatherreport",
-    "src/couch_prometheus",
-    "rel"
-].
-
-DepDescs = [
-%% Independent Apps
-{config,           "config",           {tag, "2.1.9"}},
-{b64url,           "b64url",           {tag, "1.0.3"}},
-{ets_lru,          "ets-lru",          {tag, "1.1.0"}},
-{khash,            "khash",            {tag, "1.1.0"}},
-{snappy,           "snappy",           {tag, "CouchDB-1.0.8"}},
-
-%% Non-Erlang deps
-{docs,             {url, "https://github.com/apache/couchdb-documentation"},
-                   {tag, "3.2.1-1"}, [raw]},
-{fauxton,          {url, "https://github.com/apache/couchdb-fauxton"},
-                   {tag, "v1.2.8"}, [raw]},
-%% Third party deps
-{folsom,           "folsom",           {tag, "CouchDB-0.8.4"}},
-{hyper,            "hyper",            {tag, "CouchDB-2.2.0-7"}},
-{ibrowse,          "ibrowse",          {tag, "CouchDB-4.4.2-5"}},
-{jiffy,            "jiffy",            {tag, "1.1.1"}},
-{mochiweb,         "mochiweb",         {tag, "v3.0.0"}},
-{meck,             "meck",             {tag, "0.9.2"}},
-{recon,            "recon",            {tag, "2.5.2"}}
-].
 
 WithProper = lists:keyfind(with_proper, 1, CouchConfig) == {with_proper, true}.
 
@@ -170,30 +114,99 @@
         []
 end.
 
-BaseUrl = "https://github.com/apache/".
-
-MakeDep = fun
-    ({AppName, {url, Url}, Version}) ->
-        {AppName, ".*", {git, Url, Version}};
-    ({AppName, {url, Url}, Version, Options}) ->
-        {AppName, ".*", {git, Url, Version}, Options};
-    ({AppName, RepoName, Version}) ->
-        Url = BaseUrl ++ "couchdb-" ++ RepoName ++ ".git",
-        {AppName, ".*", {git, Url, Version}};
-    ({AppName, RepoName, Version, Options}) ->
-        Url = BaseUrl ++ "couchdb-" ++ RepoName ++ ".git",
-        {AppName, ".*", {git, Url, Version}, Options}
-end.
-
 AddConfig = [
     {require_otp_vsn, "23|24|25"},
-    {deps_dir, "src"},
-    {deps, lists:map(MakeDep, DepDescs ++ OptionalDeps)},
-    {sub_dirs, SubDirs},
-    {lib_dirs, ["src"]},
-    {erl_opts, [{i, "../"}, {d, 'COUCHDB_ERLANG_VERSION', VerString}]},
-    {eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]},
-    {plugins, [eunit_plugin]},
+    {deps_error_on_conflict, true},
+    {deps, [
+        {proper, {git, "https://github.com/proper-testing/proper", {ref, "cfc29e7615ec0a93ac0be619d33609c2139b57fd"}}},
+        {config, {git, "https://github.com/jiahuili430/couchdb-config.git", {ref,"0571481ed314c77a6e7e44ec904afa0109860591"}}},
+        {bear, {git, "https://github.com/jiahuili430/couchdb-bear.git", {ref,"da1e52678d628b394d4bf241ccbe410ab90fd1e3"}}},
+        {b64url, {git, "https://github.com/apache/couchdb-b64url.git", {ref, "ef4fca0c8d18b963412fc16f5848e95944977927"}}},
+        {ets_lru, {git, "https://github.com/apache/couchdb-ets-lru.git", {ref, "f1ca157d6f96c9edf343e280709085f9eed1e716"}}},
+        {ibrowse, {git, "https://github.com/apache/couchdb-ibrowse.git", {ref, "a62d4a6d236729e5869842c70447ad46b3409912"}}},
+        {jiffy, {git, "https://github.com/apache/couchdb-jiffy.git", {ref, "9ea1b35b6e60ba21dfd4adbd18e7916a831fd7d4"}}},
+        {mochiweb, {git, "https://github.com/apache/couchdb-mochiweb.git", {ref, "845803a5defa693c546ea7250818f226a52d2891"}}},
+        {meck, {git, "https://github.com/apache/couchdb-meck.git", {ref, "cc47aab4b64a46a5409c1a93353d44a367b41454"}}},
+        {recon, {git, "https://github.com/apache/couchdb-recon", {ref, "34194da6d9f8ed25f274e0ebb098dc9e95bcf547"}}},
+        {khash, {git, "https://github.com/jiahuili430/couchdb-khash", {ref, "4a0e07f7a2870a543510db355d6c2e9c3c1d84b1"}}},
+        {snappy, {git, "https://github.com/jiahuili430/couchdb-snappy.git", {ref, "536286ada94a3aeee6042d047f3a9c369a5f1475"}}},
+        {folsom, {git, "https://github.com/jiahuili430/couchdb-folsom.git", {ref, "87f778c1efb11e9caebba328a2cba05453db668c"}}},
+        {hyper, {git, "https://github.com/jiahuili430/couchdb-hyper.git", {ref, "69fa387bc9cd67dbe2f4649b4ebd2239e879f239"}}}
+    ]},
+    {plugins, [ic, erlfmt, rebar3_path_deps]},
+    {erlfmt, [write]},
+    {erl_opts, [
+        {i, "../"},
+        {i, "src/couch_tests/include"},
+        {i, "src/mochiweb/include"},
+        {i, "src/rexi/include"},
+        {i, "src/proper/include"},
+        {i, "src/folsom/include"},
+        {i, "src/mem3/include"},
+        {i, "src/couch_mrview/include"},
+        {i, "src/couch/include"},
+        {i, "src/couch_replicator/include"},
+        {i, "src/meck/test/include"},
+        {i, "src/couch_log/include"},
+        {i, "src/dreyfus/include"},
+        {i, "src/chttpd/include"},
+        {i, "src/ibrowse/include"},
+        {i, "src/fabric/include"},
+        {d, 'COUCHDB_ERLANG_VERSION', VerString}
+    ]},
+    {eunit_opts, [
+        verbose,
+        {report, {eunit_progress, [colored, profile]}},
+        {report, {eunit_surefire, [{dir, "_build/test"}]}}
+    ]},
+    {project_app_dirs, ["src/*"]},
+    {eunit_tests, [
+        %{application, b64url},
+        {application, chttpd},
+        %{application, config},
+        {application, couch_dist},
+        {application, couch_event},
+        {application, couch_index},
+        {application, couch_log},
+        {application, couch_mrview},
+        {application, couch_peruser},
+        {application, couch_plugins},
+        {application, couch_prometheus},
+        {application, couch_pse_tests},
+        {application, couch_replicator},
+        {application, couch_stats},
+        {application, couch_tests},
+        {application, couch},
+        {application, custodian},
+        {application, ddoc_cache},
+        {application, dreyfus},
+        %{application, ets_lru},
+        {application, fabric},
+        {application, global_changes},
+        {application, ioq},
+        %{application, jiffy},
+        {application, jwtf},
+        {application, ken},
+        %{application, khash},
+        {application, mango},
+        {application, mem3},
+        %{application, recon},
+        {application, rexi},
+        {application, setup},
+        {application, smoosh},
+        {application, weatherreport},
+        {application, couch_epi}
+    ]},
+    {profiles, [{test, [
+        {extra_src_dirs, [{"test", [{recursive, true}]}]},
+        {deps, [
+            % {b64url, {git, "https://github.com/apache/couchdb-b64url.git", {ref, "ef4fca0c8d18b963412fc16f5848e95944977927"}}},
+            % {ets_lru, {git, "https://github.com/apache/couchdb-ets-lru.git", {ref, "f1ca157d6f96c9edf343e280709085f9eed1e716"}}},
+            % {jiffy, {git, "https://github.com/apache/couchdb-jiffy.git", {ref, "9ea1b35b6e60ba21dfd4adbd18e7916a831fd7d4"}}},
+            % {config, {git, "https://github.com/jiahuili430/couchdb-config.git", {ref,"0571481ed314c77a6e7e44ec904afa0109860591"}}},
+            % {khash, {git, "https://github.com/jiahuili430/couchdb-khash", {ref, "ee87ab0c6bedf0b2b859a867afe5a4ce0ef422a2"}}}
+        ]}
+    ]}]},
     {dialyzer, [
         {plt_location, local},
         {plt_location, COUCHDB_ROOT},
@@ -201,7 +214,86 @@
             asn1, compiler, crypto, inets, kernel, runtime_tools,
             sasl, setup, ssl, stdlib, syntax_tools, xmerl]},
         {warnings, [unmatched_returns, error_handling, race_conditions]}]},
-    {post_hooks, [{compile, "escript support/build_js.escript"}]}
+    {post_hooks, [{compile, "escript support/build_js.escript"}]},
+    {relx, [
+        {release, {couchdb, "3.2.2"}, [
+            %% stdlib
+            asn1,
+            compiler,
+            crypto,
+            inets,
+            runtime_tools,
+            sasl,
+            ssl,
+            syntax_tools,
+            xmerl,
+
+            %% couchdb
+            b64url,
+            bear,
+            chttpd,
+            config,
+            couch,
+            couch_epi,
+            couch_index,
+            couch_log,
+            couch_mrview,
+            couch_plugins,
+            couch_replicator,
+            couch_stats,
+            couch_tests,
+            couch_event,
+            couch_peruser,
+            couch_dist,
+            custodian,
+            ddoc_cache,
+            dreyfus,
+            ets_lru,
+            fabric,
+            folsom,
+            global_changes,
+            hyper,
+            ibrowse,
+            ioq,
+            jiffy,
+            jwtf,
+            ken,
+            khash,
+            mango,
+            mem3,
+            mochiweb,
+            rexi,
+            setup,
+            smoosh,
+            snappy,
+            weatherreport,
+            couch_prometheus,
+
+            %% extra
+            recon,
+            triq
+        ]},
+
+        {mode, prod},
+        {overlay_vars, "rel/couchdb.config"},
+        {sys_config, "rel/files/sys.config"},
+        {vm_args, "rel/files/vm.args"},
+
+        {overlay, [
+            {copy, "LICENSE", "LICENSE"},
+            {mkdir, "var/log"},
+            {copy, "rel/overlay/bin", "bin"},
+            {copy, "rel/overlay/etc", "etc"},
+            {copy, "bin/couchjs", "bin/couchjs"},
+            {copy, "share/server/main.js", "share/server/main.js"},
+            {copy, "share/server/main-coffee.js", "share/server/main-coffee.js"},
+            {copy, "bin/weatherreport", "bin/weatherreport"},
+            {template, "rel/overlay/etc/default.ini", "etc/default.ini"},
+            {template, "rel/overlay/etc/vm.args", "etc/vm.args"},
+            {template, "rel/files/couchdb.in", "bin/couchdb"},
+            {template, "rel/files/couchdb.cmd.in", "bin/couchdb.cmd"}
+        ]}
+    ]}
 ].
 
 lists:foldl(fun({K, V}, CfgAcc) ->
diff --git a/src/couch/include/couch_eunit.hrl b/src/couch/include/couch_eunit.hrl
index 1885248..d8e96fa 100644
--- a/src/couch/include/couch_eunit.hrl
+++ b/src/couch/include/couch_eunit.hrl
@@ -32,7 +32,19 @@
 -define(TEMPDIR,
     filename:join([?BUILDDIR(), "tmp", "tmp_data"])).
 
--define(APPDIR, filename:dirname(element(2, file:get_cwd()))).
+
+%% Rebar3 doesn't change the current directory
+%% Therefore the only way to get the directory of current app
+%% is to construct it from ?FILE
+%% we iterate backwards and remove elements until we find "test"
+%% then remove "test" entry by calling `filename:dirname/`
+-define(APPDIR, filename:dirname(
+    filename:join(
+        lists:reverse(
+            lists:dropwhile(
+                fun(E) -> E =/= "test" end,
+                lists:reverse(filename:split(?FILE))))))).
+
 %% Account for the fact that source files are in src/<app>/.eunit/<module>.erl
 %% when run from eunit
 -define(ABS_PATH(File), %% src/<app>/.eunit/<module>.erl
diff --git a/src/couch/rebar.config.script b/src/couch/rebar.config.script
index ba907b0..9ba8f18 100644
--- a/src/couch/rebar.config.script
+++ b/src/couch/rebar.config.script
@@ -90,11 +90,11 @@
 
 CouchJSConfig = case SMVsn of
     "78" ->
-        "priv/couch_js/86/config.h";
+        APP_DIR ++ "/priv/couch_js/86/config.h";
     "91" ->
-        "priv/couch_js/86/config.h";
+        APP_DIR ++ "/priv/couch_js/86/config.h";
     _ ->
-        "priv/couch_js/" ++ SMVsn ++ "/config.h"
+        APP_DIR ++ "/priv/couch_js/" ++ SMVsn ++ "/config.h"
 end.
 ConfigSrc = [["#define ", K, " ", V, $\n] || {K, V} <- ConfigH].
 ConfigBin = iolist_to_binary(ConfigSrc).
@@ -210,7 +210,7 @@
 ].
 
 SpawnSpec = [
-    {"priv/couchspawnkillable", ["priv/spawnkillable/*.c"]}
+    {APP_DIR ++ "/priv/couchspawnkillable", [APP_DIR ++ "/priv/spawnkillable/*.c"]}
 ].
 
 %% hack required until switch to enc/rebar3
@@ -223,16 +223,49 @@
     {win32, _} ->
         BaseSpecs ++ SpawnSpec;
     _ ->
-        {ok, CSK} = file:read_file("priv/spawnkillable/couchspawnkillable.sh"),
-        ok = CopyIfDifferent("priv/couchspawnkillable", CSK),
-        os:cmd("chmod +x priv/couchspawnkillable"),
+        {ok, CSK} = file:read_file(APP_DIR ++ "/priv/spawnkillable/couchspawnkillable.sh"),
+        ok = CopyIfDifferent(APP_DIR ++ "/priv/couchspawnkillable", CSK),
+        os:cmd("chmod +x " ++ APP_DIR ++ "/priv/couchspawnkillable"),
         BaseSpecs
 end.
 PlatformDefines = [
    {platform_define, "win32", 'WINDOWS'}
 ].
+
+LibDir = "../../_build/default/lib/".
+
 AddConfig = [
     {port_specs, PortSpecs},
+    {plugins, [rebar3_path_deps]},
+    {deps, [
+        {config, {path, LibDir ++ "config"}},
+        {proper, {path, LibDir ++ "proper"}},
+        {bear, {path, LibDir ++ "bear"}},
+        {b64url, {path, LibDir ++ "b64url"}},
+        {ets_lru, {path, LibDir ++ "ets_lru"}},
+        {ibrowse, {path, LibDir ++ "ibrowse"}},
+        {jiffy, {path, LibDir ++ "jiffy"}},
+        {mochiweb, {path, LibDir ++ "mochiweb"}},
+        {meck, {path, LibDir ++ "meck"}},
+        {recon, {path, LibDir ++ "recon"}},
+        {khash, {path, LibDir ++ "khash"}},
+        {snappy, {path, LibDir ++ "snappy"}},
+        {folsom, {path, LibDir ++ "folsom"}},
+        {hyper, {path, LibDir ++ "hyper"}}
+    ]},
+    {profiles, [{test, [
+        {extra_src_dirs, [{"test", [{recursive, true}]}]},
+        {deps, [
+            {b64url, {path, LibDir ++ "b64url"}},
+            {ets_lru, {path, LibDir ++ "ets_lru"}},
+            {jiffy, {path, LibDir ++ "jiffy"}},
+            {config, {path, LibDir ++ "config"}},
+            {khash, {path, LibDir ++ "khash"}}
+        ]}
+    ]}]},
+    {eunit_tests, [
+        {application, config}
+    ]},
     {erl_opts, PlatformDefines ++ [
         {d, 'COUCHDB_VERSION', Version},
         {d, 'COUCHDB_GIT_SHA', GitSha},
diff --git a/src/couch/test/eunit/couch_ejson_compare_tests.erl b/src/couch/test/eunit/couch_ejson_compare_tests.erl
index ae4a5ff..2ac1695 100644
--- a/src/couch/test/eunit/couch_ejson_compare_tests.erl
+++ b/src/couch/test/eunit/couch_ejson_compare_tests.erl
@@ -51,6 +51,8 @@
     {[{<<"b">>, 2}, {<<"c">>, 2}]}
 ]).
 
+-include_lib("eunit/include/eunit.hrl").
+
 % Propery tests
 
 -ifdef(WITH_PROPER).