# # # patch "automate.cc" # from [2d83f22200a3999fe8416b301f0bbbca0d90723c] # to [22bdca832e8d3725dca929762efbc9c9cce0267d] # # patch "cmd_ws_commit.cc" # from [5c4576edd5b77a135b612ca40f93c963f778a755] # to [72c210276c196dd83a6ffc907d41b1ea3563d2c3] # # patch "database.cc" # from [3e65a0b3f6e71edd464d6dc18e8ac46652a44cb1] # to [efb940d44464df55a352614fc5ac4db38d5c5945] # # patch "database.hh" # from [5d5f3613e3c091f1dc75eb734b86fa4559b03969] # to [caaab3649c6ca7d9d6e0be33dd062427a3b5c477] # ============================================================ --- automate.cc 2d83f22200a3999fe8416b301f0bbbca0d90723c +++ automate.cc 22bdca832e8d3725dca929762efbc9c9cce0267d @@ -1205,49 +1205,18 @@ AUTOMATE(common_ancestors, N_("REV1 [REV N(args.size() > 0, F("wrong argument count")); - set ancestors, common_ancestors; - vector frontier; + set revs, common_ancestors; for (vector::const_iterator i = args.begin(); i != args.end(); ++i) { revision_id rid((*i)()); N(app.db.revision_exists(rid), F("No such revision %s") % rid); - ancestors.clear(); - ancestors.insert(rid); - frontier.push_back(rid); - while (!frontier.empty()) - { - revision_id rid = frontier.back(); - frontier.pop_back(); - if(!null_id(rid)) - { - set parents; - app.db.get_revision_parents(rid, parents); - for (set::const_iterator i = parents.begin(); - i != parents.end(); ++i) - { - if (ancestors.find(*i) == ancestors.end()) - { - frontier.push_back(*i); - ancestors.insert(*i); - } - } - } - } - if (common_ancestors.empty()) - common_ancestors = ancestors; - else - { - set common; - set_intersection(ancestors.begin(), ancestors.end(), - common_ancestors.begin(), common_ancestors.end(), - inserter(common, common.begin())); - common_ancestors = common; - } + revs.insert(rid); } + app.db.get_common_ancestors(revs, common_ancestors); + for (set::const_iterator i = common_ancestors.begin(); i != common_ancestors.end(); ++i) - if (!null_id(*i)) output << (*i).inner()() << "\n"; } ============================================================ --- cmd_ws_commit.cc 5c4576edd5b77a135b612ca40f93c963f778a755 +++ cmd_ws_commit.cc 72c210276c196dd83a6ffc907d41b1ea3563d2c3 @@ -687,14 +687,63 @@ CMD(branch, N_("workspace"), N_("BRANCHN branch_name branch(idx(args, 0)()); - // check if the branch cert is already known and refuse if this is right - // TODO!! + app.require_workspace(); + E(branch != app.opts.branchname, + F("branch of the current workspace is already set to %s") % branch); + + std::set branches; + app.get_project().get_branch_list(branches); + + bool existing_branch = false; + for (set::const_iterator i = branches.begin(); + i != branches.end(); ++i) + { + if (branch == *i) + { + existing_branch = true; + break; + } + } + + // if this is an existing branch, check if this branch's head revs and + // the current workspace parent share any common ancestors, if not warn + // the user about it + if (existing_branch) + { + set revs, common_ancestors; + app.get_project().get_branch_heads(branch, revs); + + // FIXME: is there an easier way to just get the revids of the parent(s) + // of the current workspace? + revision_t work_rev; + app.work.get_work_rev(work_rev); + for (edge_map::iterator i = work_rev.edges.begin(); + i != work_rev.edges.end(); i++) + { + revs.insert(i->first); + } + + app.db.get_common_ancestors(revs, common_ancestors); + + if (common_ancestors.size() == 0) + { + W(F("the new branch has no common ancestors with the current branch;\n" + "any next commit could therefor create two unmergable heads in\n" + "%s") % branch); + } + } + // leave the other parameters empty so they won't get changed system_path path; rsa_keypair_id key; app.work.set_ws_options(path, branch, key, path); + + if (existing_branch) + P(F("next commit will use the existing branch %s") % branch); + else + P(F("next commit will use the new branch %s") % branch); } CMD(commit, N_("workspace"), N_("[PATH]..."), ============================================================ --- database.cc 3e65a0b3f6e71edd464d6dc18e8ac46652a44cb1 +++ database.cc efb940d44464df55a352614fc5ac4db38d5c5945 @@ -1824,6 +1824,59 @@ void } void +database::get_common_ancestors(std::set const & revs, + std::set & common_ancestors) +{ + set ancestors, all_common_ancestors; + vector frontier; + for (set::const_iterator i = revs.begin(); + i != revs.end(); ++i) + { + I(revision_exists(*i)); + ancestors.clear(); + ancestors.insert(*i); + frontier.push_back(*i); + while (!frontier.empty()) + { + revision_id rid = frontier.back(); + frontier.pop_back(); + if(!null_id(rid)) + { + set parents; + get_revision_parents(rid, parents); + for (set::const_iterator i = parents.begin(); + i != parents.end(); ++i) + { + if (ancestors.find(*i) == ancestors.end()) + { + frontier.push_back(*i); + ancestors.insert(*i); + } + } + } + } + if (all_common_ancestors.empty()) + all_common_ancestors = ancestors; + else + { + set common; + set_intersection(ancestors.begin(), ancestors.end(), + all_common_ancestors.begin(), all_common_ancestors.end(), + inserter(common, common.begin())); + all_common_ancestors = common; + } + } + + for (set::const_iterator i = all_common_ancestors.begin(); + i != all_common_ancestors.end(); ++i) + { + // FIXME: where do these null'ed IDs come from? + if (null_id(*i)) continue; + common_ancestors.insert(*i); + } +} + +void database::get_revision(revision_id const & id, revision_t & rev) { ============================================================ --- database.hh 5d5f3613e3c091f1dc75eb734b86fa4559b03969 +++ database.hh caaab3649c6ca7d9d6e0be33dd062427a3b5c477 @@ -296,6 +296,10 @@ public: void get_revision_manifest(revision_id const & cid, manifest_id & mid); + + void get_common_ancestors(std::set const & revs, + std::set & common_ancestors); + private: // helper void get_ids(std::string const & table, std::set< hexenc > & ids);