summaryrefslogtreecommitdiff
path: root/src/couchdb/couch_config_writer.erl
diff options
context:
space:
mode:
authorJan Lehnardt <jan@apache.org>2008-08-20 14:18:05 +0000
committerJan Lehnardt <jan@apache.org>2008-08-20 14:18:05 +0000
commit83af9a01292b5324de651ed90199f61be8d9eae7 (patch)
treecce4408d58132b37f620e033ccc0c2fac57d93ae /src/couchdb/couch_config_writer.erl
parent4700dd67f03c020c3799a4bf161eadfacbf420cb (diff)
add missing files
git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@687339 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/couchdb/couch_config_writer.erl')
-rw-r--r--src/couchdb/couch_config_writer.erl147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/couchdb/couch_config_writer.erl b/src/couchdb/couch_config_writer.erl
new file mode 100644
index 00000000..6e93c131
--- /dev/null
+++ b/src/couchdb/couch_config_writer.erl
@@ -0,0 +1,147 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+%% @doc Saves a Key/Value pair to a ini file. The Key consists of a Module
+%% and Variable combination. If that combination is found in the ini file
+%% the new value replaces the old value. If only the Module is found the
+%% Variable and value combination is appended to the Module. If the Module
+%% does not yet exist in the ini file, it is added and the Variable/Value
+%% pair is appended.
+%% @see couch_config
+
+-module(couch_config_writer).
+-include("couch_db.hrl").
+
+-export([save_to_file/2]).
+
+%% @spec save_to_file(
+%% Config::{{Module::string(), Variable::string()}, Value::string()},
+%% File::filename()) -> ok
+%% @doc Saves a Module/Key/Value triple to the ini file File::filename()
+save_to_file({{Module, Variable}, Value}, File) ->
+
+ ?LOG_DEBUG("saving to file '~s', Congif: '~p'", [File, {{Module, Variable}, Value}]),
+
+ % open file and create a list of lines
+ {ok, Stream} = file:read_file(File),
+ OldFileContents = binary_to_list(Stream),
+ {ok, Lines} = regexp:split(OldFileContents, "\r\n|\n|\r|\032"),
+
+ % prepare input variables
+ ModuleName = "[" ++ Module ++ "]",
+ VariableList = Variable,
+
+ % produce the contents for the config file
+ NewFileContents =
+ case NewFileContents2 = save_loop({{ModuleName, VariableList}, Value}, Lines, "", "", []) of
+ % we didn't change anything, that means we couldn't find a matching
+ % [ini section] in which case we just append a new one.
+ OldFileContents ->
+ append_new_ini_section({{ModuleName, VariableList}, Value}, OldFileContents);
+ _ ->
+ NewFileContents2
+ end,
+
+ % do the save, close the config file and get out
+ save_file(File, NewFileContents),
+ file:close(Stream),
+ ok.
+
+%% @doc Iterates over the lines of an ini file and replaces or adds a new
+%% configuration directive.
+save_loop({{Module, Variable}, Value}, [Line|Rest], OldCurrentModule, Contents, DoneVariables) ->
+
+ % if we find a new [ini section] (Module), save that for reference
+ NewCurrentModule = parse_module(Line, OldCurrentModule),
+
+ % if the current Module is the one we want to change, try to match
+ % each line with the Variable
+ NewContents = case Module of
+ NewCurrentModule ->
+ % see if the current line matches the variable we want to substitute
+ case parse_variable(Line, Variable, Value) of
+ % nope, return original line
+ nomatch ->
+ DoneVariables2 = DoneVariables,
+ Line;
+ % got em! return new line
+ NewLine ->
+ DoneVariables2 = [Variable|DoneVariables],
+ NewLine
+ end;
+ % if the variable we want to change couldn't be replaced, we append it
+ % in the proper module section
+ OldCurrentModule ->
+ case lists:member(Variable, DoneVariables) of
+ false ->
+ DoneVariables2 = [Variable|DoneVariables],
+ Variable ++ "=" ++ Value ++ "\n" ++ Line;
+ true ->
+ DoneVariables2 = DoneVariables,
+ Line
+ end;
+ % otherwise we just print out the original line
+ _ ->
+ DoneVariables2 = DoneVariables,
+ Line
+ end,
+ % clumsy way to only append a newline character
+ % if the line is not empty. We need this to not
+ % avoid haveing a newline inserted at the top
+ % of the target file each time we save it.
+ Contents2 = case Contents of "" -> ""; _ -> Contents ++ "\n" end,
+
+ % go to next line
+ save_loop({{Module, Variable}, Value}, Rest, NewCurrentModule, Contents2 ++ NewContents, DoneVariables2);
+
+save_loop(_Config, [], _OldModule, NewFileContents, _DoneVariable) ->
+ % we're out of new lines, just return the new file's contents
+ NewFileContents.
+
+append_new_ini_section({{ModuleName, Variable}, Value}, OldFileContents) ->
+ OldFileContents ++ "\n\n" ++ ModuleName ++ "\n" ++ Variable ++ "=" ++ Value ++ "\n".
+
+%% @spec parse_module(Lins::string(), OldModule::string()) -> string()
+%% @doc Tries to match a line against a pattern specifying a ini module or
+%% section ("[Module]"). Returns OldModule if no match is found.
+parse_module(Line, OldModule) ->
+ case regexp:match(Line, "^\\[([a-zA-Z0-9_-]*)\\]$") of
+ nomatch ->
+ OldModule;
+ {error, Error} ->
+ io:format("ini file regex error module: '~s'~n", [Error]),
+ OldModule;
+ {match, Start, Length} ->
+ string:substr(Line, Start, Length)
+ end.
+
+%% @spec parse_variable(Line::string(), Variable::string(), Value::string()) ->
+%% string() | nomatch
+%% @doc Tries to match a variable assignment in Line. Returns nomatch if the
+%% Variable is not found. Returns a new line composed of the Variable and
+%% Value otherwise.
+parse_variable(Line, Variable, Value) ->
+ case regexp:match(Line, "^" ++ Variable ++ "=") of
+ nomatch ->
+ nomatch;
+ {error, Error}->
+ io:format("ini file regex error variable: '~s'~n", [Error]),
+ nomatch;
+ {match, _Start, _Length} ->
+ Variable ++ "=" ++ Value
+ end.
+
+%% @spec save_file(File::filename(), Contents::string()) ->
+%% ok | {error, Reason::string()}
+%% @doc Writes Contents to File
+save_file(File, Contents) ->
+ file:write_file(File, list_to_binary(Contents)). \ No newline at end of file