# # # patch "annotate.cc" # from [d359129ebda4db42123b8b92f9effdfdadb2f8f4] # to [d77d991d49e46949e5bde61598ad71d1f9d51c31] # # patch "annotate.hh" # from [c14105693d3c6e7813adc27295e44d2134ef5502] # to [a9fdb38af6e6f80dcd5b29a8b7515c669ea79a24] # # patch "app_state.cc" # from [acb72ad9e75d174d1852467018b8973dd1d53c63] # to [6bdc0540bb924f98d4e366d0f58f9f95c3e4e4b6] # # patch "app_state.hh" # from [1a06d41cacc12454d0a15c912822109b0d242d98] # to [e2fa5664051153ade6613f6b6b6f805ef58e2f3f] # # patch "automate.cc" # from [58f559595f558158d76e5bb03c9884bb8a7681ef] # to [84df2e648eb1da3c631f59838fc698189cfb59c7] # # patch "cert.cc" # from [25b940332f484215c5c5f8f3e44858abe4d70a1f] # to [e6fc84a4286f358f8318eae82958f3fa5463cd06] # # patch "cert.hh" # from [3de66d8aa60bcb14a5fa76a78b21abe24502e52d] # to [23879b52a32842a20191d70bf3581b864669c191] # # patch "cmd.hh" # from [6bd31b3c5f20311811d208ec0255abbd2012c9cb] # to [dcf69b2d51ab109f729076caa76dc7c8762ae432] # # patch "cmd_db.cc" # from [2e9d5f17e51546ec041e857df0c084e2f591ac2a] # to [2675e7d8c564ad00fe6d723220acda3b459e4053] # # patch "cmd_diff_log.cc" # from [6511423a5b72bdba00db61af9d49fcd42ea207db] # to [37997a5ae177947a4779dc0943726cfebcf0244d] # # patch "cmd_files.cc" # from [df0cd6d8b2545d93df4eb70832896212c94c97b0] # to [9ec49f7fd284b014e45e3d3a6054fb4e5ff5b69c] # # patch "cmd_key_cert.cc" # from [7ff053c42f366c5cc0ee8fcc72e92ea7596f9b02] # to [aa0f5995c59032ece0b1ef08acceb51cf4805bde] # # patch "cmd_list.cc" # from [9bc42d7fd78b94a6a5509f63844bd7c86d6ecb99] # to [a2bf9563613a3aa450b88c29c7228dc2a081f0f0] # # patch "cmd_merging.cc" # from [ae9de0a973ad13985c41f2aa6ac22244a5e8653b] # to [329003be23836608a6aad5b8d4479b9c9151e1ca] # # patch "cmd_netsync.cc" # from [a246173f141d20b75f52ac5746a869557eff497e] # to [03efee47f588f807007fc1b739d3e1757d2f824b] # # patch "cmd_othervcs.cc" # from [d3d91faf9411b7cd245353edd2469e0ed48a1614] # to [cad7815967cfa329240476b4264b130912ed8f8d] # # patch "cmd_ws_commit.cc" # from [871fe640df8e15eeb5aa6ee39469e349822d9d08] # to [fcf629639ef904647cb2017e0bd0fe708547851f] # # patch "commands.cc" # from [83b3cbd4dd7fc1fa242b3a7311797449fb88ff14] # to [ec93e333cfa4a79eb4109829de2e94d7b47ac796] # # patch "enumerator.cc" # from [9d7d81efbfa8befe3a150399b2bde472d9e5e3b9] # to [dab80484661f97432593b8cd831ad875ed308869] # # patch "enumerator.hh" # from [c911c8622932915c90e96b53668df5bdd5317c7a] # to [682804347386396f210b558a4daec90cee67a7fb] # # patch "netcmd.hh" # from [7a72dc722db614fd522f07c040cad8be2de3ecfb] # to [b61c27de5390169e5c8abd4f182ae03bf130dafd] # # patch "netsync.cc" # from [e126786acc3d194c84416e6b360fdbc44050ec01] # to [cf1767eaaae71ceec00a977403fcf26eeeca3e3f] # # patch "project.cc" # from [c0f388cd89cd7c7964e0c517a2da9e812d07034e] # to [89c5235c7b7693cdf954b16d594b123fffb970a6] # # patch "project.hh" # from [4dae65adb8451ff22df7ac664e5e45d6b7fefd63] # to [a869324a08efe4894c084eb0d6d30d55ef76b7b1] # # patch "selectors.cc" # from [a63cff13b6230113758688098d9be976db0ea60f] # to [363089ff77762398f45398abe931605d142ac06a] # ============================================================ --- annotate.cc d359129ebda4db42123b8b92f9effdfdadb2f8f4 +++ annotate.cc d77d991d49e46949e5bde61598ad71d1f9d51c31 @@ -58,7 +58,7 @@ public: class annotate_context { public: - annotate_context(file_id fid, project_t & project); + annotate_context(file_id fid, project_set & projects); shared_ptr initial_lineage() const; @@ -85,7 +85,7 @@ private: private: void build_revisions_to_annotations(map & r2a) const; - project_t & project; + project_set & projects; /// keep a count so we can tell quickly whether we can terminate size_t annotated_lines_completed; @@ -206,12 +206,12 @@ typedef multi_index_container< > work_units; -annotate_context::annotate_context(file_id fid, project_t & project) - : project(project), annotated_lines_completed(0) +annotate_context::annotate_context(file_id fid, project_set & projects) + : projects(projects), annotated_lines_completed(0) { // initialize file_lines file_data fpacked; - project.db.get_file_version(fid, fpacked); + projects.db.get_file_version(fid, fpacked); string encoding = constants::default_encoding; // FIXME split_into_lines(fpacked.inner()(), encoding, file_lines); L(FL("annotate_context::annotate_context initialized " @@ -392,8 +392,8 @@ annotate_context::build_revisions_to_ann i != seen.end(); i++) { vector< revision > certs; - project.get_revision_certs(*i, certs); - erase_bogus_certs(certs, project.db); + projects.get_revision_certs(*i, certs); + erase_bogus_certs(certs, projects.db); string author(cert_string_value(certs, author_cert_name, true, false, "@< ")); @@ -816,14 +816,14 @@ void } void -do_annotate (project_t & project, file_t file_node, +do_annotate (project_set & projects, file_t file_node, revision_id rid, bool just_revs) { L(FL("annotating file %s with content %s in revision %s") % file_node->self % file_node->content % rid); shared_ptr - acp(new annotate_context(file_node->content, project)); + acp(new annotate_context(file_node->content, projects)); shared_ptr lineage = acp->initial_lineage(); @@ -832,14 +832,14 @@ do_annotate (project_t & project, file_t { // prepare the first work_unit rev_height height; - project.db.get_rev_height(rid, height); + projects.db.get_rev_height(rid, height); set rids_interesting_ancestors; - get_file_content_marks(project.db, rid, file_node->self, + get_file_content_marks(projects.db, rid, file_node->self, rids_interesting_ancestors); bool rid_marked = (rids_interesting_ancestors.size() == 1 && *(rids_interesting_ancestors.begin()) == rid); if (rid_marked) - project.db.get_revision_parents(rid, rids_interesting_ancestors); + projects.db.get_revision_parents(rid, rids_interesting_ancestors); annotate_node_work workunit(acp, lineage, rid, file_node->self, height, rids_interesting_ancestors, file_node->content, @@ -858,7 +858,7 @@ do_annotate (project_t & project, file_t annotate_node_work work = *w; work_units.erase(w); - do_annotate_node(work, project.db, work_units); + do_annotate_node(work, projects.db, work_units); } acp->annotate_equivalent_lines(); ============================================================ --- annotate.hh c14105693d3c6e7813adc27295e44d2134ef5502 +++ annotate.hh a9fdb38af6e6f80dcd5b29a8b7515c669ea79a24 @@ -13,10 +13,10 @@ #include "vocab.hh" #include "roster.hh" -class project_t; +class project_set; void -do_annotate(project_t & project, file_t file_node, revision_id rid, +do_annotate(project_set & projects, file_t file_node, revision_id rid, bool just_revs); // Local Variables: ============================================================ --- app_state.cc acb72ad9e75d174d1852467018b8973dd1d53c63 +++ app_state.cc 6bdc0540bb924f98d4e366d0f58f9f95c3e4e4b6 @@ -209,29 +209,17 @@ app_state::make_branch_sticky() } } -project_t & -app_state::get_project() +project_set & +app_state::get_projects() { - if (projects.empty()) + // You can't use this until system_path is available, + // which means we need to have the workspace already. + // Need to teach our lua to read directories... + if (!projects) { - map project_definitions; - lua.hook_get_projects(project_definitions); - for (map::const_iterator i = project_definitions.begin(); - i != project_definitions.end(); ++i) - { - projects.insert(make_pair(i->first, - project_t(branch_prefix(i->first), - i->second, - db))); - } - if (projects.empty()) - { - projects.insert(std::make_pair("default", project_t(db))); - } - N(projects.size() == 1, F("multiple projects not supported yet")); + projects.reset(new project_set(db, lua)); } - I(projects.size() == 1); - return projects.begin()->second; + return *projects; } // rc files are loaded after we've changed to the workspace so that ============================================================ --- app_state.hh 1a06d41cacc12454d0a15c912822109b0d242d98 +++ app_state.hh e2fa5664051153ade6613f6b6b6f805ef58e2f3f @@ -60,10 +60,9 @@ private: void make_branch_sticky(); private: - std::map projects; + boost::shared_ptr projects; public: - //project_t & get_project(string const & name); - project_t & get_project(); // get_project(opts.project) or I() + project_set & get_projects(); void set_database(system_path const & filename); void set_key_dir(system_path const & filename); ============================================================ --- automate.cc 58f559595f558158d76e5bb03c9884bb8a7681ef +++ automate.cc 84df2e648eb1da3c631f59838fc698189cfb59c7 @@ -87,8 +87,10 @@ CMD_AUTOMATE(heads, N_("[BRANCH]"), branch_option = branch_name(idx(args, 0)()); } set heads; - app.get_project().get_branch_heads(branch_option, heads, - app.opts.ignore_suspend_certs); + app.get_projects() + .get_project_of_branch(branch_option) + .get_branch_heads(branch_option, heads, + app.opts.ignore_suspend_certs); for (set::const_iterator i = heads.begin(); i != heads.end(); ++i) output << (*i).inner()() << '\n'; @@ -1421,7 +1423,7 @@ CMD_AUTOMATE(packets_for_certs, N_("REVI N(db.revision_exists(r_id), F("no such revision '%s'") % r_id); - app.get_project().get_revision_certs(r_id, certs); + app.get_projects().get_revision_certs(r_id, certs); for (size_t i = 0; i < certs.size(); ++i) pw.consume_revision_cert(idx(certs,i)); } @@ -1588,8 +1590,8 @@ CMD_AUTOMATE(branches, "", set names; - app.get_project().get_branch_list(names, - !app.opts.ignore_suspend_certs); + app.get_projects().get_branch_list(names, + !app.opts.ignore_suspend_certs); for (set::const_iterator i = names.begin(); i != names.end(); ++i) @@ -1656,13 +1658,13 @@ CMD_AUTOMATE(tags, N_("[BRANCH_PATTERN]" prt.print_stanza(stz); set tags; - app.get_project().get_tags(tags); + app.get_projects().get_tags(tags); for (set::const_iterator tag = tags.begin(); tag != tags.end(); ++tag) { set branches; - app.get_project().get_revision_branches(tag->ident, branches); + app.get_projects().get_revision_branches(tag->ident, branches); bool show(!filtering); vector branch_names; ============================================================ --- cert.cc 25b940332f484215c5c5f8f3e44858abe4d70a1f +++ cert.cc e6fc84a4286f358f8318eae82958f3fa5463cd06 @@ -447,7 +447,7 @@ guess_branch(revision_id const & ident, // Does not modify branch state in OPTS. void guess_branch(revision_id const & ident, options & opts, - project_t & project, branch_name & branchname) + project_set & projects, branch_name & branchname) { if (opts.branch_given && !opts.branchname().empty()) branchname = opts.branchname; @@ -458,7 +458,7 @@ guess_branch(revision_id const & ident, "please provide a branch name")); set branches; - project.get_revision_branches(ident, branches); + projects.get_revision_branches(ident, branches); N(branches.size() != 0, F("no branch certs found for revision %s, " @@ -477,10 +477,10 @@ void // As above, but set the branch name in the options // if it wasn't already set. void -guess_branch(revision_id const & ident, options & opts, project_t & project) +guess_branch(revision_id const & ident, options & opts, project_set & projects) { branch_name branchname; - guess_branch(ident, opts, project, branchname); + guess_branch(ident, opts, projects, branchname); opts.branchname = branchname; } ============================================================ --- cert.hh 3de66d8aa60bcb14a5fa76a78b21abe24502e52d +++ cert.hh 23879b52a32842a20191d70bf3581b864669c191 @@ -28,7 +28,7 @@ class database; class key_store; class database; -class project_t; +class project_set; struct options; struct cert @@ -126,10 +126,10 @@ void get_user_key(rsa_keypair_id & key, key_store & keys, database & db); void -guess_branch(revision_id const & id, options & opts, project_t & project, +guess_branch(revision_id const & id, options & opts, project_set & projects, branch_name & branchname); void -guess_branch(revision_id const & id, options & opts, project_t & project); +guess_branch(revision_id const & id, options & opts, project_set & projects); #define date_cert_name cert_name("date") #define author_cert_name cert_name("author") ============================================================ --- cmd.hh 6bd31b3c5f20311811d208ec0255abbd2012c9cb +++ cmd.hh dcf69b2d51ab109f729076caa76dc7c8762ae432 @@ -21,6 +21,7 @@ class project_t; class app_state; class database; class project_t; +class project_set; struct workspace; namespace commands @@ -156,7 +157,7 @@ std::string } std::string -describe_revision(project_t & project, revision_id const & id); +describe_revision(project_set & projects, revision_id const & id); void notify_if_multiple_heads(project_t & project, branch_name const & branchname, ============================================================ --- cmd_db.cc 2e9d5f17e51546ec041e857df0c084e2f591ac2a +++ cmd_db.cc 2675e7d8c564ad00fe6d723220acda3b459e4053 @@ -273,7 +273,7 @@ CMD_HIDDEN(clear_epoch, "clear_epoch", " throw usage(execid); branch_name name(idx(args, 0)()); - branch_uid branch = app.get_project().translate_branch(name); + branch_uid branch = app.get_projects().translate_branch(name); app.db.clear_epoch(branch); } @@ -289,7 +289,7 @@ CMD(db_set_epoch, "set_epoch", "", CMD_R N(ed.inner()().size() == constants::epochlen, F("The epoch must be %s characters") % constants::epochlen); branch_name name(idx(args, 0)()); - branch_uid branch = app.get_project().translate_branch(name); + branch_uid branch = app.get_projects().translate_branch(name); app.db.set_epoch(branch, ed); } @@ -353,7 +353,7 @@ CMD(complete, "complete", "", CMD_REF(in i != completions.end(); ++i) { if (!verbose) cout << i->inner()() << '\n'; - else cout << describe_revision(app.get_project(), *i) << '\n'; + else cout << describe_revision(app.get_projects(), *i) << '\n'; } } else if (idx(args, 0)() == "file") ============================================================ --- cmd_diff_log.cc 6511423a5b72bdba00db61af9d49fcd42ea207db +++ cmd_diff_log.cc 37997a5ae177947a4779dc0943726cfebcf0244d @@ -561,7 +561,7 @@ log_certs(ostream & os, app_state & app, if (multiline) newline = true; - app.get_project().get_revision_certs_by_name(id, name, certs); + app.get_projects().get_revision_certs_by_name(id, name, certs); for (vector< revision >::const_iterator i = certs.begin(); i != certs.end(); ++i) { ============================================================ --- cmd_files.cc df0cd6d8b2545d93df4eb70832896212c94c97b0 +++ cmd_files.cc 9ec49f7fd284b014e45e3d3a6054fb4e5ff5b69c @@ -181,7 +181,7 @@ CMD(annotate, "annotate", "", CMD_REF(in file_t file_node = downcast_to_file_t(node); L(FL("annotate for file_id %s") % file_node->self); - do_annotate(app.get_project(), file_node, rid, app.opts.revs_only); + do_annotate(app.get_projects(), file_node, rid, app.opts.revs_only); } CMD(identify, "identify", "", CMD_REF(debug), N_("[PATH]"), ============================================================ --- cmd_key_cert.cc 7ff053c42f366c5cc0ee8fcc72e92ea7596f9b02 +++ cmd_key_cert.cc aa0f5995c59032ece0b1ef08acceb51cf4805bde @@ -213,7 +213,7 @@ CMD(cert, "cert", "", CMD_REF(key_and_ce val = cert_value(dat()); } - app.get_project().put_cert(app.keys, rid, cname, val); + put_simple_revision_cert(rid, cname, val, app.db, app.keys); guard.commit(); } @@ -308,9 +308,11 @@ CMD(approve, "approve", "", CMD_REF(revi revision_id r; complete(app, idx(args, 0)(), r); - guess_branch(r, app.opts, app.get_project()); + guess_branch(r, app.opts, app.get_projects()); N(app.opts.branchname() != "", F("need --branch argument for approval")); - app.get_project().put_revision_in_branch(app.keys, r, app.opts.branchname); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .put_revision_in_branch(app.keys, r, app.opts.branchname); } CMD(suspend, "suspend", "", CMD_REF(review), N_("REVISION"), @@ -323,9 +325,11 @@ CMD(suspend, "suspend", "", CMD_REF(revi revision_id r; complete(app, idx(args, 0)(), r); - guess_branch(r, app.opts, app.get_project()); + guess_branch(r, app.opts, app.get_projects()); N(app.opts.branchname() != "", F("need --branch argument to suspend")); - app.get_project().suspend_revision_in_branch(app.keys, r, app.opts.branchname); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .suspend_revision_in_branch(app.keys, r, app.opts.branchname); } CMD(comment, "comment", "", CMD_REF(review), N_("REVISION [COMMENT]"), ============================================================ --- cmd_list.cc 9bc42d7fd78b94a6a5509f63844bd7c86d6ecb99 +++ cmd_list.cc a2bf9563613a3aa450b88c29c7228dc2a081f0f0 @@ -66,7 +66,7 @@ CMD(certs, "certs", "", CMD_REF(list), " vector< revision > ts; // FIXME_PROJECTS: after projects are implemented, // use the app.db version instead if no project is specified. - app.get_project().get_revision_certs(ident, ts); + app.get_projects().get_revision_certs(ident, ts); for (size_t i = 0; i < ts.size(); ++i) certs.push_back(idx(ts, i).inner()); @@ -281,8 +281,8 @@ CMD(branches, "branches", "", CMD_REF(li globish exc(app.opts.exclude_patterns); set names; - app.get_project().get_branch_list(inc, names, - !app.opts.ignore_suspend_certs); + app.get_projects().get_branch_list(inc, names, + !app.opts.ignore_suspend_certs); for (set::const_iterator i = names.begin(); i != names.end(); ++i) @@ -301,7 +301,7 @@ CMD(epochs, "epochs", "", CMD_REF(list), if (args.size() == 0) { std::set branches; - app.get_project().get_branch_list(branches); + app.get_projects().get_branch_uids(branches); for (map::const_iterator i = epochs.begin(); i != epochs.end(); ++i) @@ -312,7 +312,7 @@ CMD(epochs, "epochs", "", CMD_REF(list), } else { - branch_name branch = app.get_project().translate_branch(i->first); + branch_name branch = app.get_projects().translate_branch(i->first); cout << i->second << ' ' << branch << '\n'; } } @@ -320,7 +320,7 @@ CMD(epochs, "epochs", "", CMD_REF(list), else { std::set branches; - app.get_project().get_branch_list(branches, false); + app.get_projects().get_branch_list(branches, false); for (args_vector::const_iterator i = args.begin(); i != args.end(); ++i) @@ -328,7 +328,7 @@ CMD(epochs, "epochs", "", CMD_REF(list), branch_name branch((*i)()); N(branches.find(branch) != branches.end(), F("Unknown branch %s") % branch); - branch_uid b = app.get_project().translate_branch(branch); + branch_uid b = app.get_projects().translate_branch(branch); map::const_iterator j = epochs.find(b); N(j != epochs.end(), F("no epoch for branch %s") % *i); cout << j->second << ' ' << j->first << '\n'; @@ -342,7 +342,7 @@ CMD(tags, "tags", "", CMD_REF(list), "", options::opts::depth | options::opts::exclude) { set tags; - app.get_project().get_tags(tags); + app.get_projects().get_tags(tags); for (set::const_iterator i = tags.begin(); i != tags.end(); ++i) { @@ -699,7 +699,7 @@ CMD_AUTOMATE(certs, N_("REV"), vector< revision > ts; // FIXME_PROJECTS: after projects are implemented, // use the db version instead if no project is specified. - app.get_project().get_revision_certs(rid, ts); + app.get_projects().get_revision_certs(rid, ts); for (size_t i = 0; i < ts.size(); ++i) certs.push_back(idx(ts, i).inner()); ============================================================ --- cmd_merging.cc ae9de0a973ad13985c41f2aa6ac22244a5e8653b +++ cmd_merging.cc 329003be23836608a6aad5b8d4479b9c9151e1ca @@ -173,7 +173,8 @@ CMD(update, "update", "", CMD_REF(worksp P(F("updating along branch '%s'") % app.opts.branchname); set candidates; pick_update_candidates(candidates, old_rid, app.opts.branchname, - app.get_project(), + app.get_projects() + .get_project_of_branch(app.opts.branchname), app.opts.ignore_suspend_certs, app.lua); N(!candidates.empty(), F("your request matches no descendents of the current revision\n" @@ -186,7 +187,7 @@ CMD(update, "update", "", CMD_REF(worksp for (set::const_iterator i = candidates.begin(); i != candidates.end(); ++i) P(i18n_format(" %s") - % describe_revision(app.get_project(), *i)); + % describe_revision(app.get_projects(), *i)); P(F("choose one with '%s update -r'") % ui.prog_name); E(false, F("multiple update candidates remain after selection")); } @@ -201,7 +202,7 @@ CMD(update, "update", "", CMD_REF(worksp // do this notification before checking to see if we can bail out early, // because when you are at one of several heads, and you hit update, you // want to know that merging would let you update further. - notify_if_multiple_heads(app.get_project(), + notify_if_multiple_heads(app.get_projects().get_project_of_branch(app.opts.branchname), app.opts.branchname, app.opts.ignore_suspend_certs); if (old_rid == chosen_rid) @@ -360,10 +361,12 @@ merge_two(revision_id const & left, revi transaction_guard guard(app.db); interactive_merge_and_store(left, right, merged, app.db, app.lua); - app.get_project().put_standard_certs_from_options(app.opts, app.lua, - app.keys, - merged, branch, - utf8(log.str())); + app.get_projects() + .get_project_of_branch(branch) + .put_standard_certs_from_options(app.opts, app.lua, + app.keys, + merged, branch, + utf8(log.str())); guard.commit(); if (automate) @@ -391,8 +394,10 @@ CMD(merge, "merge", "", CMD_REF(tree), " F("please specify a branch, with --branch=BRANCH")); set heads; - app.get_project().get_branch_heads(app.opts.branchname, heads, - app.opts.ignore_suspend_certs); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .get_branch_heads(app.opts.branchname, heads, + app.opts.ignore_suspend_certs); N(heads.size() != 0, F("branch '%s' is empty") % app.opts.branchname); if (heads.size() == 1) @@ -460,8 +465,10 @@ CMD(merge, "merge", "", CMD_REF(tree), " ancestors.clear(); heads_for_ancestor.clear(); - app.get_project().get_branch_heads(app.opts.branchname, heads, - app.opts.ignore_suspend_certs); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .get_branch_heads(app.opts.branchname, heads, + app.opts.ignore_suspend_certs); pass++; } @@ -530,21 +537,25 @@ CMD(merge_into_dir, "merge_into_dir", "" if (args.size() != 3) throw usage(execid); - app.get_project().get_branch_heads(branch_name(idx(args, 0)()), src_heads, - app.opts.ignore_suspend_certs); - app.get_project().get_branch_heads(branch_name(idx(args, 1)()), dst_heads, - app.opts.ignore_suspend_certs); + branch_name src_branch(idx(args, 0)()); + branch_name dst_branch(idx(args, 1)()); + project_t & src_project = app.get_projects().get_project_of_branch(src_branch); + project_t & dst_project = app.get_projects().get_project_of_branch(dst_branch); + src_project.get_branch_heads(src_branch, src_heads, + app.opts.ignore_suspend_certs); + dst_project.get_branch_heads(dst_branch, dst_heads, + app.opts.ignore_suspend_certs); - N(src_heads.size() != 0, F("branch '%s' is empty") % idx(args, 0)()); - N(src_heads.size() == 1, F("branch '%s' is not merged") % idx(args, 0)()); + N(src_heads.size() != 0, F("branch '%s' is empty") % src_branch); + N(src_heads.size() == 1, F("branch '%s' is not merged") % src_branch); - N(dst_heads.size() != 0, F("branch '%s' is empty") % idx(args, 1)()); - N(dst_heads.size() == 1, F("branch '%s' is not merged") % idx(args, 1)()); + N(dst_heads.size() != 0, F("branch '%s' is empty") % dst_branch); + N(dst_heads.size() == 1, F("branch '%s' is not merged") % dst_branch); set::const_iterator src_i = src_heads.begin(); set::const_iterator dst_i = dst_heads.begin(); - P(F("propagating %s -> %s") % idx(args,0) % idx(args,1)); + P(F("propagating %s -> %s") % src_branch % dst_branch); P(F("[left] %s") % *src_i); P(F("[right] %s") % *dst_i); @@ -552,16 +563,15 @@ CMD(merge_into_dir, "merge_into_dir", "" if (*src_i == *dst_i || is_ancestor(*src_i, *dst_i, app.db)) { P(F("branch '%s' is up-to-date with respect to branch '%s'") - % idx(args, 1)() % idx(args, 0)()); + % dst_branch % src_branch); P(F("no action taken")); } else if (is_ancestor(*dst_i, *src_i, app.db)) { P(F("no merge necessary; putting %s in branch '%s'") - % (*src_i) % idx(args, 1)()); + % (*src_i) % dst_branch); transaction_guard guard(app.db); - app.get_project().put_revision_in_branch(app.keys, *src_i, - branch_name(idx(args, 1)())); + dst_project.put_revision_in_branch(app.keys, *src_i, dst_branch); guard.commit(); } else @@ -643,14 +653,14 @@ CMD(merge_into_dir, "merge_into_dir", "" if (!log_message_given) log_message = utf8((FL("propagate from branch '%s' (head %s)\n" " to branch '%s' (head %s)\n") - % idx(args, 0) % (*src_i) - % idx(args, 1) % (*dst_i)).str()); + % src_branch % (*src_i) + % dst_branch % (*dst_i)).str()); - app.get_project().put_standard_certs_from_options(app.opts, app.lua, - app.keys, - merged, - branch_name(idx(args, 1)()), - log_message); + dst_project.put_standard_certs_from_options(app.opts, app.lua, + app.keys, + merged, + dst_branch, + log_message); guard.commit(); P(F("[merged] %s") % merged); @@ -1043,8 +1053,10 @@ CMD(heads, "heads", "", CMD_REF(tree), " N(app.opts.branchname() != "", F("please specify a branch, with --branch=BRANCH")); - app.get_project().get_branch_heads(app.opts.branchname, heads, - app.opts.ignore_suspend_certs); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .get_branch_heads(app.opts.branchname, heads, + app.opts.ignore_suspend_certs); if (heads.size() == 0) P(F("branch '%s' is empty") % app.opts.branchname); @@ -1055,7 +1067,7 @@ CMD(heads, "heads", "", CMD_REF(tree), " for (set::const_iterator i = heads.begin(); i != heads.end(); ++i) - cout << describe_revision(app.get_project(), *i) << '\n'; + cout << describe_revision(app.get_projects(), *i) << '\n'; } CMD(get_roster, "get_roster", "", CMD_REF(debug), N_("[REVID]"), ============================================================ --- cmd_netsync.cc a246173f141d20b75f52ac5746a869557eff497e +++ cmd_netsync.cc 03efee47f588f807007fc1b739d3e1757d2f824b @@ -165,7 +165,7 @@ CMD(push, "push", "", CMD_REF(network), run_netsync_protocol(client_voice, source_role, uris, include_pattern, exclude_pattern, - app.get_project(), app.keys, app.lua, app.opts); + app.get_projects(), app.keys, app.lua, app.opts); } CMD(pull, "pull", "", CMD_REF(network), @@ -189,7 +189,7 @@ CMD(pull, "pull", "", CMD_REF(network), run_netsync_protocol(client_voice, sink_role, uris, include_pattern, exclude_pattern, - app.get_project(), app.keys, app.lua, app.opts); + app.get_projects(), app.keys, app.lua, app.opts); } CMD(sync, "sync", "", CMD_REF(network), @@ -211,7 +211,7 @@ CMD(sync, "sync", "", CMD_REF(network), run_netsync_protocol(client_voice, source_and_sink_role, uris, include_pattern, exclude_pattern, - app.get_project(), app.keys, app.lua, app.opts); + app.get_projects(), app.keys, app.lua, app.opts); } class dir_cleanup_helper @@ -331,7 +331,7 @@ CMD(clone, "clone", "", CMD_REF(network) run_netsync_protocol(client_voice, sink_role, uris, include_pattern, exclude_pattern, - app.get_project(), app.keys, app.lua, app.opts); + app.get_projects(), app.keys, app.lua, app.opts); change_current_working_dir(workspace_dir); @@ -344,8 +344,10 @@ CMD(clone, "clone", "", CMD_REF(network) F("use --revision or --branch to specify what to checkout")); set heads; - app.get_project().get_branch_heads(app.opts.branchname, heads, - app.opts.ignore_suspend_certs); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .get_branch_heads(app.opts.branchname, heads, + app.opts.ignore_suspend_certs); N(heads.size() > 0, F("branch '%s' is empty") % app.opts.branchname); if (heads.size() > 1) @@ -353,7 +355,7 @@ CMD(clone, "clone", "", CMD_REF(network) P(F("branch %s has multiple heads:") % app.opts.branchname); for (set::const_iterator i = heads.begin(); i != heads.end(); ++i) P(i18n_format(" %s") - % describe_revision(app.get_project(), *i)); + % describe_revision(app.get_projects(), *i)); P(F("choose one with '%s checkout -r'") % ui.prog_name); E(false, F("branch %s has multiple heads") % app.opts.branchname); } @@ -364,10 +366,12 @@ CMD(clone, "clone", "", CMD_REF(network) // use specified revision complete(app, idx(app.opts.revision_selectors, 0)(), ident); - guess_branch(ident, app.opts, app.get_project()); + guess_branch(ident, app.opts, app.get_projects()); I(!app.opts.branchname().empty()); - N(app.get_project().revision_is_in_branch(ident, app.opts.branchname), + N(app.get_projects() + .get_project_of_branch(app.opts.branchname) + .revision_is_in_branch(ident, app.opts.branchname), F("revision %s is not a member of branch %s") % ident % app.opts.branchname); } @@ -455,7 +459,7 @@ CMD_NO_WORKSPACE(serve, "serve", "", CMD run_netsync_protocol(server_voice, source_and_sink_role, app.opts.bind_uris, globish("*"), globish(""), - app.get_project(), app.keys, app.lua, app.opts); + app.get_projects(), app.keys, app.lua, app.opts); } // Local Variables: ============================================================ --- cmd_othervcs.cc d3d91faf9411b7cd245353edd2469e0ed48a1614 +++ cmd_othervcs.cc cad7815967cfa329240476b4264b130912ed8f8d @@ -55,7 +55,9 @@ CMD(cvs_import, "cvs_import", "", CMD_RE get_user_key(key, app.keys, app.db); require_password(key, app.keys, app.db); - import_cvs_repo(cvsroot, app.keys, app.get_project(), app.opts.branchname); + import_cvs_repo(cvsroot, app.keys, + app.get_projects().get_project_of_branch(app.opts.branchname), + app.opts.branchname); } ============================================================ --- cmd_ws_commit.cc 871fe640df8e15eeb5aa6ee39469e349822d9d08 +++ cmd_ws_commit.cc fcf629639ef904647cb2017e0bd0fe708547851f @@ -347,7 +347,7 @@ CMD(disapprove, "disapprove", "", CMD_RE N(rev.edges.size() == 1, F("revision %s has %d changesets, cannot invert") % r % rev.edges.size()); - guess_branch(r, app.opts, app.get_project()); + guess_branch(r, app.opts, app.get_projects()); N(app.opts.branchname() != "", F("need --branch argument for disapproval")); process_commit_message_args(log_message_given, log_message, app, @@ -374,11 +374,13 @@ CMD(disapprove, "disapprove", "", CMD_RE calculate_ident(rdat, inv_id); app.db.put_revision(inv_id, rdat); - app.get_project().put_standard_certs_from_options(app.opts, app.lua, - app.keys, - inv_id, - app.opts.branchname, - log_message); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .put_standard_certs_from_options(app.opts, app.lua, + app.keys, + inv_id, + app.opts.branchname, + log_message); guard.commit(); } } @@ -594,8 +596,10 @@ CMD(checkout, "checkout", "co", CMD_REF( F("use --revision or --branch to specify what to checkout")); set heads; - app.get_project().get_branch_heads(app.opts.branchname, heads, - app.opts.ignore_suspend_certs); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .get_branch_heads(app.opts.branchname, heads, + app.opts.ignore_suspend_certs); N(heads.size() > 0, F("branch '%s' is empty") % app.opts.branchname); if (heads.size() > 1) @@ -603,7 +607,7 @@ CMD(checkout, "checkout", "co", CMD_REF( P(F("branch %s has multiple heads:") % app.opts.branchname); for (set::const_iterator i = heads.begin(); i != heads.end(); ++i) P(i18n_format(" %s") - % describe_revision(app.get_project(), *i)); + % describe_revision(app.get_projects(), *i)); P(F("choose one with '%s checkout -r'") % ui.prog_name); E(false, F("branch %s has multiple heads") % app.opts.branchname); } @@ -614,11 +618,13 @@ CMD(checkout, "checkout", "co", CMD_REF( // use specified revision complete(app, idx(app.opts.revision_selectors, 0)(), revid); - guess_branch(revid, app.opts, app.get_project()); + guess_branch(revid, app.opts, app.get_projects()); I(!app.opts.branchname().empty()); - N(app.get_project().revision_is_in_branch(revid, app.opts.branchname), + N(app.get_projects() + .get_project_of_branch(app.opts.branchname) + .revision_is_in_branch(revid, app.opts.branchname), F("revision %s is not a member of branch %s") % revid % app.opts.branchname); } @@ -1089,7 +1095,7 @@ CMD(commit, "commit", "ci", CMD_REF(work i++) { // this will prefer --branch if it was set - guess_branch(edge_old_revision(i), app.opts, app.get_project(), + guess_branch(edge_old_revision(i), app.opts, app.get_projects(), bn_candidate); N(branchname() == "" || branchname == bn_candidate, F("parent revisions of this commit are in different branches:\n" @@ -1153,8 +1159,10 @@ CMD(commit, "commit", "ci", CMD_REF(work // for the divergence check, below set heads; - app.get_project().get_branch_heads(app.opts.branchname, heads, - app.opts.ignore_suspend_certs); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .get_branch_heads(app.opts.branchname, heads, + app.opts.ignore_suspend_certs); unsigned int old_head_size = heads.size(); { @@ -1239,11 +1247,13 @@ CMD(commit, "commit", "ci", CMD_REF(work app.db.put_revision(restricted_rev_id, rdat); } - app.get_project().put_standard_certs_from_options(app.opts, app.lua, - app.keys, - restricted_rev_id, - app.opts.branchname, - log_message); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .put_standard_certs_from_options(app.opts, app.lua, + app.keys, + restricted_rev_id, + app.opts.branchname, + log_message); guard.commit(); } @@ -1258,8 +1268,10 @@ CMD(commit, "commit", "ci", CMD_REF(work app.work.blank_user_log(); - app.get_project().get_branch_heads(app.opts.branchname, heads, - app.opts.ignore_suspend_certs); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .get_branch_heads(app.opts.branchname, heads, + app.opts.ignore_suspend_certs); if (heads.size() > old_head_size && old_head_size > 0) { P(F("note: this revision creates divergence\n" "note: you may (or may not) wish to run '%s merge'") @@ -1277,7 +1289,7 @@ CMD(commit, "commit", "ci", CMD_REF(work // later. map certs; vector< revision > ctmp; - app.get_project().get_revision_certs(restricted_rev_id, ctmp); + app.get_projects().get_revision_certs(restricted_rev_id, ctmp); for (vector< revision >::const_iterator i = ctmp.begin(); i != ctmp.end(); ++i) { @@ -1335,11 +1347,13 @@ CMD_NO_WORKSPACE(import, "import", "", C // use specified revision complete(app, idx(app.opts.revision_selectors, 0)(), ident); - guess_branch(ident, app.opts, app.get_project()); + guess_branch(ident, app.opts, app.get_projects()); I(!app.opts.branchname().empty()); - N(app.get_project().revision_is_in_branch(ident, app.opts.branchname), + N(app.get_projects() + .get_project_of_branch(app.opts.branchname) + .revision_is_in_branch(ident, app.opts.branchname), F("revision %s is not a member of branch %s") % ident % app.opts.branchname); } @@ -1350,14 +1364,16 @@ CMD_NO_WORKSPACE(import, "import", "", C F("use --revision or --branch to specify what to checkout")); set heads; - app.get_project().get_branch_heads(app.opts.branchname, heads, - app.opts.ignore_suspend_certs); + app.get_projects() + .get_project_of_branch(app.opts.branchname) + .get_branch_heads(app.opts.branchname, heads, + app.opts.ignore_suspend_certs); if (heads.size() > 1) { P(F("branch %s has multiple heads:") % app.opts.branchname); for (set::const_iterator i = heads.begin(); i != heads.end(); ++i) P(i18n_format(" %s") - % describe_revision(app.get_project(), *i)); + % describe_revision(app.get_projects(), *i)); P(F("choose one with '%s checkout -r'") % ui.prog_name); E(false, F("branch %s has multiple heads") % app.opts.branchname); } ============================================================ --- commands.cc 83b3cbd4dd7fc1fa242b3a7311797449fb88ff14 +++ commands.cc ec93e333cfa4a79eb4109829de2e94d7b47ac796 @@ -853,7 +853,7 @@ string } string -describe_revision(project_t & project, revision_id const & id) +describe_revision(project_set & projects, revision_id const & id) { cert_name author_name(author_cert_name); cert_name date_name(date_cert_name); @@ -864,7 +864,7 @@ describe_revision(project_t & project, r // append authors and date of this revision vector< revision > tmp; - project.get_revision_certs_by_name(id, author_name, tmp); + projects.get_revision_certs_by_name(id, author_name, tmp); for (vector< revision >::const_iterator i = tmp.begin(); i != tmp.end(); ++i) { @@ -873,7 +873,7 @@ describe_revision(project_t & project, r description += " "; description += tv(); } - project.get_revision_certs_by_name(id, date_name, tmp); + projects.get_revision_certs_by_name(id, date_name, tmp); for (vector< revision >::const_iterator i = tmp.begin(); i != tmp.end(); ++i) { ============================================================ --- enumerator.cc 9d7d81efbfa8befe3a150399b2bde472d9e5e3b9 +++ enumerator.cc dab80484661f97432593b8cd831ad875ed308869 @@ -28,13 +28,13 @@ revision_enumerator::revision_enumerator using std::vector; revision_enumerator::revision_enumerator(enumerator_callbacks & cb, - project_t & project) - : cb(cb), project(project) + project_set & projects) + : cb(cb), projects(projects) { revision_id root; revs.push_back(root); - project.db.get_revision_ancestry(graph); + projects.db.get_revision_ancestry(graph); for (multimap::const_iterator i = graph.begin(); i != graph.end(); ++i) { @@ -101,7 +101,7 @@ revision_enumerator::files_for_revision( revision_t rs; MM(rs); - project.db.get_revision(r, rs); + projects.db.get_revision(r, rs); for (edge_map::const_iterator i = rs.edges.begin(); i != rs.edges.end(); ++i) @@ -186,7 +186,7 @@ revision_enumerator::get_revision_certs( hashes.push_back(i->second); } if (!found_one) - project.get_revision_cert_hashes(rid, hashes); + projects.db.get_revision_certs(rid, hashes); } void ============================================================ --- enumerator.hh c911c8622932915c90e96b53668df5bdd5317c7a +++ enumerator.hh 682804347386396f210b558a4daec90cee67a7fb @@ -17,7 +17,7 @@ class database; #include "vocab.hh" class database; -class project_t; +class project_set; // The revision_enumerator struct acts as a cursor which emits files, // deltas, revisions and certs in dependency-correct order. This is @@ -53,7 +53,7 @@ revision_enumerator revision_enumerator { enumerator_callbacks & cb; - project_t & project; + project_set & projects; std::set terminal_nodes; std::set enumerated_nodes; std::deque revs; @@ -71,7 +71,7 @@ public: public: revision_enumerator(enumerator_callbacks & cb, - project_t & project); + project_set & projects); void get_revision_parents(revision_id const & rid, std::vector & parents); void note_cert(revision_id const & rid, ============================================================ --- netcmd.hh 7a72dc722db614fd522f07c040cad8be2de3ecfb +++ netcmd.hh b61c27de5390169e5c8abd4f182ae03bf130dafd @@ -22,7 +22,7 @@ class database; struct globish; class database; -class project_t; +class project_set; class key_store; class lua_hooks; class options; @@ -181,7 +181,7 @@ void run_netsync_protocol(protocol_voice std::list const & addrs, globish const & include_pattern, globish const & exclude_pattern, - project_t & project, + project_set & project, key_store & keys, lua_hooks & lua, options & opts); // Local Variables: ============================================================ --- netsync.cc e126786acc3d194c84416e6b360fdbc44050ec01 +++ netsync.cc cf1767eaaae71ceec00a977403fcf26eeeca3e3f @@ -298,7 +298,7 @@ session: globish our_exclude_pattern; globish_matcher our_matcher; - project_t & project; + project_set & projects; key_store & keys; lua_hooks & lua; bool use_transport_auth; @@ -401,7 +401,7 @@ session: protocol_voice voice, globish const & our_include_pattern, globish const & our_exclude_pattern, - project_t & project, + project_set & projects, key_store & keys, lua_hooks & lua, options & opts, @@ -520,7 +520,7 @@ session::session(protocol_role role, protocol_voice voice, globish const & our_include_pattern, globish const & our_exclude_pattern, - project_t & project, + project_set & projects, key_store & keys, lua_hooks & lua, options & opts, @@ -532,7 +532,7 @@ session::session(protocol_role role, our_include_pattern(our_include_pattern), our_exclude_pattern(our_exclude_pattern), our_matcher(our_include_pattern, our_exclude_pattern), - project(project), + projects(projects), keys(keys), lua(lua), use_transport_auth(opts.use_transport_auth), @@ -572,7 +572,7 @@ session::session(protocol_role role, key_refiner(key_item, voice, *this), cert_refiner(cert_item, voice, *this), rev_refiner(revision_item, voice, *this), - rev_enumerator(*this, project), + rev_enumerator(*this, projects), initiated_by_server(initiated_by_server) {} @@ -629,7 +629,7 @@ session::~session() certs.insert(make_pair(j->key, make_pair(j->name, vtmp))); } revision_data rdat; - project.db.get_revision(*i, rdat); + projects.db.get_revision(*i, rdat); lua.hook_note_netsync_revision_received(*i, rdat, certs, session_id); } @@ -683,7 +683,7 @@ session::note_file_data(file_id const & file_data fd; id item; decode_hexenc(f.inner(), item); - project.db.get_file_version(f, fd); + projects.db.get_file_version(f, fd); queue_data_cmd(file_item, item, fd.inner()()); file_items_sent.insert(f); } @@ -697,7 +697,7 @@ session::note_file_delta(file_id const & id fid1, fid2; decode_hexenc(src.inner(), fid1); decode_hexenc(dst.inner(), fid2); - project.db.get_arbitrary_file_delta(src, dst, fdel); + projects.db.get_arbitrary_file_delta(src, dst, fdel); queue_delta_cmd(file_item, fid1, fid2, fdel.inner()); file_items_sent.insert(dst); } @@ -710,7 +710,7 @@ session::note_rev(revision_id const & re revision_t rs; id item; decode_hexenc(rev.inner(), item); - project.db.get_revision(rev, rs); + projects.db.get_revision(rev, rs); data tmp; write_revision(rs, tmp); queue_data_cmd(revision_item, item, tmp()); @@ -725,7 +725,7 @@ session::note_cert(hexenc const & c) decode_hexenc(c, item); revision cert; string str; - project.db.get_revision_cert(c, cert); + projects.db.get_revision_cert(c, cert); write_cert(cert.inner(), str); queue_data_cmd(cert_item, item, str); } @@ -1305,10 +1305,10 @@ session::process_hello_cmd(rsa_keypair_i key_hash_code(their_keyname, their_key_encoded, their_key_hash); L(FL("server key has name %s, hash %s") % their_keyname % their_key_hash); var_key their_key_key(known_servers_domain, var_name(peer_id)); - if (project.db.var_exists(their_key_key)) + if (projects.db.var_exists(their_key_key)) { var_value expected_key_hash; - project.db.get_var(their_key_key, expected_key_hash); + projects.db.get_var(their_key_key, expected_key_hash); if (expected_key_hash() != their_key_hash()) { P(F("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" @@ -1329,9 +1329,9 @@ session::process_hello_cmd(rsa_keypair_i P(F("first time connecting to server %s\n" "I'll assume it's really them, but you might want to double-check\n" "their key's fingerprint: %s") % peer_id % their_key_hash); - project.db.set_var(their_key_key, var_value(their_key_hash())); + projects.db.set_var(their_key_key, var_value(their_key_hash())); } - if (project.db.put_key(their_keyname, their_key_encoded)) + if (projects.db.put_key(their_keyname, their_key_encoded)) W(F("saving public key for %s to database") % their_keyname); { @@ -1341,7 +1341,7 @@ session::process_hello_cmd(rsa_keypair_i % their_key_hash % hnonce); } - I(project.db.public_key_exists(their_key_hash)); + I(projects.db.public_key_exists(their_key_hash)); // save their identity id their_key_hash_decoded; @@ -1352,7 +1352,7 @@ session::process_hello_cmd(rsa_keypair_i // clients always include in the synchronization set, every branch that the // user requested set all_branches, ok_branches; - project.get_branch_list(all_branches); + projects.get_branch_list(all_branches); for (set::const_iterator i = all_branches.begin(); i != all_branches.end(); i++) { @@ -1373,12 +1373,12 @@ session::process_hello_cmd(rsa_keypair_i // this also ensures our public key is in the database base64 sig; rsa_sha1_signature sig_raw; - keys.make_signature(project.db, signing_key, nonce(), sig); + keys.make_signature(projects.db, signing_key, nonce(), sig); decode_base64(sig, sig_raw); // get the hash identifier for our pubkey base64 our_pub; - project.db.get_key(signing_key, our_pub); + projects.db.get_key(signing_key, our_pub); hexenc our_key_hash; id our_key_hash_raw; key_hash_code(signing_key, our_pub, our_key_hash); @@ -1447,7 +1447,7 @@ session::process_anonymous_cmd(protocol_ } set all_branches, ok_branches; - project.get_branch_list(all_branches); + projects.get_branch_list(all_branches); globish_matcher their_matcher(their_include_pattern, their_exclude_pattern); for (set::const_iterator i = all_branches.begin(); i != all_branches.end(); i++) @@ -1524,14 +1524,14 @@ session::process_auth_cmd(protocol_role globish_matcher their_matcher(their_include_pattern, their_exclude_pattern); - if (!project.db.public_key_exists(their_key_hash)) + if (!projects.db.public_key_exists(their_key_hash)) { // If it's not in the db, it still could be in the keystore if we // have the private key that goes with it. rsa_keypair_id their_key_id; keypair their_keypair; if (keys.maybe_get_key_pair(their_key_hash, their_key_id, their_keypair)) - project.db.put_key(their_key_id, their_keypair.pub); + projects.db.put_key(their_key_id, their_keypair.pub); else { this->saved_nonce = id(""); @@ -1549,7 +1549,7 @@ session::process_auth_cmd(protocol_role // Get their public key. rsa_keypair_id their_id; base64 their_key; - project.db.get_pubkey(their_key_hash, their_id, their_key); + projects.db.get_pubkey(their_key_hash, their_id, their_key); lua.hook_note_netsync_start(session_id, "server", their_role, peer_id, their_id, @@ -1588,7 +1588,7 @@ session::process_auth_cmd(protocol_role } set all_branches, ok_branches; - project.get_branch_list(all_branches); + projects.get_branch_list(all_branches); for (set::const_iterator i = all_branches.begin(); i != all_branches.end(); i++) { @@ -1642,7 +1642,7 @@ session::process_auth_cmd(protocol_role // Check the signature. base64 sig; encode_base64(rsa_sha1_signature(signature), sig); - if (project.db.check_signature(their_id, nonce1(), sig) == cert_ok) + if (projects.db.check_signature(their_id, nonce1(), sig) == cert_ok) { // Get our private key and sign back. L(FL("client signature OK, accepting authentication")); @@ -1827,18 +1827,18 @@ session::data_exists(netcmd_item_type ty { case key_item: return key_refiner.local_item_exists(item) - || project.db.public_key_exists(hitem); + || projects.db.public_key_exists(hitem); case file_item: - return project.db.file_version_exists(file_id(hitem)); + return projects.db.file_version_exists(file_id(hitem)); case revision_item: return rev_refiner.local_item_exists(item) - || project.db.revision_exists(revision_id(hitem)); + || projects.db.revision_exists(revision_id(hitem)); case cert_item: return cert_refiner.local_item_exists(item) - || project.db.revision_cert_exists(hitem); + || projects.db.revision_cert_exists(hitem); case epoch_item: return epoch_refiner.local_item_exists(item) - || project.db.epoch_exists(epoch_id(hitem)); + || projects.db.epoch_exists(epoch_id(hitem)); } return false; } @@ -1863,7 +1863,7 @@ session::load_data(netcmd_item_type type { branch_uid branch; epoch_data epoch; - project.db.get_epoch(epoch_id(hitem), branch, epoch); + projects.db.get_epoch(epoch_id(hitem), branch, epoch); write_epoch(branch, epoch, out); } break; @@ -1871,7 +1871,7 @@ session::load_data(netcmd_item_type type { rsa_keypair_id keyid; base64 pub_encoded; - project.db.get_pubkey(hitem, keyid, pub_encoded); + projects.db.get_pubkey(hitem, keyid, pub_encoded); L(FL("public key '%s' is also called '%s'") % hitem % keyid); write_pubkey(keyid, pub_encoded, out); } @@ -1881,7 +1881,7 @@ session::load_data(netcmd_item_type type { revision_data mdat; data dat; - project.db.get_revision(revision_id(hitem), mdat); + projects.db.get_revision(revision_id(hitem), mdat); out = mdat.inner()(); } break; @@ -1890,7 +1890,7 @@ session::load_data(netcmd_item_type type { file_data fdat; data dat; - project.db.get_file_version(file_id(hitem), fdat); + projects.db.get_file_version(file_id(hitem), fdat); out = fdat.inner()(); } break; @@ -1898,7 +1898,7 @@ session::load_data(netcmd_item_type type case cert_item: { revision c; - project.db.get_revision_cert(hitem, c); + projects.db.get_revision_cert(hitem, c); string tmp; write_cert(c.inner(), out); } @@ -1935,13 +1935,13 @@ session::process_data_cmd(netcmd_item_ty read_epoch(dat, branch, epoch); L(FL("received epoch %s for branch %s") % epoch % branch); map epochs; - project.db.get_epochs(epochs); + projects.db.get_epochs(epochs); map::const_iterator i; i = epochs.find(branch); if (i == epochs.end()) { L(FL("branch %s has no epoch; setting epoch to %s") % branch % epoch); - project.db.set_epoch(branch, epoch); + projects.db.set_epoch(branch, epoch); } else { @@ -1979,7 +1979,7 @@ session::process_data_cmd(netcmd_item_ty throw bad_decode(F("hash check failed for public key '%s' (%s);" " wanted '%s' got '%s'") % hitem % keyid % hitem % tmp); - if (project.db.put_key(keyid, pub)) + if (projects.db.put_key(keyid, pub)) written_keys.push_back(keyid); else error(partial_transfer, @@ -1995,7 +1995,7 @@ session::process_data_cmd(netcmd_item_ty cert_hash_code(c, tmp); if (! (tmp == hitem)) throw bad_decode(F("hash check failed for revision cert '%s'") % hitem); - if (project.db.put_revision_cert(revision(c))) + if (projects.db.put_revision_cert(revision(c))) written_certs.push_back(c); } break; @@ -2003,7 +2003,7 @@ session::process_data_cmd(netcmd_item_ty case revision_item: { L(FL("received revision '%s'") % hitem); - if (project.db.put_revision(revision_id(hitem), revision_data(dat))) + if (projects.db.put_revision(revision_id(hitem), revision_data(dat))) written_revisions.push_back(revision_id(hitem)); } break; @@ -2011,7 +2011,7 @@ session::process_data_cmd(netcmd_item_ty case file_item: { L(FL("received file '%s'") % hitem); - project.db.put_file(file_id(hitem), file_data(dat)); + projects.db.put_file(file_id(hitem), file_data(dat)); } break; } @@ -2039,7 +2039,7 @@ session::process_delta_cmd(netcmd_item_t case file_item: { file_id src_file(hbase), dst_file(hident); - project.db.put_file_version(src_file, dst_file, file_delta(del)); + projects.db.put_file_version(src_file, dst_file, file_delta(del)); } break; @@ -2402,7 +2402,7 @@ call_server(protocol_role role, call_server(protocol_role role, globish const & include_pattern, globish const & exclude_pattern, - project_t & project, + project_set & projects, key_store & keys, lua_hooks & lua, options & opts, @@ -2411,7 +2411,7 @@ call_server(protocol_role role, unsigned long timeout_seconds) { Netxx::PipeCompatibleProbe probe; - transaction_guard guard(project.db); + transaction_guard guard(projects.db); I(addresses.size() == 1); utf8 address(*addresses.begin()); @@ -2435,7 +2435,7 @@ call_server(protocol_role role, session sess(role, client_voice, include_pattern, exclude_pattern, - project, keys, lua, opts, address(), server); + projects, keys, lua, opts, address(), server); while (true) { @@ -2600,7 +2600,7 @@ handle_new_connection(Netxx::Address & a globish const & include_pattern, globish const & exclude_pattern, map > & sessions, - project_t & project, key_store & keys, + project_set & projects, key_store & keys, lua_hooks & lua, options & opts) { L(FL("accepting new connection on %s : %s") @@ -2627,7 +2627,7 @@ handle_new_connection(Netxx::Address & a shared_ptr sess(new session(role, server_voice, include_pattern, exclude_pattern, - project, keys, lua, opts, + projects, keys, lua, opts, lexical_cast(client), str)); sess->begin_service(); sessions.insert(make_pair(client.get_socketfd(), sess)); @@ -2769,7 +2769,7 @@ serve_connections(protocol_role role, serve_connections(protocol_role role, globish const & include_pattern, globish const & exclude_pattern, - project_t & project, + project_set & projects, key_store & keys, lua_hooks & lua, options & opts, @@ -2806,7 +2806,8 @@ serve_connections(protocol_role role, addr.add_all_addresses(default_port); else { - for (std::list::const_iterator it = addresses.begin(); it != addresses.end(); ++it) + for (std::list::const_iterator it = addresses.begin(); + it != addresses.end(); ++it) { const utf8 & address = *it; if (!address().empty()) @@ -2864,7 +2865,7 @@ serve_connections(protocol_role role, if (!guard) guard = shared_ptr - (new transaction_guard(project.db)); + (new transaction_guard(projects.db)); I(guard); @@ -2902,7 +2903,7 @@ serve_connections(protocol_role role, shared_ptr sess(new session(role, client_voice, inc, exc, - project, keys, + projects, keys, lua, opts, addr(), server, true)); @@ -2914,7 +2915,8 @@ serve_connections(protocol_role role, } } - arm_sessions_and_calculate_probe(probe, sessions, armed_sessions, *guard); + arm_sessions_and_calculate_probe(probe, sessions, + armed_sessions, *guard); L(FL("i/o probe with %d armed") % armed_sessions.size()); Netxx::socket_type fd; @@ -2943,7 +2945,7 @@ serve_connections(protocol_role role, else if (fd == server) handle_new_connection(addr, server, timeout, role, include_pattern, exclude_pattern, - sessions, project, keys, + sessions, projects, keys, lua, opts); // or an existing session woke up @@ -3042,7 +3044,7 @@ serve_single_connection(shared_ptrbegin_service(); - transaction_guard guard(sess->project.db); + transaction_guard guard(sess->projects.db); map > sessions; set armed_sessions; @@ -3172,7 +3174,9 @@ session::rebuild_merkle_trees(setproject).get_branch_certs(i->branch) // or so. - project.get_branch_certs(*i, certs); + projects + .get_project_of_branch(*i) + .get_branch_certs(*i, certs); for (vector< revision >::const_iterator j = certs.begin(); j != certs.end(); j++) { @@ -3194,13 +3198,13 @@ session::rebuild_merkle_trees(set epochs; - project.db.get_epochs(epochs); + projects.db.get_epochs(epochs); epoch_data epoch_zero(string(constants::epochlen, '0')); for (set::const_iterator i = branchnames.begin(); i != branchnames.end(); ++i) { - branch_uid branch = project.translate_branch(*i); + branch_uid branch = projects.translate_branch(*i); map::const_iterator j; j = epochs.find(branch); @@ -3209,7 +3213,7 @@ session::rebuild_merkle_trees(set > > cert_idx; cert_idx idx; - project.db.get_revision_cert_nobranch_index(idx); + projects.db.get_revision_cert_nobranch_index(idx); // Insert all non-branch certs reachable via these revisions // (branch certs were inserted earlier). @@ -3260,11 +3264,11 @@ session::rebuild_merkle_trees(set::const_iterator key = inserted_keys.begin(); key != inserted_keys.end(); key++) { - if (project.db.public_key_exists(*key)) + if (projects.db.public_key_exists(*key)) { base64 pub_encoded; - project.db.get_key(*key, pub_encoded); + projects.db.get_key(*key, pub_encoded); hexenc keyhash; key_hash_code(*key, pub_encoded, keyhash); L(FL("noting key '%s' = '%s' to send") % *key % keyhash); @@ -3302,7 +3306,7 @@ run_netsync_protocol(protocol_voice voic std::list const & addrs, globish const & include_pattern, globish const & exclude_pattern, - project_t & project, key_store & keys, + project_set & projects, key_store & keys, lua_hooks & lua, options & opts) { if (include_pattern().find_first_of("'\"") != string::npos) @@ -3329,13 +3333,13 @@ run_netsync_protocol(protocol_voice voic shared_ptr str(new Netxx::PipeStream(0,1)); shared_ptr sess(new session(role, server_voice, include_pattern, exclude_pattern, - project, keys, lua, opts, + projects, keys, lua, opts, "stdio", str)); serve_single_connection(sess,constants::netsync_timeout_seconds); } else serve_connections(role, include_pattern, exclude_pattern, - project, keys, lua, opts, + projects, keys, lua, opts, addrs, static_cast(constants::netsync_default_port), static_cast(constants::netsync_timeout_seconds), static_cast(constants::netsync_connection_limit)); @@ -3344,7 +3348,7 @@ run_netsync_protocol(protocol_voice voic { I(voice == client_voice); call_server(role, include_pattern, exclude_pattern, - project, keys, lua, opts, + projects, keys, lua, opts, addrs, static_cast(constants::netsync_default_port), static_cast(constants::netsync_timeout_seconds)); } ============================================================ --- project.cc c0f388cd89cd7c7964e0c517a2da9e812d07034e +++ project.cc 89c5235c7b7693cdf954b16d594b123fffb970a6 @@ -673,13 +673,12 @@ project_t::get_revision_branches(revisio get_branch_list(branchids); if (branchids.find(branch_uid(b())) != branchids.end()) branches.insert(translate_branch(branch_uid(b()))); - else - branches.insert(branch_name(b())); } } return i; } + outdated_indicator project_t::get_branch_certs(branch_name const & branch, std::vector > & certs) @@ -805,7 +804,189 @@ project_t::put_cert(key_store & keys, put_simple_revision_cert(id, name, value, db, keys); } +//////////////////////////////////////////////////////////////////////// +project_set::project_set(database & db, lua_hooks & lua) + : db(db) +{ + map project_definitions; + lua.hook_get_projects(project_definitions); + for (map::const_iterator i = project_definitions.begin(); + i != project_definitions.end(); ++i) + { + projects.insert(make_pair(branch_prefix(i->first), + project_t(branch_prefix(i->first), + i->second, + db))); + } + if (projects.empty()) + { + projects.insert(std::make_pair("", project_t(db))); + } +} + +project_t & +project_set::get_project(branch_prefix const & name) +{ + project_t * const project = maybe_get_project(name); + I(project != NULL); + return *project; +} + +project_t * const +project_set::maybe_get_project(branch_prefix const & name) +{ + map::iterator i = projects.find(name); + if (i != projects.end()) + return &i->second; + else + return NULL; +} + +project_t & +project_set::get_project_of_branch(branch_name const & branch) +{ + project_t * const project = maybe_get_project_of_branch(branch); + I(project != NULL); + return *project; +} + +project_t * const +project_set::maybe_get_project_of_branch(branch_name const & branch) +{ + for (map::iterator i = projects.begin(); + i != projects.end(); ++i) + { + if (i->first() == "") + return &i->second; + std::string pre = i->first() + "."; + if (branch().substr(0, pre.size()) == pre) + return &i->second; + } + return NULL; +} + +void +project_set::get_branch_list(std::set & names, + bool check_heads) +{ + names.clear(); + for (project_map::iterator i = projects.begin(); + i != projects.end(); ++i) + { + std::set some_names; + i->second.get_branch_list(some_names, check_heads); + std::copy(some_names.begin(), some_names.end(), + std::inserter(names, names.end())); + } +} + +void +project_set::get_branch_list(globish const & glob, + std::set & names, + bool check_heads) +{ + names.clear(); + for (project_map::iterator i = projects.begin(); + i != projects.end(); ++i) + { + std::set some_names; + i->second.get_branch_list(glob, some_names, check_heads); + std::copy(some_names.begin(), some_names.end(), + std::inserter(names, names.end())); + } +} + +void +project_set::get_branch_uids(std::set & uids) +{ + uids.clear(); + for (project_map::iterator i = projects.begin(); + i != projects.end(); ++i) + { + std::set some_uids; + i->second.get_branch_list(some_uids); + std::copy(some_uids.begin(), some_uids.end(), + std::inserter(uids, uids.end())); + } +} + +branch_uid +project_set::translate_branch(branch_name const & branch) +{ + return get_project_of_branch(branch).translate_branch(branch); +} + +branch_name +project_set::translate_branch(branch_uid const & branch) +{ + for (project_map::iterator i = projects.begin(); + i != projects.end(); ++i) + { + std::set uids; + i->second.get_branch_list(uids); + if (uids.find(branch) != uids.end()) + { + return i->second.translate_branch(branch); + } + } + E(false, F("Cannot find a name for the branch with uid '%s'") % branch); +} + +outdated_indicator +project_set::get_tags(std::set & tags) +{ + I(!projects.empty()); + return projects.begin()->second.get_tags(tags); +} + +outdated_indicator +project_set::get_revision_branches(revision_id const & id, + std::set & branches) +{ + std::vector > certs; + outdated_indicator i = get_revision_certs_by_name(id, branch_cert_name, certs); + branches.clear(); + for (std::vector >::const_iterator i = certs.begin(); + i != certs.end(); ++i) + { + cert_value b; + decode_base64(i->inner().value, b); + branch_uid uid(b()); + + for (project_map::iterator i = projects.begin(); + i != projects.end(); ++i) + { + std::set branchids; + i->second.get_branch_list(branchids); + if (branchids.find(uid) != branchids.end()) + { + branches.insert(i->second.translate_branch(uid)); + break; + } + } + } + return i; +} + +outdated_indicator +project_set::get_revision_certs_by_name(revision_id const & id, + cert_name const & name, + std::vector > & certs) +{ + outdated_indicator i = db.get_revision_certs(id, name, certs); + erase_bogus_certs(certs, db); + return i; +} + +outdated_indicator +project_set::get_revision_certs(revision_id const & id, + std::vector > & certs) +{ + return db.get_revision_certs(id, certs); +} + + // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- project.hh 4dae65adb8451ff22df7ac664e5e45d6b7fefd63 +++ project.hh a869324a08efe4894c084eb0d6d30d55ef76b7b1 @@ -19,9 +19,9 @@ public: class tag_t { public: - revision_id ident; - utf8 name; - rsa_keypair_id key; + revision_id const ident; + utf8 const name; + rsa_keypair_id const key; tag_t(revision_id const & ident, utf8 const & name, rsa_keypair_id const & key); }; bool operator < (tag_t const & a, tag_t const & b); @@ -77,7 +77,8 @@ public: revision_id const & id, branch_name const & branch); - bool revision_is_suspended_in_branch(revision_id const & id, branch_name const & branch); + bool revision_is_suspended_in_branch(revision_id const & id, + branch_name const & branch); void suspend_revision_in_branch(key_store & keys, revision_id const & id, branch_name const & branch); @@ -86,9 +87,13 @@ public: std::vector > & hashes); outdated_indicator get_revision_certs(revision_id const & id, std::vector > & certs); + // This kind of assumes that we'll eventually have certs be for a specific + // project. There's a fairly good chance that that won't happen, which would + // mean that this can go away. outdated_indicator get_revision_certs_by_name(revision_id const & id, cert_name const & name, std::vector > & certs); + // What branches in *this* project does the given revision belong to? outdated_indicator get_revision_branches(revision_id const & id, std::set & branches); outdated_indicator get_branch_certs(branch_name const & branch, @@ -113,6 +118,54 @@ public: cert_value const & value); }; +class project_set +{ +public: + database & db; + +private: + typedef std::map project_map; + project_map projects; + +public: + explicit project_set(database & db, lua_hooks & lua); + + // Get a named project. + project_t & get_project(branch_prefix const & name); + project_t * const maybe_get_project(branch_prefix const & name); + + // Get the project containing a named branch. + project_t & get_project_of_branch(branch_name const & branch); + project_t * const maybe_get_project_of_branch(branch_name const & branch); + + // All branches in all projects. + void get_branch_list(std::set & names, + bool check_heads = false); + // Subset of branches from all projects. + void get_branch_list(globish const & glob, + std::set & names, + bool check_heads = false); + + // used by epoch handling + void get_branch_uids(std::set & ids); + branch_uid translate_branch(branch_name const & branch); + branch_name translate_branch(branch_uid const & branch); + + // What tags exist across all projects? + outdated_indicator get_tags(std::set & tags); + + // What branches in *any* project does the given revision belong to? + outdated_indicator get_revision_branches(revision_id const & id, + std::set & branches); + + outdated_indicator get_revision_certs_by_name(revision_id const & id, + cert_name const & name, + std::vector > & certs); + + outdated_indicator get_revision_certs(revision_id const & id, + std::vector > & certs); +}; + #endif ============================================================ --- selectors.cc a63cff13b6230113758688098d9be976db0ea60f +++ selectors.cc 363089ff77762398f45398abe931605d142ac06a @@ -210,45 +210,57 @@ complete_one_selector(selector_type ty, static void complete_one_selector(selector_type ty, string const & value, set & completions, - project_t & project) + project_set & projects) { switch (ty) { case sel_ident: - project.db.complete(value, completions); + projects.db.complete(value, completions); break; case sel_parent: - project.db.select_parent(value, completions); + projects.db.select_parent(value, completions); break; case sel_author: - project.db.select_cert(author_cert_name(), value, completions); + projects.db.select_cert(author_cert_name(), value, completions); break; case sel_tag: - project.db.select_cert(tag_cert_name(), value, completions); + projects.db.select_cert(tag_cert_name(), value, completions); break; case sel_branch: I(!value.empty()); - project.db.select_cert(branch_cert_name(), value, completions); + { + set branches; + projects.get_branch_list(globish(value), branches); + for (set::const_iterator i = branches.begin(); + i != branches.end(); ++i) + { + set in_this_branch; + projects.db.select_cert(branch_cert_name(), (*i)(), in_this_branch); + std::copy(in_this_branch.begin(), + in_this_branch.end(), + std::inserter(completions, completions.end())); + } + } break; case sel_unknown: - project.db.select_author_tag_or_branch(value, completions); + projects.db.select_author_tag_or_branch(value, completions); break; case sel_date: - project.db.select_date(value, "GLOB", completions); + projects.db.select_date(value, "GLOB", completions); break; case sel_earlier: - project.db.select_date(value, "<=", completions); + projects.db.select_date(value, "<=", completions); break; case sel_later: - project.db.select_date(value, ">", completions); + projects.db.select_date(value, ">", completions); break; case sel_cert: @@ -265,10 +277,10 @@ complete_one_selector(selector_type ty, spot++; certvalue = value.substr(spot); - project.db.select_cert(certname, certvalue, completions); + projects.db.select_cert(certname, certvalue, completions); } else - project.db.select_cert(value, completions); + projects.db.select_cert(value, completions); } break; @@ -278,7 +290,7 @@ complete_one_selector(selector_type ty, // get branch names set branch_names; I(!value.empty()); - project.get_branch_list(globish(value), branch_names); + projects.get_branch_list(globish(value), branch_names); L(FL("found %d matching branches") % branch_names.size()); @@ -287,7 +299,9 @@ complete_one_selector(selector_type ty, bn != branch_names.end(); bn++) { set branch_heads; - project.get_branch_heads(*bn, branch_heads, ty == sel_any_head); + projects + .get_project_of_branch(*bn) + .get_branch_heads(*bn, branch_heads, ty == sel_any_head); completions.insert(branch_heads.begin(), branch_heads.end()); L(FL("after get_branch_heads for %s, heads has %d entries") % (*bn) % completions.size()); @@ -300,23 +314,23 @@ complete_selector(selector_list const & static void complete_selector(selector_list const & limit, set & completions, - project_t & project) + project_set & projects) { if (limit.empty()) // all the ids in the database { - project.db.complete("", completions); + projects.db.complete("", completions); return; } selector_list::const_iterator i = limit.begin(); - complete_one_selector(i->first, i->second, completions, project); + complete_one_selector(i->first, i->second, completions, projects); i++; while (i != limit.end()) { set candidates; set intersection; - complete_one_selector(i->first, i->second, candidates, project); + complete_one_selector(i->first, i->second, candidates, projects); intersection.clear(); set_intersection(completions.begin(), completions.end(), @@ -348,7 +362,7 @@ complete(app_state & app, } P(F("expanding selection '%s'") % str); - complete_selector(sels, completions, app.get_project()); + complete_selector(sels, completions, app.get_projects()); N(completions.size() != 0, F("no match for selection '%s'") % str); @@ -398,7 +412,7 @@ expand_selector(app_state & app, return; } - complete_selector(sels, completions, app.get_project()); + complete_selector(sels, completions, app.get_projects()); } void @@ -413,7 +427,7 @@ diagnose_ambiguous_expansion(app_state & % str).str(); for (set::const_iterator i = completions.begin(); i != completions.end(); ++i) - err += ("\n" + describe_revision(app.get_project(), *i)); + err += ("\n" + describe_revision(app.get_projects(), *i)); N(false, i18n_format(err)); }