anchor.diff:                  [] ->
                       ok;
                   _ ->
  -                    ?ERROR("Apps in {rel, ...} section not found by reltool: ~p\n", [Missing]),
  -                    ?FAIL
  +                    ?ABORT("Apps in {rel, ...} section not found by reltool: ~p\n", [Missing])
               end;
           {value, Rel} ->
               %% Invalid release format!
  -            ?ERROR("Invalid {rel, ...} section in reltools.config: ~p\n", [Rel]),
  -            ?FAIL;
  +            ?ABORT("Invalid {rel, ...} section in reltools.config: ~p\n", [Rel]);
           false ->
               ok
       end.
  
positive.code:             ok
      end.
  
  process_rebar_specs([], Spec) ->
      Spec;
  process_rebar_specs([{overlay, Source} | Rest], Spec) ->
      case file:list_dir(Source) of
          {ok, Files} ->
              OverlaySpec = spec_copy_overlay(Files, Source, []),
              process_rebar_specs(Rest, Spec ++ OverlaySpec);
          {error, Reason} ->
              ?ERROR("Failed to list overlay directory ~p: ~p\n", [Source, Reason]),
              ?FAIL
      end;
  process_rebar_specs([{empty_dirs, Dirs} | Rest], Spec) ->
      Spec2 = lists:foldl(fun(Dir, SpecAcc) ->
                                  spec_create_dir(filename:split(Dir), SpecAcc)
                          end, Spec, Dirs),
      process_rebar_specs(Rest, Spec2);
  process_rebar_specs([ Other | Rest], Spec) ->
      ?WARN("Ignoring unknown rebar spec: ~p\n", [Other]),
      process_rebar_specs(Rest, Spec).
  
  
  spec_create_dir([], Spec) ->
      Spec;
  spec_create_dir([Path | Rest], Spec) ->
      case lists:keysearch(Path, 2, Spec) of
          {value, {create_dir, Path, Subspec}} ->
              %% Directory already exists; process down into
              %% Note: this is not tail recursive, but unless the directory structure
              %% is insanely deep, shouldn't be a problem
              lists:keystore(Path, 2, Spec, {create_dir, Path, spec_create_dir(Rest, Subspec)});
          {value, Other} ->
              %% Collision -- something other than create_dir is associated with this
              %% portion of our path name.
              ?ERROR("Collision of path name with existing tuple in spec: ~p\n", [Other]),
              ?FAIL;
          false ->
              %% Directory doesn't yet exist
              [{create_dir, Path, spec_create_dir(Rest, [])} | Spec]
      end.
  
  spec_copy_overlay([], _Dir, Acc) ->
      lists:reverse(Acc);
  spec_copy_overlay([F | Rest], Dir, Acc) ->
      Filename = filename:join(Dir, F),
      {ok, Info} = file:read_file_info(Filename),
      case Info#file_info.type of
          directory ->
              %% If this directory has the special name of "erts-vsn", we are going to replace "vsn" with the
              %% actual erts vsn for the output directory name
              case filename:basename(Filename) of
                  "erts-vsn" -> OutDir = "erts-" ++ erlang:system_info(version);
                  OutDir -> ok
              end,
              {ok, Files} = file:list_dir(Filename),
              Entry = {create_dir, OutDir, spec_copy_overlay(Files, Filename, [])},
              spec_copy_overlay(Rest, Dir, [Entry | Acc]);
          regular ->
              Entry = {copy_file, filename:basename(F), filename:absname(Filename)},
              spec_copy_overlay(Rest, Dir, [Entry | Acc]);
          Other ->
              ?DEBUG("Skipping ~p of type ~p\n", [F, Other]),
              spec_copy_overlay(Rest, Dir, Acc)
      end.
  
  
negative.code:     app_exists(element(1, AppTuple), Server).
  
  
  run_reltool(Server, Config, ReltoolConfig) ->
      case reltool:get_target_spec(Server) of
          {ok, Spec} ->
              %% Pull the target dir and make sure it exists
              TargetDir = target_dir(ReltoolConfig),
              mk_target_dir(TargetDir),
  
              %% Dump the spec, if necessary
              dump_spec(Spec),
  
              %% Have reltool actually run
              case reltool:eval_target_spec(Spec, code:root_dir(), TargetDir) of
                  ok ->
                      ok;
                  {error, Reason} ->
                      ?ABORT("Failed to generate target from spec: ~p\n", [Reason])
              end,
  
              %% Initialize overlay vars with some basics (that can get overwritten)
              OverlayVars0 = [{erts_vsn, "erts-" ++ erlang:system_info(version)}],
  
              %% Load up any variables specified by overlay_vars
              OverlayVars = case overlay_vars(ReltoolConfig) of
                                undefined ->
                                    dict:new(OverlayVars0);
                                File ->
                                    case file:consult(File) of
                                        {ok, Terms} ->
                                            dict:from_list(OverlayVars0 ++ Terms);
                                        {error, Reason2} ->
                                            ?ABORT("Unable to load overlay_vars from ~s: ~p\n",
                                                   [File, Reason2])
                                    end
                            end,
  
              %% Finally, overlay the files specified by the overlay section
              case lists:keysearch(overlay, 1, ReltoolConfig) of
                  {value, {overlay, Overlay}} when is_list(Overlay) ->
                      execute_overlay(Overlay, OverlayVars, rebar_utils:get_cwd(), TargetDir);
                  {value, _} ->
                      ?ABORT("{overlay, [...]} entry in reltool.config must be a list.\n", []);
                  false ->
                      ?INFO("No {overlay, [...]} found in reltool.config.\n", [])
              end;
  
          {error, Reason} ->
              ?ABORT("Unable to generate spec: ~s\n", [Reason])
      end.
  
  
  