Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 99CD31096C for ; Thu, 3 Oct 2013 14:12:12 +0000 (UTC) Received: (qmail 18250 invoked by uid 500); 3 Oct 2013 14:11:28 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 17261 invoked by uid 500); 3 Oct 2013 14:11:10 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 16618 invoked by uid 99); 3 Oct 2013 14:11:03 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 03 Oct 2013 14:11:03 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 156E890E6D8; Thu, 3 Oct 2013 14:11:03 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jan@apache.org To: commits@couchdb.apache.org Date: Thu, 03 Oct 2013 14:11:30 -0000 Message-Id: <6cf2271f7a04494abba6f568aea14e67@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [30/50] [abbrv] git commit: updated refs/heads/1867-feature-plugins to 95d6e35 more comments, add uninstall() Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/f090382d Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/f090382d Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/f090382d Branch: refs/heads/1867-feature-plugins Commit: f090382de56b57aaa452ecfd3b9f5ef9aacd0ee4 Parents: dd83609 Author: Jan Lehnardt Authored: Fri Aug 2 21:16:59 2013 +0200 Committer: Jan Lehnardt Committed: Thu Oct 3 16:08:36 2013 +0200 ---------------------------------------------------------------------- src/couch_plugins/src/couch_plugins.erl | 113 +++++++++++++++++++-------- 1 file changed, 80 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/f090382d/src/couch_plugins/src/couch_plugins.erl ---------------------------------------------------------------------- diff --git a/src/couch_plugins/src/couch_plugins.erl b/src/couch_plugins/src/couch_plugins.erl index 9c2c58f..8b4a22a 100644 --- a/src/couch_plugins/src/couch_plugins.erl +++ b/src/couch_plugins/src/couch_plugins.erl @@ -11,7 +11,7 @@ % the License. -module(couch_plugins). -include("couch_db.hrl"). --export([install/1]). +-export([install/1, uninstall/1]). % couch_plugins:install({"geocouch", "http://127.0.0.1:8000", "1.0.0", [{"R15B03", "+XOJP6GSzmuO2qKdnjO+mWckXVs="}]}). % couch_plugins:install({"geocouch", "http://people.apache.org/~jan/", "couchdb1.2.x_v0.3.0-11-gd83ba22", [{"R15B03", "ZetgdHj2bY2w37buulWVf3USOZs="}]}). @@ -53,30 +53,30 @@ install({Name, _BaseUrl, Version, Checksums}=Plugin) -> % Idempotent uninstall, if you uninstall a non-existant % plugin, you get an `ok`. -% -spec uninstall(string()) -> ok | {error, string()}. -% uninstall(Name) -> -% % unload app -% ok = unload_plugin(Name), -% log("plugin unloaded"), +-spec uninstall(plugin()) -> ok | {error, string()}. +uninstall({Name, _BaseUrl, Version, _Checksums}) -> + % unload app + ok = unload_plugin(Name), + log("plugin unloaded"), -% % unload config -% ok = unload_config(Name), -% log("config unloaded"), + % unload config + ok = unload_config(Name, Version), + log("config unloaded"), -% % delete files -% ok = delete_files(Name), -% log("files deleted"), + % delete files + ok = delete_files(Name, Version), + log("files deleted"), -% % remove code path -% ok = remove_code_path(Name), -% log("removed code path"), + % delete code path + ok = del_code_path(Name, Version), + log("deleted code path"), -% % unregister plugin -% ok = unregister_plugin(Name), -% log("unregistered plugin"), + % unregister plugin + ok = unregister_plugin(Name), + log("unregistered plugin"), -% % done -% ok. + % done + ok. %% * * * @@ -99,30 +99,49 @@ unregister_plugin(Name) -> %% Load Config -%% Pareses /priv/default.d/ and applies -%% the contents to the config system. +%% Parses /priv/default.d/ and applies +%% the contents to the config system, or removes them on uninstall -spec load_config(string(), string()) -> ok. load_config(Name, Version) -> - lists:foreach( - fun load_config_file/1, - filelib:wildcard( - filename:join( - [plugin_dir(), get_file_slug(Name, Version), - "priv", "default.d", "*.ini"]))). - --spec load_config_file(string()) -> ok. -load_config_file(File) -> + loop_config(Name, Version, fun set_config/1). + +-spec unload_config(string(), string()) -> ok. +unload_config(Name, Version) -> + loop_config(Name, Version, fun delete_config/1). + +-spec loop_config(string(), string(), function()) -> ok. +loop_config(Name, Version, Fun) -> + lists:foreach(fun(File) -> load_config_file(File, Fun) end, + filelib:wildcard(file_names(Name, Version))). + +-spec load_config_file(string(), function()) -> ok. +load_config_file(File, Fun) -> {ok, Config} = couch_config:parse_ini_file(File), - lists:foreach(fun set_config/1, Config). + lists:foreach(Fun, Config). -spec set_config({{string(), string()}, string()}) -> ok. set_config({{Section, Key}, Value}) -> - ok = couch_config:set(Section, Key, Value, false). + ok = couch_config:set(Section, Key, Value). + +-spec delete_config({{string(), string()}, _Value}) -> ok. +delete_config({Section, Key}) -> + ok = couch_config:delete(Section, Key). + +-spec file_names(string(), string()) -> string(). +file_names(Name, Version) -> + filename:join( + [plugin_dir(), get_file_slug(Name, Version), + "priv", "default.d", "*.ini"]). %% * * * +%% Code Path Management +%% The Erlang code path is where the Erlang runtime looks for `.beam` +%% files to load on, say, `application:load()`. Since plugin directories +%% are created on demand and named after CouchDB and Erlang versions, +%% we manage the Erlang code path semi-automatically here. -spec add_code_path(string(), string()) -> ok | {error, bad_directory}. add_code_path(Name, Version) -> @@ -134,11 +153,35 @@ add_code_path(Name, Version) -> Else end. +-spec del_code_path(string(), string()) -> ok | {error, atom()}. +del_code_path(Name, Version) -> + PluginPath = plugin_dir() ++ "/" ++ get_file_slug(Name, Version) ++ "/ebin", + case code:del_path(PluginPath) of + true -> ok; + _Else -> + ?LOG_DEBUG("Failed to delete PluginPath: '~s', ignoring", [PluginPath]), + ok + end. + +%% * * * + + +%% Load Plugin +%% This uses `appliction:load()` to load the plugin +%% and `appliction:unload()` to unload the plugin. + -spec load_plugin(string()) -> ok | {error, atom()}. load_plugin(NameList) -> Name = list_to_atom(NameList), application:load(Name). +-spec unload_plugin(string()) -> ok | {error, atom()}. +unload_plugin(NameList) -> + Name = list_to_atom(NameList), + application:unload(Name). + +%% * * * + -spec untargz(string()) -> {ok, string()} | {error, string()}. untargz(Filename) -> @@ -151,6 +194,10 @@ untargz(Filename) -> % untar erl_tar:extract({binary, TarData}, [{cwd, plugin_dir()}, keep_old_files]). +-spec delete_files(string(), string()) -> ok | {error, atom()}. +delete_files(Name, Version) -> + PluginPath = plugin_dir() ++ "/" ++ get_file_slug(Name, Version), + file:del_dir(PluginPath). % downloads a pluygin .tar.gz into a local plugins directory -spec download(string()) -> ok | {error, string()}.