# # # patch "automate.cc" # from [9b2d2c6438d01423cde0615b3df1a753454bb506] # to [46cd7b100578361c5542ac381e9254afcec4a8d8] # # patch "cmd_diff_log.cc" # from [9af7d3366efc27279a4a42e5971d352859de6c26] # to [3115670c4956765d30fb00d5e387cd741875da22] # # patch "cmd_files.cc" # from [fc8b38ef2403f9ef32880ebf86a2a39d4703d8d6] # to [f233c1c63a60b180c644c1aa98ca92ce1f3b30d0] # # patch "cmd_list.cc" # from [783991aedffea80666c33fe6e3fff2ff251a87d9] # to [532385156665e4e401c1001557a15ab826fe5668] # # patch "cmd_merging.cc" # from [5ebc0d909d0ea52fd29bcb5177a9df5595b97121] # to [89f42ba29c37619121bfaaa4a0912fd890d9549c] # # patch "cmd_netsync.cc" # from [17199b154899d9bfb5c99f02f1c9e6c5d8b1c9e5] # to [8bf20313954aa7e71da03ee5e9280bbd6b34cfb5] # # patch "cmd_ws_commit.cc" # from [978acabdbea5739e0b18c7a4187255b7c6343d47] # to [eeb3a84d8e43c532cd3888bd844454a961b0c7f2] # # patch "revision.cc" # from [4fcc44663ce844747a92a235ba529b1cbb091451] # to [a628f1b8d23558e64bbe258adf8f60fbccd00911] # # patch "revision.hh" # from [eb8fe69255a0e21fcfd1074060f5c6b87b844b5a] # to [a4d7f2b364ef0692a9ad8863a1b4dd4ba05596b4] # # patch "work.cc" # from [8ccb08cdc7afd8db1c33770ae69ab827c5a96ce4] # to [831ef4d2dbcada1d37de642e99dd4d55dbe4f975] # ============================================================ --- automate.cc 9b2d2c6438d01423cde0615b3df1a753454bb506 +++ automate.cc 46cd7b100578361c5542ac381e9254afcec4a8d8 @@ -673,7 +673,12 @@ CMD_AUTOMATE(inventory, "", cset cs; MM(cs); set unchanged, changed, missing, unknown, ignored; - app.work.get_current_roster_shape(curr, nis); + { + // FIXME: this is totally gross, we load the parent roster(s) twice for + // no reason, etc. + parent_map parents; + app.work.get_current_roster_shape(parents, curr, nis); + } app.work.get_work_rev(rev); N(rev.edges.size() == 1, F("this command can only be used in a single-parent workspace")); @@ -877,8 +882,7 @@ CMD_AUTOMATE(get_revision, N_("[REVID]") revision_t rev; app.require_workspace(); - app.work.get_parent_rosters(old_rosters); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(old_rosters, new_roster, nis); app.work.update_current_roster_from_filesystem(new_roster); make_revision(old_rosters, new_roster, rev); @@ -914,12 +918,9 @@ CMD_AUTOMATE(get_base_revision_id, "", app.require_workspace(); - parent_map parents; - app.work.get_parent_rosters(parents); - N(parents.size() == 1, - F("this command can only be used in a single-parent workspace")); - - output << parent_id(parents.begin()) << '\n'; + revision_id base; + appt.work.get_unique_base_rid(base); + output << base << '\n'; } // Name: get_current_revision_id @@ -948,7 +949,7 @@ CMD_AUTOMATE(get_current_revision_id, "" temp_node_id_source nis; app.require_workspace(); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(parents, new_roster, nis); app.work.update_current_roster_from_filesystem(new_roster); app.work.get_parent_rosters(parents); @@ -1017,7 +1018,8 @@ CMD_AUTOMATE(get_manifest_of, N_("[REVID temp_node_id_source nis; app.require_workspace(); - app.work.get_current_roster_shape(new_roster, nis); + parent_map parents; + app.work.get_current_roster_shape(parents, new_roster, nis); app.work.update_current_roster_from_filesystem(new_roster); } else ============================================================ --- cmd_diff_log.cc 9af7d3366efc27279a4a42e5971d352859de6c26 +++ cmd_diff_log.cc 3115670c4956765d30fb00d5e387cd741875da22 @@ -362,7 +362,7 @@ prepare_diff(cset & included, revision_id old_rid; parent_map parents; - app.work.get_parent_rosters(parents); + app.work.get_current_roster_shape(parents, new_roster, nis); // With no arguments, which parent should we diff against? N(parents.size() == 1, @@ -371,7 +371,6 @@ prepare_diff(cset & included, old_rid = parent_id(parents.begin()); old_roster = parent_roster(parents.begin()); - app.work.get_current_roster_shape(new_roster, nis); node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), @@ -398,7 +397,10 @@ prepare_diff(cset & included, F("no such revision '%s'") % r_old_id); app.db.get_roster(r_old_id, old_roster); - app.work.get_current_roster_shape(new_roster, nis); + { + parent_map parents; + app.work.get_current_roster_shape(parents, new_roster, nis); + } node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), @@ -674,8 +676,7 @@ CMD(log, "log", "", CMD_REF(informative) parent_map parents; temp_node_id_source nis; - app.work.get_parent_rosters(parents); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(parents, new_roster, nis); mask = node_restriction(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), ============================================================ --- cmd_files.cc fc8b38ef2403f9ef32880ebf86a2a39d4703d8d6 +++ cmd_files.cc f233c1c63a60b180c644c1aa98ca92ce1f3b30d0 @@ -295,12 +295,7 @@ CMD(cat, "cat", "", CMD_REF(informative) if (app.opts.revision_selectors.size() == 0) { app.require_workspace(); - - parent_map parents; - app.work.get_parent_rosters(parents); - N(parents.size() == 1, - F("this command can only be used in a single-parent workspace")); - rid = parent_id(parents.begin()); + app.work.get_unique_base_rid(rid); } else complete(app, idx(app.opts.revision_selectors, 0)(), rid); @@ -357,11 +352,7 @@ CMD_AUTOMATE(get_file_of, N_("FILENAME") { app.require_workspace(); - parent_map parents; - app.work.get_parent_rosters(parents); - N(parents.size() == 1, - F("this command can only be used in a single-parent workspace")); - rid = parent_id(parents.begin()); + app.work.get_unique_base_rid(rid); } else complete(app, idx(app.opts.revision_selectors, 0)(), rid); ============================================================ --- cmd_list.cc 783991aedffea80666c33fe6e3fff2ff251a87d9 +++ cmd_list.cc 532385156665e4e401c1001557a15ab826fe5668 @@ -362,7 +362,10 @@ CMD(known, "known", "", CMD_REF(list), " temp_node_id_source nis; app.require_workspace(); - app.work.get_current_roster_shape(new_roster, nis); + { + parent_map parents; + app.work.get_current_roster_shape(parents, new_roster, nis); + } node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), @@ -454,11 +457,9 @@ CMD(changed, "changed", "", CMD_REF(list app.require_workspace(); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(parents, new_roster, nis); app.work.update_current_roster_from_filesystem(new_roster); - app.work.get_parent_rosters(parents); - node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), app.opts.depth, ============================================================ --- cmd_merging.cc 5ebc0d909d0ea52fd29bcb5177a9df5595b97121 +++ cmd_merging.cc 89f42ba29c37619121bfaaa4a0912fd890d9549c @@ -141,9 +141,10 @@ update(app_state & app, commands::comman app.require_workspace(); - // Figure out where we are + // Figure out where we are, and what we look like. parent_map parents; - app.work.get_parent_rosters(parents); + roster_t working_roster; MM(working_roster); + app.work.get_current_roster_shape(parents, working_roster, nis); N(parents.size() == 1, F("this command can only be used in a single-parent workspace")); @@ -244,21 +245,20 @@ update(app_state & app, commands::comman temp_node_id_source nis; - // Get the OLD and WORKING rosters + // Get the OLD roster, and finish getting the WORKING roster database::roster_t_cp old_roster = parent_cached_roster(parents.begin()).first; MM(*old_roster); - roster_t working_roster; MM(working_roster); - app.work.get_current_roster_shape(working_roster, nis); app.work.update_current_roster_from_filesystem(working_roster); // Get the CHOSEN roster - roster_t chosen_roster; MM(chosen_roster); + database::cached_roster chosen_roster; app.db.get_roster(chosen_rid, chosen_roster); + MM(*chosen_roster.first); // And finally do the merge roster_merge_result result; - three_way_merge(*old_roster, working_roster, chosen_roster, result); + three_way_merge(*old_roster, working_roster, *chosen_roster.first, result); roster_t & merged_roster = result.roster; @@ -266,7 +266,7 @@ update(app_state & app, commands::comman get_content_paths(working_roster, paths); content_merge_workspace_adaptor wca(app, old_roster, paths); - resolve_merge_conflicts(working_roster, chosen_roster, + resolve_merge_conflicts(working_roster, *chosen_roster.first, result, wca, app); // Make sure it worked... @@ -278,12 +278,10 @@ update(app_state & app, commands::comman make_cset(working_roster, merged_roster, update); app.work.perform_content_update(update, wca); - revision_t remaining; - make_revision_for_workspace(chosen_rid, chosen_roster, - merged_roster, remaining); - // small race condition here... - app.work.put_work_rev(remaining); + parent_map new_parents; + safe_insert(new_parents, std::make_pair(chosen_rid, chosen_roster)); + app.work.set_work_state(new_parents, merged_roster); app.work.update_any_attrs(); app.work.maybe_update_inodeprints(); @@ -702,12 +700,12 @@ CMD(merge_into_workspace, "merge_into_wo // (revs can have no more than two parents). { parent_map parents; - app.work.get_parent_rosters(parents); + temp_node_id_source nis; + app.work.get_current_roster_shape(parents, working_roster, nis); + N(parents.size() == 1, F("this command can only be used in a single-parent workspace")); - temp_node_id_source nis; - app.work.get_current_roster_shape(working_roster, nis); app.work.update_current_roster_from_filesystem(working_roster); N(parent_roster(parents.begin()) == working_roster, @@ -748,22 +746,17 @@ CMD(merge_into_workspace, "merge_into_wo I(merge_result.is_clean()); merge_result.roster.check_sane(true); - // Construct the workspace revision. + // Construct the new workspace state. parent_map parents; safe_insert(parents, std::make_pair(left_id, left)); safe_insert(parents, std::make_pair(right_id, right)); - revision_t merged_rev; - make_revision_for_workspace(parents, merge_result.roster, merged_rev); - - // Note: the csets in merged_rev are _not_ suitable for submission to - // perform_content_update, because content changes have been dropped. cset update; make_cset(*left.first, merge_result.roster, update); // small race condition here... app.work.perform_content_update(update, wca); - app.work.put_work_rev(merged_rev); + app.work.set_work_state(parents, merge_result.roster); app.work.update_any_attrs(); app.work.maybe_update_inodeprints(); @@ -923,8 +916,9 @@ CMD(pluck, "pluck", "", CMD_REF(workspac app.db.get_roster(from_rid, *from_roster); // Get the WORKING roster + parent_map parents; roster_t working_roster; MM(working_roster); - app.work.get_current_roster_shape(working_roster, nis); + app.work.get_current_roster_shape(parents, working_roster, nis); app.work.update_current_roster_from_filesystem(working_roster); @@ -979,14 +973,8 @@ CMD(pluck, "pluck", "", CMD_REF(workspac P(F("applied changes to workspace")); // and record any remaining changes in _MTN/revision - parent_map parents; - revision_t remaining; - MM(remaining); - app.work.get_parent_rosters(parents); - make_revision_for_workspace(parents, merged_roster, remaining); - - // small race condition here... - app.work.put_work_rev(remaining); + // (small race condition here...) + app.work.set_work_state(parents, merged_roster); app.work.update_any_attrs(); // add a note to the user log file about what we did @@ -1049,8 +1037,7 @@ CMD(get_roster, "get_roster", "", CMD_RE revision_id rid(fake_id()); app.require_workspace(); - app.work.get_parent_rosters(parents); - app.work.get_current_roster_shape(roster, nis); + app.work.get_current_roster_shape(parents, roster, nis); app.work.update_current_roster_from_filesystem(roster); if (parents.size() == 0) ============================================================ --- cmd_netsync.cc 17199b154899d9bfb5c99f02f1c9e6c5d8b1c9e5 +++ cmd_netsync.cc 8bf20313954aa7e71da03ee5e9280bbd6b34cfb5 @@ -414,17 +414,16 @@ CMD(clone, "clone", "", CMD_REF(network) } shared_ptr empty_roster = shared_ptr(new roster_t()); - roster_t current_roster; + database::cached_roster current_roster; L(FL("checking out revision %s to directory %s") % ident % workspace_dir); app.db.get_roster(ident, current_roster); + parent_map parents; + safe_insert(parents, std::make_pair(ident, current_roster)); + app.work.set_work_state(parents, *current_roster.first); - revision_t workrev; - make_revision_for_workspace(ident, cset(), workrev); - app.work.put_work_rev(workrev); - cset checkout; - make_cset(*empty_roster, current_roster, checkout); + make_cset(*empty_roster, *current_roster.first, checkout); map paths; get_content_paths(*empty_roster, paths); @@ -489,7 +488,7 @@ CMD_NO_WORKSPACE(serve, "serve", "", CMD find_key(utf8(), globish("*"), globish(""), app); N(app.lua.hook_persist_phrase_ok(), - F("need permission to store persistent passphrase (see hook persist_phrase_ok())")); + F("need permission to store persistent passphrase (see hook persist_phrase_ok())")); require_password(app.opts.signing_key, app); } else if (!app.opts.bind_stdio) ============================================================ --- cmd_ws_commit.cc 978acabdbea5739e0b18c7a4187255b7c6343d47 +++ cmd_ws_commit.cc eeb3a84d8e43c532cd3888bd844454a961b0c7f2 @@ -158,15 +158,13 @@ CMD(revert, "revert", "", CMD_REF(worksp app.require_workspace(); parent_map parents; - app.work.get_parent_rosters(parents); + temp_node_id_source nis; + app.work.get_current_roster_shape(parents, new_roster, nis); + N(parents.size() == 1, F("this command can only be used in a single-parent workspace")); old_roster = parent_roster(parents.begin()); - { - temp_node_id_source nis; - app.work.get_current_roster_shape(new_roster, nis); - } node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), @@ -208,6 +206,12 @@ CMD(revert, "revert", "", CMD_REF(worksp // old roster. check_restricted_cset(old_roster, excluded); + // The check passed, so the cset will actually apply. + roster_t new_new_roster = old_roster; + { + editable_roster_base er(new_new_roster, nis); + excluded.apply_to(er); + } node_map const & nodes = old_roster.all_nodes(); for (node_map::const_iterator i = nodes.begin(); @@ -265,11 +269,8 @@ CMD(revert, "revert", "", CMD_REF(worksp // been rewritten above but this may leave rename targets laying // around. - revision_t remaining; - make_revision_for_workspace(parent_id(parents.begin()), excluded, remaining); - // Race. - app.work.put_work_rev(remaining); + app.work.set_work_state(parents, new_new_roster); app.work.update_any_attrs(); app.work.maybe_update_inodeprints(); } @@ -415,7 +416,8 @@ CMD(drop, "drop", "rm", CMD_REF(workspac { temp_node_id_source nis; roster_t current_roster_shape; - app.work.get_current_roster_shape(current_roster_shape, nis); + parent_map parents; + app.work.get_current_roster_shape(parents, current_roster_shape, nis); node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), app.opts.depth, @@ -459,8 +461,8 @@ CMD(rename, "rename", "mv", CMD_REF(work //cases for more than one source item. if (src_paths.size() == 1 && dstr()[dstr().size() -1] == '/') if (get_path_status(*src_paths.begin()) != path::directory) - N(get_path_status(dst_path) == path::directory, - F(_("The specified target directory %s/ doesn't exist.")) % dst_path); + N(get_path_status(dst_path) == path::directory, + F(_("The specified target directory %s/ doesn't exist.")) % dst_path); app.work.perform_rename(src_paths, dst_path, app.opts.bookkeep_only); } @@ -496,8 +498,7 @@ CMD(status, "status", "", CMD_REF(inform temp_node_id_source nis; app.require_workspace(); - app.work.get_parent_rosters(old_rosters); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(old_rosters, new_roster, nis); node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), @@ -596,26 +597,27 @@ CMD(checkout, "checkout", "co", CMD_REF( app.create_workspace(dir); - shared_ptr empty_roster = shared_ptr(new roster_t()); - roster_t current_roster; - L(FL("checking out revision %s to directory %s") % revid % dir); + database::cached_roster current_roster; app.db.get_roster(revid, current_roster); + parent_map parents; + safe_insert(parents, std::make_pair(revid, current_roster)); - revision_t workrev; - make_revision_for_workspace(revid, cset(), workrev); - app.work.put_work_rev(workrev); + app.work.set_work_state_unchanged(parents, *current_roster.first); - cset checkout; - make_cset(*empty_roster, current_roster, checkout); - - map paths; - get_content_paths(*empty_roster, paths); - - content_merge_workspace_adaptor wca(app, empty_roster, paths); - - app.work.perform_content_update(checkout, wca, false); - + { + shared_ptr empty_roster = shared_ptr(new roster_t()); + cset checkout; + make_cset(*empty_roster, current_roster, checkout); + + map paths; + get_content_paths(*empty_roster, paths); + + content_merge_workspace_adaptor wca(app, empty_roster, paths); + + app.work.perform_content_update(checkout, wca, false); + } + app.work.update_any_attrs(); app.work.maybe_update_inodeprints(); guard.commit(); @@ -635,11 +637,12 @@ CMD(attr_drop, "drop", "", CMD_REF(attr) N(args.size() > 0 && args.size() < 3, F("wrong argument count")); + parent_map parents; roster_t new_roster; temp_node_id_source nis; app.require_workspace(); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(parents, new_roster, nis); file_path path = file_path_external(idx(args, 0)); @@ -663,12 +666,7 @@ CMD(attr_drop, "drop", "", CMD_REF(attr) node->attrs[a_key] = make_pair(false, ""); } - parent_map parents; - app.work.get_parent_rosters(parents); - - revision_t new_work; - make_revision_for_workspace(parents, new_roster, new_work); - app.work.put_work_rev(new_work); + app.work.set_work_state(parents, new_roster); app.work.update_any_attrs(); } @@ -686,7 +684,10 @@ CMD(attr_get, "get", "", CMD_REF(attr), temp_node_id_source nis; app.require_workspace(); - app.work.get_current_roster_shape(new_roster, nis); + { + parent_map parents; + app.work.get_current_roster_shape(parents, new_roster, nis); + } file_path path = file_path_external(idx(args, 0)); @@ -732,11 +733,12 @@ CMD(attr_set, "set", "", CMD_REF(attr), N(args.size() == 3, F("wrong argument count")); + parent_map parents; roster_t new_roster; temp_node_id_source nis; app.require_workspace(); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(parents, new_roster, nis); file_path path = file_path_external(idx(args, 0)); @@ -748,12 +750,7 @@ CMD(attr_set, "set", "", CMD_REF(attr), node->attrs[a_key] = make_pair(true, a_value); - parent_map parents; - app.work.get_parent_rosters(parents); - - revision_t new_work; - make_revision_for_workspace(parents, new_roster, new_work); - app.work.put_work_rev(new_work); + app.work.set_work_state(parents, new_roster); app.work.update_any_attrs(); } @@ -795,8 +792,7 @@ CMD_AUTOMATE(get_attributes, N_("PATH"), temp_node_id_source nis; // get the base and the current roster of this workspace - app.work.get_current_roster_shape(current, nis); - app.work.get_parent_rosters(parents); + app.work.get_current_roster_shape(parents, current, nis); N(parents.size() == 1, F("this command can only be used in a single-parent workspace")); base = parent_roster(parents.begin()); @@ -902,11 +898,12 @@ CMD_AUTOMATE(set_attribute, N_("PATH KEY N(args.size() == 3, F("wrong argument count")); + parent_map parents; roster_t new_roster; temp_node_id_source nis; app.require_workspace(); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(parents, new_roster, nis); file_path path = file_path_external(idx(args,0)); @@ -918,12 +915,7 @@ CMD_AUTOMATE(set_attribute, N_("PATH KEY node->attrs[a_key] = make_pair(true, a_value); - parent_map parents; - app.work.get_parent_rosters(parents); - - revision_t new_work; - make_revision_for_workspace(parents, new_roster, new_work); - app.work.put_work_rev(new_work); + app.work.set_work_state(parents, new_roster); app.work.update_any_attrs(); } @@ -946,11 +938,12 @@ CMD_AUTOMATE(drop_attribute, N_("PATH [K N(args.size() ==1 || args.size() == 2, F("wrong argument count")); + parent_map parents; roster_t new_roster; temp_node_id_source nis; app.require_workspace(); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(parents, new_roster, nis); file_path path = file_path_external(idx(args,0)); @@ -973,12 +966,7 @@ CMD_AUTOMATE(drop_attribute, N_("PATH [K node->attrs[a_key] = make_pair(false, ""); } - parent_map parents; - app.work.get_parent_rosters(parents); - - revision_t new_work; - make_revision_for_workspace(parents, new_roster, new_work); - app.work.put_work_rev(new_work); + app.work.set_work_state(parents, new_roster); app.work.update_any_attrs(); } @@ -1004,8 +992,7 @@ commit(app_state & app, commands::comman } app.make_branch_sticky(); - app.work.get_parent_rosters(old_rosters); - app.work.get_current_roster_shape(new_roster, nis); + app.work.get_current_roster_shape(old_rosters, new_roster, nis); node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), @@ -1188,13 +1175,23 @@ commit(app_state & app, commands::comman guard.commit(); } - // the work revision is now whatever changes remain on top of the revision + // the work roster is now whatever changes remain on top of the revision // we just checked in. - revision_t remaining; - make_revision_for_workspace(restricted_rev_id, excluded, remaining); + { + database::cached_roster new_parent; + app.db.get_roster(restricted_rev_id, new_parent); + parent_map new_parents; + safe_insert(new_parents, std::make_pair(restricted_rev_id, new_parent)); + + roster_t new_work = *new_parent.first; + temp_node_id_source nis; + editable_roster_base er(new_work, nis); + excluded.apply_to(er); - // small race condition here... - app.work.put_work_rev(remaining); + // small race condition here... + app.work.set_work_state(new_parents, new_work); + } + if (automate) output << restricted_rev_id << "\n"; else @@ -1276,9 +1273,7 @@ CMD_NO_WORKSPACE(setup, "setup", "", CMD app.create_workspace(dir); - revision_t rev; - make_revision_for_workspace(revision_id(), cset(), rev); - app.work.put_work_rev(rev); + app.work.set_work_state_to_new_root(); } CMD_NO_WORKSPACE(import, "import", "", CMD_REF(tree), N_("DIRECTORY"), @@ -1341,9 +1336,7 @@ CMD_NO_WORKSPACE(import, "import", "", C try { - revision_t rev; - make_revision_for_workspace(ident, cset(), rev); - app.work.put_work_rev(rev); + app.work.set_work_state_unchanged(ident); // prepare stuff for 'add' and so on. app.found_workspace = true; // Yup, this is cheating! ============================================================ --- revision.cc 4fcc44663ce844747a92a235ba529b1cbb091451 +++ revision.cc a628f1b8d23558e64bbe258adf8f60fbccd00911 @@ -784,21 +784,6 @@ void } void -make_revision_for_workspace(revision_id const & old_rev_id, - roster_t const & old_roster, - roster_t const & new_roster, - revision_t & rev) -{ - MM(old_rev_id); - MM(old_roster); - MM(new_roster); - MM(rev); - cset changes; - make_cset(old_roster, new_roster, changes); - make_revision_for_workspace(old_rev_id, changes, rev); -} - -void make_revision_for_workspace(parent_map const & old_rosters, roster_t const & new_roster, revision_t & rev) ============================================================ --- revision.hh eb8fe69255a0e21fcfd1074060f5c6b87b844b5a +++ revision.hh a4d7f2b364ef0692a9ad8863a1b4dd4ba05596b4 @@ -190,18 +190,15 @@ make_revision(revision_id const & old_re // content-only changes from the cset. They are only to be used to // construct a revision that will be written to the workspace. Don't use // them for revisions written to the database or presented to the user. +// +// You probably want workspace::set_work_state instead; these are +// lower-level primitives. void make_revision_for_workspace(revision_id const & old_rev_id, cset const & changes, revision_t & rev); void -make_revision_for_workspace(revision_id const & old_rev_id, - roster_t const & old_roster, - roster_t const & new_roster, - revision_t & rev); - -void make_revision_for_workspace(parent_map const & old_rosters, roster_t const & new_roster, revision_t & rev); ============================================================ --- work.cc 8ccb08cdc7afd8db1c33770ae69ab827c5a96ce4 +++ work.cc 831ef4d2dbcada1d37de642e99dd4d55dbe4f975 @@ -104,6 +104,15 @@ void } void +workspace::get_unique_base_rid(revision_id & rid) +{ + revision_t & rev; + get_work_rev(rev); + N(rev.edges.size() == 1, + F("this command can only be used in a single-parent workspace")); +} + +void workspace::put_work_rev(revision_t const & rev) { MM(rev); @@ -118,6 +127,29 @@ workspace::put_work_rev(revision_t const write_data(rev_path, rev_data); } +void +workspace::set_work_state_to_new_root() +{ + set_work_state_unchanged(revision_id()); +} + +void +workspace::set_work_state_unchanged(revision_id const & rid) +{ + revision_t rev; + make_revision_for_workspace(rid, cset(), rev); + put_work_rev(rev); +} + +void +workspace::set_work_state(parent_map const & parents, + roster_t const & new_roster) +{ + revision_t rev; + make_revision_for_workspace(parents, new_roster); + put_work_rev(rev); +} + // structures derived from the work revision, the database, and possibly // the workspace @@ -159,7 +191,8 @@ void } void -workspace::get_current_roster_shape(roster_t & ros, node_id_source & nis) +workspace::get_current_roster_shape(parent_map & parents, + roster_t & ros, node_id_source & nis) { revision_t rev; get_work_rev(rev); @@ -418,7 +451,10 @@ workspace::maybe_update_inodeprints() temp_node_id_source nis; roster_t new_roster; - get_current_roster_shape(new_roster, nis); + { + parent_map parents; + get_current_roster_shape(parents, new_roster, nis); + } update_current_roster_from_filesystem(new_roster); parent_map parents; @@ -1240,7 +1276,10 @@ workspace::find_unknown_and_ignored(path roster_t new_roster; temp_node_id_source nis; - get_current_roster_shape(new_roster, nis); + { + parent_map parents; + get_current_roster_shape(parents, new_roster, nis); + } new_roster.extract_path_set(known); file_itemizer u(db, lua, known, unknown, ignored, mask); @@ -1259,9 +1298,10 @@ workspace::perform_additions(set is lexicographically // sorted). this is important in cases like @@ -1408,10 +1441,7 @@ workspace::perform_deletions(set bool bookkeep_only) { temp_node_id_source nis; + parent_map parents; roster_t new_roster; MM(new_roster); set< pair > renames; I(!srcs.empty()); - get_current_roster_shape(new_roster, nis); + get_current_roster_shape(parents, new_roster, nis); // validation. it's okay if the target exists as a file; we just won't // clobber it (in !--bookkeep-only mode). similarly, it's okay if the @@ -1455,8 +1486,8 @@ workspace::perform_rename(set // touch foo // mtn mv foo bar/foo where bar doesn't exist file_path parent = dst.dirname(); - N(get_path_status(parent) == path::directory, - F("destination path's parent directory %s/ doesn't exist") % parent); + N(get_path_status(parent) == path::directory, + F("destination path's parent directory %s/ doesn't exist") % parent); } renames.insert(make_pair(src, dpath)); @@ -1496,13 +1527,8 @@ workspace::perform_rename(set P(F("renaming %s to %s in workspace manifest") % i->first % i->second); } - parent_map parents; - get_parent_rosters(parents); + set_work_state(parents, new_roster); - revision_t new_work; - make_revision_for_workspace(parents, new_roster, new_work); - put_work_rev(new_work); - if (!bookkeep_only) for (set< pair >::const_iterator i = renames.begin(); i != renames.end(); i++) @@ -1541,9 +1567,10 @@ workspace::perform_pivot_root(file_path bool bookkeep_only) { temp_node_id_source nis; + parent_map parents; roster_t new_roster; MM(new_roster); - get_current_roster_shape(new_roster, nis); + get_current_roster_shape(parents, new_roster, nis); I(new_roster.has_root()); N(new_roster.has_node(new_root), @@ -1581,14 +1608,8 @@ workspace::perform_pivot_root(file_path cs.apply_to(e); } - { - parent_map parents; - get_parent_rosters(parents); + set_work_state(parents, new_roster); - revision_t new_work; - make_revision_for_workspace(parents, new_roster, new_work); - put_work_rev(new_work); - } if (!bookkeep_only) { content_merge_empty_adaptor cmea; @@ -1613,7 +1634,10 @@ workspace::perform_content_update(cset c "you must clean up and remove the %s directory") % detached); - get_current_roster_shape(new_roster, nis); + { + parent_map parents; + get_current_roster_shape(parents, new_roster, nis); + } new_roster.extract_path_set(known); workspace_itemizer itemizer(roster, known, nis); @@ -1635,7 +1659,10 @@ workspace::update_any_attrs() { temp_node_id_source nis; roster_t new_roster; - get_current_roster_shape(new_roster, nis); + { + parent_map parents; + get_current_roster_shape(parents, new_roster, nis); + } node_map const & nodes = new_roster.all_nodes(); for (node_map::const_iterator i = nodes.begin(); i != nodes.end(); ++i)