anchor.diff:  ignore_dir(_Sub, _Ignorable) ->
       false.
   
  -%%--------------------------------------------------------------------
   %% @doc
   %%  If any dirs in the list are ignorable ignore it
  -%% @spec ([H | T], Igs) -> ok
  -%% @end
  -%%--------------------------------------------------------------------
  -are_dirs_ignorable([H | T], Igs) ->
  -    case is_dir_ignorable(H, Igs) of
  -        false ->
  -            are_dirs_ignorable(T, Igs);
  -        true ->
  -            true
  +%% @end
  +-spec are_dirs_ignorable(ListOfDirs::[string()], Igs::[string()]) -> boolean().
  +are_dirs_ignorable([Dir | RestOfDirs], Igs) ->
  +    case is_dir_ignorable(Dir, Igs) of
  +	false ->
  +	    are_dirs_ignorable(RestOfDirs, Igs);
  +	true ->
  +	    true
       end;
   are_dirs_ignorable([], _Igs) ->
       false.
   
  -%%-------------------------------------------------------------------
   %% @doc
   %%   find "_build.cfg" in the current directory. if not recurse
   %%   with parent directory.
  -%% @spec (Dir::string()) -> ok
  -%% @end
  -%% @private
  -%%-------------------------------------------------------------------
  -find_project_root("/") ->
  -    throw(no_build_config);
  +%% @end
  +-spec find_project_root(Dir::string()) -> string().
   find_project_root(Start) ->
       ConfigFile1 = filename:join(Start, "_build.cfg"),
       ConfigFile2 = filename:join(Start, "sinan.cfg"),
       case file:read_file_info(ConfigFile1) of
  -        {ok, _FileInfo} ->
  -            Start;
  -        {error, _Reason} ->
  -            case file:read_file_info(ConfigFile2) of
  -                {ok, _FileInfo} ->
  -                    Start;
  -                {error, _Reason} ->
  -                    find_project_root(sin_utils:parent_dir(Start))
  -            end
  -    end.
  -%%-------------------------------------------------------------------
  -%% @doc
  -%% convert a list body to a list
  -%% @spec (I::term(), Acc::list()) -> list()
  -%% @end
  -%% @private
  -%%-------------------------------------------------------------------
  +      {ok, _FileInfo} ->
  +	    Start;
  +	{error, _Reason} ->
  +	    case file:read_file_info(ConfigFile2) of
  +		{ok, _FileInfo} ->
  +		    Start;
  +		{error, _Reason} ->
  +		    find_project_root(parent_dir(Start))
  +	    end
  +    end.
  +
  +%% @doc
  +%% convert a list body to a string
  +%% @end
  +-spec listify_list_body(I::term(), Acc::list()) -> list().
   listify_list_body([H | T], []) ->
       listify_list_body(T, term_to_list(H));
   listify_list_body([H | T], Acc) ->
  
positive.code: to_bool(_) ->
      false.
  
  %%-------------------------------------------------------------------
  %% @doc
  %%  Get the ignore dirs
  %%
  %% @spec (BuildRef) -> IgnoreDirs
  %% @end
  %%-------------------------------------------------------------------
  get_ignore_dirs(BuildRef) ->
      BuildDir = sin_build_config:get_value(BuildRef, "build.dir"),
      IgnoreDirs = sin_build_config:get_value(BuildRef, "ignore_dirs", []),
      [BuildDir | IgnoreDirs].
  
  %%-------------------------------------------------------------------
  %% @doc
  %%  Check to see if a file exists.
  %%
  %% @spec (FileName) -> true | false
  %% @end
  %%-------------------------------------------------------------------
  file_exists(FileName) ->
      case file:read_file_info(FileName) of
          {error, enoent} ->
              false;
          Error = {error, _} ->
              throw(Error);
          _ ->
              true
      end.
  
  
  
  %%-------------------------------------------------------------------
  %% @doc
  %%  Copies the specified directory down to the build
  %%  dir on a file by file basis. It only copies if the file has .
  %% @spec (BuilderDir, TargetDir, Subdirs) -> ok
  %% @end
  %%-------------------------------------------------------------------
  copy_dir(BuildDir, TargetDir, Sub) ->
      copy_dir(BuildDir, TargetDir, Sub, []).
  
  copy_dir(BuildDir, TargetDir) ->
      copy_dir(BuildDir, TargetDir, [], []).
  
  
  copy_dir(BuildDir, TargetDir, SubDir, Ignorables) ->
      check_not_circular(BuildDir, TargetDir, SubDir),
      case are_dirs_ignorable(SubDir, Ignorables) of
          true ->
              ok;
          false ->
              Target = filename:join([BuildDir | SubDir]),
              filelib:ensure_dir(filename:join([Target, "tmp"])),
              CpyTarget = filename:join([TargetDir | SubDir]),
              {ok, Files} = file:list_dir(CpyTarget),
              lists:foldl(fun(IFile, _Acc) ->
                                  File = filename:join([CpyTarget, IFile]),
                                  case {is_dir_ignorable(IFile, Ignorables),
                                        filelib:is_dir(File)} of
                                      {true, _} ->
                                          ok;
                                      {_, true} ->
                                          copy_dir(BuildDir, TargetDir, SubDir ++
                                                   [IFile], Ignorables);
                                      {_, false} ->
                                          copy_file(Target, IFile, File)
                                  end
                          end, [], Files)
      end.
  
  check_not_circular(Target, Source, SubDir) ->
      case filename:split(Source) ++ SubDir == filename:split(Target) of
  	true ->
  	    ewl_talk:say(
  	      "Can't copy a directory to itself (~p to ~p)",
  	      [filename:join([Source | SubDir]), Target]),
  	    throw(circular_recursion);
  	false ->
  	    ok
      end.
  
  %%-------------------------------------------------------------------
  %% @doc
  %%  Given a directory returns the name of the parent directory.
  %% @spec (Filename) -> DirName | top
  %% @end
  %%-------------------------------------------------------------------
  parent_dir(Filename) ->
      parent_dir(filename:split(Filename), []).
  
  %%-------------------------------------------------------------------
  %% @doc
  %%  Given list of directories, splits the list and returns all
  %% dirs but the last as a path.
  %% @spec (List::list(), Acc::list()) -> DirName | top
  %% @end
  %%-------------------------------------------------------------------
  parent_dir([_H], []) ->
      top;
  parent_dir([], []) ->
      top;
  parent_dir([_H], Acc) ->
      filename:join(lists:reverse(Acc));
  parent_dir([H | T], Acc) ->
      parent_dir(T, [ H | Acc]).
  
  %%--------------------------------------------------------------------
  %% @doc
  %%  Remove the set code paths from the system.
  %% @spec (Paths) -> ok
  %% @end
  %%--------------------------------------------------------------------
  remove_code_paths([Path | T]) ->
      code:del_path(Path),
      remove_code_paths(T);
  remove_code_paths([]) ->
      ok.
  
  %%--------------------------------------------------------------------
  %% @doc
  %%  Return wether the directory is in the list of ignorables. If it
  %%  is then return true, otherwise return false.
  %% @spec (Directory, ListOfIgnores) -> true | false
  %% @end
  %% @private
  %%--------------------------------------------------------------------
  is_dir_ignorable(Sub, [Ignore | Rest]) ->
      case ignore_dir(Sub, Ignore) of
          true ->
              true;
          false ->
              is_dir_ignorable(Sub, Rest)
      end;
  is_dir_ignorable(_Sub, []) ->
      false.
  
  
  
  %%====================================================================
  %% Internal functions
  %%====================================================================
  %%-------------------------------------------------------------------
  %% @doc
  %%  Copies the file specified by file to the target specified by
  %%  ifile.
  %% @spec (Target, IFile, File) -> ok
  %% @end
  %% @private
  %%-------------------------------------------------------------------
  copy_file(_Target, [$. | _], _File) ->
      ok;
  copy_file(Target, IFile, File) ->
      NFile = filename:join([Target, IFile]),
      case sin_sig:target_changed(File, NFile) of
          file_not_found ->
              ewl_talk:say("File ~s is not does not exist in the file "
                           "System. This shouldn't happen.", [File]),
              throw(file_not_on_disc);
          unable_to_access ->
              ewl_talk:say("File ~s exists but is inaccessable.", [File]),
              throw(file_inaccessable);
          true ->
              {ok, FileInfo} = file:read_file_info(File),
              file:copy(File, NFile),
              file:write_file_info(NFile, FileInfo);
          _ ->
              ok
      end.
  
  
  %%--------------------------------------------------------------------
  %% @doc
  %%  Delete the directory and all of its sub directories.
  %% @spec (Dir) -> ok
  %% @end
  %% @private
  %%--------------------------------------------------------------------
  delete_dir(Dir) ->
      case file:list_dir(Dir) of
          {ok, Files} ->
              lists:foldl(fun(File, _Acc) ->
                                  NFile = filename:join([Dir, File]),
                                  case filelib:is_dir(NFile) of
                                      true ->
                                          case is_symlink(NFile) of
                                              true ->
                                                  file:delete(NFile);
                                              false ->
                                                  delete_dir(NFile)
                                          end;
                                      false ->
                                          file:delete(NFile)
                                  end
                          end, [], Files),
              file:del_dir(Dir);
          _ ->
              ok
      end.
  
  
  %%--------------------------------------------------------------------
  %% @doc
  %%  Check to see if the file is a symlink.
  %% @spec (Name) -> true | false
  %% @end
  %%--------------------------------------------------------------------
  is_symlink(Name) ->
      case catch file:read_link_info(Name) of
          {ok, Env} ->
              Env#file_info.type == symlink;
          _Else ->
              false
      end.
  
  %%--------------------------------------------------------------------
  %% @doc
  %%  Check the directory against teh possible ignores to see if the
  %%  prefix matches.
  %% @spec (Directory, PossibleIgnorePrefix) -> true | false
  %% @end
  %% @private
  %%--------------------------------------------------------------------
  ignore_dir([Char | SubRest], [Char | IgRest]) ->
      ignore_dir(SubRest, IgRest);
  ignore_dir(_Sub, []) ->
  
negative.code: 	    ["[", listify_list_body(I, []), "]"]
      end.
  
  -spec is_character(Char::integer()) -> boolean().
  is_character(Char) when Char < 0 ->
      false;
  is_character(Char) when Char > 255 ->
      false;
  is_character(_) ->
      true.
  
  -spec is_string(String::string()) -> boolean().
  is_string(XY) when is_list(XY) ->
      lists:all(fun is_character/1, XY);
  is_string(_) ->
      false.
  
  %% @doc
  %%  Get an enviroment variable, throw error if unavailable.
  %% @end
  -spec get_application_env(atom()) -> term().
  get_application_env(Key) ->
      case application:get_env(sinan, Key) of
  	{ok, Value} ->
  	    Value;
        _ ->
  	    ?SIN_RAISE_DA(variables_not_set,
  			  "Key ~w not set, must be set as application "
  			  "environment variable ",
  			  [Key])
      end.
  
  check_not_circular(Target, Source, SubDir) ->
      case filename:split(Source) ++ SubDir ==
  	filename:split(Target) of
  	true ->
  	    ewl_talk:say("Can't copy a directory to itself (~p "
  			 "to ~p)",
  			 [filename:join([Source | SubDir]), Target]),
  	  throw(circular_recursion);
  	false ->
  	    ok
      end.
  
  %% @doc
  %%  Given a directory returns the name of the parent directory.
  %% @end
  -spec parent_dir(Filename::string()) -> DirName::string().
  parent_dir(Filename) ->
      parent_dir(filename:split(Filename), []).
  
  %% @doc
  %%  Given list of directories, splits the list and returns all
  %% dirs but the last as a path.
  %% @spec (List::list(), Acc::list()) -> DirName.
  %% @end
  parent_dir([_H], []) ->
      throw(no_parent_dir);
  parent_dir([], []) ->
      throw(no_parent_dir);
  parent_dir([_H], Acc) ->
      filename:join(lists:reverse(Acc));
  parent_dir([H | T], Acc) ->
      parent_dir(T, [H | Acc]).
  
  %%====================================================================
  %% tests
  