# # # patch "cmd_netsync.cc" # from [6dc326b08d810bea1b96ca7ce71e96d2fd2c60d7] # to [fe6530a5bb3a02388366873891c07668a6a6c01d] # # patch "lua_hooks.cc" # from [d8d705a6bb25bf199b715cc8e73489bf114b1c36] # to [8b2119a72410c7c5f7f997473c61010f4cb1473a] # # patch "lua_hooks.hh" # from [9908c60aeec1949c6f8d16698ce2132d0120aeb7] # to [e9569a63763815809452a9705e7ed2c2b3a63e66] # # patch "std_hooks.lua" # from [7c97a71fda5accd86188472092e52f812dc848d1] # to [9fd3160c435eff59acc8622875047304e3472b9c] # # patch "tests/netsync_mtn_uri_scheme/__driver__.lua" # from [b31411d665b6aa92f6ae04396930f449f8412e56] # to [8f598b3fd3a7824c8d90a87cedbd91ad8d7fc000] # ============================================================ --- cmd_netsync.cc 6dc326b08d810bea1b96ca7ce71e96d2fd2c60d7 +++ cmd_netsync.cc fe6530a5bb3a02388366873891c07668a6a6c01d @@ -39,30 +39,6 @@ static void static char const ws_internal_db_file_name[] = "mtn.db"; static void -extract_address(options & opts, database & db, - args_vector const & args, utf8 & addr) -{ - if (args.size() >= 1) - { - addr = idx(args, 0); - if (!db.var_exists(default_server_key) || opts.set_default) - { - P(F("setting default server to %s") % addr()); - db.set_var(default_server_key, var_value(addr())); - } - } - else - { - N(db.var_exists(default_server_key), - F("no server given and no default server set")); - var_value addr_value; - db.get_var(default_server_key, addr_value); - addr = utf8(addr_value()); - L(FL("using default server address: %s") % addr()); - } -} - -static void find_key(options & opts, lua_hooks & lua, database & db, @@ -89,67 +65,123 @@ static void } static void -extract_patterns(options & opts, database & db, args_vector const & args, - globish & include_pattern, globish & exclude_pattern, - bool host_is_uri) +build_client_connection_info(options & opts, + lua_hooks & lua, + database & db, + key_store & keys, + netsync_connection_info & info, + bool address_given, + bool include_or_exclude_given, + bool need_key = true) { - if (args.size() >= 2 || opts.exclude_given) + // Use the default values if needed and available. + if (!address_given) { - E(args.size() >= 2, F("no branch pattern given")); - - include_pattern = globish(args.begin() + 1, args.end()); - exclude_pattern = globish(opts.exclude_patterns); - - if (!db.var_exists(default_include_pattern_key) - || opts.set_default) - { - P(F("setting default branch include pattern to '%s'") % include_pattern); - db.set_var(default_include_pattern_key, var_value(include_pattern())); - } - if (!db.var_exists(default_exclude_pattern_key) - || opts.set_default) - { - P(F("setting default branch exclude pattern to '%s'") % exclude_pattern); - db.set_var(default_exclude_pattern_key, var_value(exclude_pattern())); - } + N(db.var_exists(default_server_key), + F("no server given and no default server set")); + var_value addr_value; + db.get_var(default_server_key, addr_value); + info.client.unparsed = utf8(addr_value()); + L(FL("using default server address: %s") % info.client.unparsed); } - else if (!host_is_uri) + parse_uri(info.client.unparsed(), info.client.u); + if (info.client.u.query.empty() && !include_or_exclude_given) { + // No include/exclude given anywhere, use the defaults. N(db.var_exists(default_include_pattern_key), F("no branch pattern given and no default pattern set")); var_value pattern_value; db.get_var(default_include_pattern_key, pattern_value); - include_pattern = globish(pattern_value()); - L(FL("using default branch include pattern: '%s'") % include_pattern); + info.client.include_pattern = globish(pattern_value()); + L(FL("using default branch include pattern: '%s'") + % info.client.include_pattern); if (db.var_exists(default_exclude_pattern_key)) { db.get_var(default_exclude_pattern_key, pattern_value); - exclude_pattern = globish(pattern_value()); + info.client.exclude_pattern = globish(pattern_value()); } else - exclude_pattern = globish(); - L(FL("excluding: %s") % exclude_pattern); + info.client.exclude_pattern = globish(); + L(FL("excluding: %s") % info.client.exclude_pattern); } -} - -static void -build_client_connection_info(options & opts, - lua_hooks & lua, - database & db, - key_store & keys, - utf8 const & addr, - globish const & include, - globish const & exclude, - netsync_connection_info & info, - bool need_key = true) -{ - info.client.include_pattern = include; - info.client.exclude_pattern = exclude; - info.client.unparsed = addr; - parse_uri(info.client.unparsed(), info.client.u); - info.client.use_argv = false; - lua.hook_get_netsync_connect_command(info, - global_sanity.debug_p()); + else if(!info.client.u.query.empty()) + { + N(!include_or_exclude_given, + F("Include/exclude pattern was given both as part of the URL and as a separate argument.")); + + // Pull include/exclude from the query string + char const separator = '/'; + char const negate = '-'; + string const & query(info.client.u.query); + std::vector includes, excludes; + string::size_type begin = 0; + string::size_type end = query.find(separator); + while (begin < query.size()) + { + std::string item = query.substr(begin, end); + if (end == string::npos) + begin = end; + else + { + begin = end+1; + if (begin < query.size()) + end = query.find(separator, begin); + } + + bool is_exclude = false; + if (item.size() >= 1 && item.at(0) == negate) + { + is_exclude = true; + item.erase(0, 1); + } + else if (item.find("include=") == 0) + { + item.erase(0, string("include=").size()); + } + else if (item.find("exclude=") == 0) + { + is_exclude = true; + item.erase(0, string("exclude=").size()); + } + + if (is_exclude) + excludes.push_back(arg_type(item)); + else + includes.push_back(arg_type(item)); + } + info.client.include_pattern = globish(includes); + info.client.exclude_pattern = globish(excludes); + } + + // Maybe set the default values. + if (!db.var_exists(default_server_key) || opts.set_default) + { + P(F("setting default server to %s") % info.client.unparsed()); + db.set_var(default_server_key, var_value(info.client.unparsed())); + } + if (!db.var_exists(default_include_pattern_key) + || opts.set_default) + { + P(F("setting default branch include pattern to '%s'") + % info.client.include_pattern); + db.set_var(default_include_pattern_key, + var_value(info.client.include_pattern())); + } + if (!db.var_exists(default_exclude_pattern_key) + || opts.set_default) + { + P(F("setting default branch exclude pattern to '%s'") + % info.client.exclude_pattern); + db.set_var(default_exclude_pattern_key, + var_value(info.client.exclude_pattern())); + } + + info.client.use_argv = + lua.hook_get_netsync_connect_command(info.client.u, + info.client.include_pattern, + info.client.exclude_pattern, + global_sanity.debug_p(), + info.client.argv); opts.use_transport_auth = lua.hook_use_transport_auth(info.client.u); if (opts.use_transport_auth) { @@ -166,14 +198,24 @@ extract_client_connection_info(options & netsync_connection_info & info, bool need_key = true) { - utf8 addr; - globish inc; - globish exc; - extract_address(opts, db, args, addr); - parse_uri(addr(), info.client.u); - extract_patterns(opts, db, args, inc, exc, !info.client.u.host.empty()); + bool have_address = false; + bool have_include_exclude = false; + if (args.size() >= 1) + { + have_address = true; + info.client.unparsed = idx(args, 0); + } + if (args.size() >= 2 || opts.exclude_given) + { + E(args.size() >= 2, F("no branch pattern given")); + + have_include_exclude = true; + info.client.include_pattern = globish(args.begin() + 1, args.end()); + info.client.exclude_pattern = globish(opts.exclude_patterns); + } build_client_connection_info(opts, lua, db, keys, - addr, inc, exc, info, need_key); + info, have_address, have_include_exclude, + need_key); } CMD(push, "push", "", CMD_REF(network), @@ -276,14 +318,15 @@ CMD(clone, "clone", "", CMD_REF(network) N_("If a revision is given, that's the one that will be checked out. " "Otherwise, it will be the head of the branch supplied. " "If no directory is given, the branch name will be used as directory"), - options::opts::exclude | options::opts::branch | options::opts::revision) + options::opts::branch | options::opts::revision) { if (args.size() < 1 || args.size() > 2 || app.opts.revision_selectors.size() > 1) throw usage(execid); revision_id ident; system_path workspace_dir; - utf8 addr = idx(args, 0); + netsync_connection_info info; + info.client.unparsed = idx(args, 0); N(app.opts.branch_given && !app.opts.branchname().empty(), F("you must specify a branch to clone")); @@ -326,42 +369,17 @@ CMD(clone, "clone", "", CMD_REF(network) db.ensure_open(); - if (!db.var_exists(default_server_key) || app.opts.set_default) - { - P(F("setting default server to %s") % addr); - db.set_var(default_server_key, var_value(addr())); - } - key_store keys(app); project_t project(db); - globish include_pattern(app.opts.branchname()); - globish exclude_pattern(app.opts.exclude_patterns); - netsync_connection_info info; + info.client.include_pattern = globish(app.opts.branchname()); + info.client.exclude_pattern = globish(app.opts.exclude_patterns); build_client_connection_info(app.opts, app.lua, db, keys, - addr, include_pattern, exclude_pattern, - info); + info, true, true); if (app.opts.signing_key() == "") P(F("doing anonymous pull; use -kKEYNAME if you need authentication")); - if (!db.var_exists(default_include_pattern_key) - || app.opts.set_default) - { - P(F("setting default branch include pattern to '%s'") % include_pattern); - db.set_var(default_include_pattern_key, var_value(include_pattern())); - } - - if (app.opts.exclude_given) - { - if (!db.var_exists(default_exclude_pattern_key) - || app.opts.set_default) - { - P(F("setting default branch exclude pattern to '%s'") % exclude_pattern); - db.set_var(default_exclude_pattern_key, var_value(exclude_pattern())); - } - } - // make sure we're back in the original dir so that file: URIs work change_current_working_dir(start_dir); ============================================================ --- lua_hooks.cc d8d705a6bb25bf199b715cc8e73489bf114b1c36 +++ lua_hooks.cc 8b2119a72410c7c5f7f997473c61010f4cb1473a @@ -23,7 +23,6 @@ #include "app_state.hh" #include "file_io.hh" #include "lua_hooks.hh" -#include "netcmd.hh" #include "sanity.hh" #include "vocab.hh" #include "transforms.hh" @@ -609,28 +608,31 @@ bool } bool -lua_hooks::hook_get_netsync_connect_command(netsync_connection_info & info, - bool debug) +lua_hooks::hook_get_netsync_connect_command(uri const & u, + globish const & include_pattern, + globish const & exclude_pattern, + bool debug, + std::vector & argv) { bool cmd = false, exec_ok = false; Lua ll(st); ll.func("get_netsync_connect_command"); - push_uri(info.client.u, ll); + push_uri(u, ll); ll.push_table(); - if (!info.client.include_pattern().empty()) + if (!include_pattern().empty()) { ll.push_str("include"); - ll.push_str(info.client.include_pattern()); + ll.push_str(include_pattern()); ll.set_table(); } - if (!info.client.exclude_pattern().empty()) + if (!exclude_pattern().empty()) { ll.push_str("exclude"); - ll.push_str(info.client.exclude_pattern()); + ll.push_str(exclude_pattern()); ll.set_table(); } @@ -644,63 +646,15 @@ lua_hooks::hook_get_netsync_connect_comm ll.call(2,1); ll.begin(); - - netsync_connection_info info2(info); - info2.client.argv.clear(); - info2.client.use_argv = false; - bool not_use_argv = false; + argv.clear(); while(ll.next()) { std::string s; ll.extract_str(s).pop(); - if (!lua_isnumber(st, -1)) - { - std::string k; - ll.extract_str(k); // do not pop - // can be URI parts, or include/exclude - if (k == "scheme") - info2.client.u.scheme = s; - else if (k == "user") - info2.client.u.user = s; - else if (k == "host") - info2.client.u.host = s; - else if (k == "port") - info2.client.u.port = s; - else if (k == "path") - info2.client.u.path = s; - else if (k == "query") - info2.client.u.query = s; - else if (k == "fragment") - info2.client.u.fragment = s; - else if (k == "include") - info2.client.include_pattern = s; - else if (k == "exclude") - info2.client.exclude_pattern = s; - else - W(F("get_netsync_connect_command hook returned unknown item '%s'") - % k); - - not_use_argv = true; - } - else - { - info2.client.argv.push_back(s); - info2.client.use_argv = true; - } + argv.push_back(s); } - E(!(info2.client.use_argv && not_use_argv), - F("get_netsync_command returned inconsistent data")); - - if (ll.ok()) - { - info = info2; - return true; - } - else - { - return false; - } + return ll.ok() && !argv.empty(); } ============================================================ --- lua_hooks.hh 9908c60aeec1949c6f8d16698ce2132d0120aeb7 +++ lua_hooks.hh e9569a63763815809452a9705e7ed2c2b3a63e66 @@ -26,8 +26,6 @@ struct options; struct globish; struct options; -struct netsync_connection_info; - extern app_state* get_app_state(lua_State *L); class lua_hooks @@ -73,8 +71,11 @@ public: globish const & include, globish const & exclude, rsa_keypair_id & k); - bool hook_get_netsync_connect_command(netsync_connection_info & info, - bool debug); + bool hook_get_netsync_connect_command(uri const & u, + globish const & include_pattern, + globish const & exclude_pattern, + bool debug, + std::vector & argv); bool hook_use_transport_auth(uri const & u); bool hook_get_netsync_read_permitted(std::string const & branch, ============================================================ --- std_hooks.lua 7c97a71fda5accd86188472092e52f812dc848d1 +++ std_hooks.lua 9fd3160c435eff59acc8622875047304e3472b9c @@ -1056,41 +1056,6 @@ function get_netsync_connect_command(uri local argv = nil - local include = {} - local exclude = {} - if uri["query"] then - for ex, pat in string.gmatch(uri["query"], "(!?)([^!&]+)") do - if pat and string.len(pat) > 0 then - if ex == "!" then - table.insert(exclude, pat) - else - table.insert(include, pat) - end - end - end - end - - if uri["scheme"] == "mtn" then - local ret = {} - - local inc = table.concat(include, ",") - local exc = table.concat(exclude, ",") - - if inc == "" then - ret.include = "*" - else - ret.include = "{" .. inc .. "}" - end - - if exc == "" then - ret.exclude = "" - else - ret.exclude = "{" .. exc .. "}" - end - - return ret - end - if uri["scheme"] == "ssh" and uri["host"] and uri["path"] then ============================================================ --- tests/netsync_mtn_uri_scheme/__driver__.lua b31411d665b6aa92f6ae04396930f449f8412e56 +++ tests/netsync_mtn_uri_scheme/__driver__.lua 8f598b3fd3a7824c8d90a87cedbd91ad8d7fc000 @@ -15,13 +15,13 @@ srv = netsync.start() srv = netsync.start() -check(mtn2("pull", "mtn://" .. srv.address .. "?branch-te*&!branch-test-*"), 0, false, false) +check(mtn2("pull", "mtn://" .. srv.address .. "?branch-te*/-branch-test-*"), 0, false, false) check(mtn2("ls", "branches"), 0, true) check(not qgrep("^branch$", "stdout")) check( qgrep("^branch-test$", "stdout")) check(not qgrep("^branch-test-exclude$", "stdout")) -check(mtn2("pull", "mtn://" .. srv.address), 0, false, false) +check(mtn2("pull", "mtn://" .. srv.address .. "?include=*"), 0, false, false) check(mtn2("ls", "branches"), 0, true) check(qgrep("^branch$", "stdout")) check(qgrep("^branch-test$", "stdout"))