# # # patch "automate.cc" # from [b1f53aae5921c30444b8671a07c5c55ae3ee0a0b] # to [36060912ba341b40831791a08530893de5715809] # # patch "options_list.hh" # from [185432e32dc44b93821c965cd658d4de5354c1bb] # to [1f1eb3ce7a6a72870d0a42ef7f79b58eef621127] # # patch "tests/automate_inventory_options/__driver__.lua" # from [4fb7dcccf3839bf7767d1488f3ac2a347fb69d09] # to [e96e3d50ab1309fe882b71cc9be6c8bf5c61401d] # # patch "tests/automate_inventory_options/test_hooks.lua" # from [4c7ad3157746b50af10102b317498c574345d102] # to [65969e7f3ca931595755a65fddbf4032ad76b7a3] # ============================================================ --- automate.cc b1f53aae5921c30444b8671a07c5c55ae3ee0a0b +++ automate.cc 36060912ba341b40831791a08530893de5715809 @@ -546,7 +546,8 @@ inventory_rosters(roster_t const & old_r static void inventory_rosters(roster_t const & old_roster, roster_t const & new_roster, - node_restriction const & mask, + node_restriction const & nmask, + path_restriction const & pmask, inventory_map & inventory) { std::map old_paths; @@ -555,24 +556,30 @@ inventory_rosters(roster_t const & old_r node_map const & old_nodes = old_roster.all_nodes(); for (node_map::const_iterator i = old_nodes.begin(); i != old_nodes.end(); ++i) { - if (mask.includes(old_roster, i->first)) + if (nmask.includes(old_roster, i->first)) { file_path fp; old_roster.get_name(i->first, fp); - get_node_info(old_roster.get_node(i->first), inventory[fp].old_node); - old_paths[inventory[fp].old_node.id] = fp; + if (pmask.includes(fp)) + { + get_node_info(old_roster.get_node(i->first), inventory[fp].old_node); + old_paths[inventory[fp].old_node.id] = fp; + } } } node_map const & new_nodes = new_roster.all_nodes(); for (node_map::const_iterator i = new_nodes.begin(); i != new_nodes.end(); ++i) { - if (mask.includes(new_roster, i->first)) + if (nmask.includes(new_roster, i->first)) { file_path fp; new_roster.get_name(i->first, fp); - get_node_info(new_roster.get_node(i->first), inventory[fp].new_node); - new_paths[inventory[fp].new_node.id] = fp; + if (pmask.includes(fp)) + { + get_node_info(new_roster.get_node(i->first), inventory[fp].new_node); + new_paths[inventory[fp].new_node.id] = fp; + } } } @@ -584,10 +591,10 @@ inventory_rosters(roster_t const & old_r // There is no new node available; this is either a drop or a // rename to outside the current path restriction. - if (new_roster.has_node (i->first)) + if (new_roster.has_node(i->first)) { // record rename to outside restriction - new_roster.get_name (i->first, inventory[i->second].new_path); + new_roster.get_name(i->first, inventory[i->second].new_path); continue; } else @@ -617,10 +624,10 @@ inventory_rosters(roster_t const & old_r // There is no old node available; this is either added or a // rename from outside the current path restriction. - if (old_roster.has_node (i->first)) + if (old_roster.has_node(i->first)) { // record rename from outside restriction - old_roster.get_name (i->first, inventory[i->second].old_path); + old_roster.get_name(i->first, inventory[i->second].old_path); } else // added; no old path @@ -634,14 +641,14 @@ static void // paths as well, so the tree walker code will correctly identify them later // on or skips them if they should be excluded static void -inventory_expand_paths(roster_t const & old_roster, - roster_t const & new_roster, - node_restriction const & mask, - vector & includes, - vector & excludes) +inventory_determine_corresponding_paths(roster_t const & old_roster, + roster_t const & new_roster, + vector const & includes, + vector const & excludes, + vector & additional_includes, + vector & additional_excludes) { // at first check the includes vector - vector new_includes; for (int i=0, s=includes.size(); i new_excludes; for (int i=0, s=excludes.size(); i includes = args_to_paths(args); vector excludes = args_to_paths(app.opts.exclude_patterns); - node_restriction nmask(includes, excludes, app.opts.depth, old_roster, new_roster, app); - inventory_rosters(old_roster, new_roster, nmask, inventory); + if (!app.opts.no_corresponding_renames) + { + vector add_includes, add_excludes; + inventory_determine_corresponding_paths(old_roster, new_roster, + includes, excludes, + add_includes, add_excludes); - // ensure that the include/exclude paths contain the corresponding paths - // for the old/new roster items if restricted to such - inventory_expand_paths(old_roster, new_roster, nmask, includes, excludes); + copy(add_includes.begin(), add_includes.end(), + inserter(includes, includes.end())); + copy(add_excludes.begin(), add_excludes.end(), + inserter(excludes, excludes.end())); + } + + node_restriction nmask(includes, excludes, app.opts.depth, old_roster, new_roster, app); // skip the check of the workspace paths because some of them might // be missing and the user might want to query the recorded structure // of them anyways path_restriction pmask(includes, excludes, app.opts.depth, app, path_restriction::skip_check); + + inventory_rosters(old_roster, new_roster, nmask, pmask, inventory); inventory_filesystem(pmask, inventory, app); basic_io::printer pr; @@ -1007,8 +1019,18 @@ CMD_AUTOMATE(inventory, N_("[PATH]...") vector changes; inventory_determine_changes(item, old_roster, changes); - bool is_known = find(states.begin(), states.end(), "known") != states.end(); - if (is_known && changes.empty() && app.opts.no_unchanged) + bool is_tracked = + find(states.begin(), states.end(), "unknown") == states.end() && + find(states.begin(), states.end(), "ignored") == states.end(); + + bool has_changed = + find(states.begin(), states.end(), "rename_source") != states.end() || + find(states.begin(), states.end(), "rename_target") != states.end() || + find(states.begin(), states.end(), "added") != states.end() || + find(states.begin(), states.end(), "dropped") != states.end() || + !changes.empty(); + + if (is_tracked && !has_changed && app.opts.no_unchanged) continue; // ============================================================ --- options_list.hh 185432e32dc44b93821c965cd658d4de5354c1bb +++ options_list.hh 1f1eb3ce7a6a72870d0a42ef7f79b58eef621127 @@ -529,10 +529,10 @@ OPTSET(automate_inventory_opts) #endif OPTSET(automate_inventory_opts) -// These options take arguments, so they can be used with automate stdio. OPTVAR(automate_inventory_opts, bool, no_ignored, false) OPTVAR(automate_inventory_opts, bool, no_unknown, false) OPTVAR(automate_inventory_opts, bool, no_unchanged, false) +OPTVAR(automate_inventory_opts, bool, no_corresponding_renames, false) OPTION(automate_inventory_opts, no_ignored, false, "no-ignored", gettext_noop("don't output ignored files")) @@ -558,6 +558,14 @@ OPTION(automate_inventory_opts, no_uncha } #endif +OPTION(automate_inventory_opts, no_corresponding_renames, false, "no-corresponding-renames", + gettext_noop("don't output corresponding renames if restricted on such nodes")) +#ifdef option_bodies +{ + no_corresponding_renames = true; +} +#endif + // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- tests/automate_inventory_options/__driver__.lua 4fb7dcccf3839bf7767d1488f3ac2a347fb69d09 +++ tests/automate_inventory_options/__driver__.lua e96e3d50ab1309fe882b71cc9be6c8bf5c61401d @@ -1,4 +1,5 @@ -- Test 'automate inventory' options --no-ignored, --no-unchanged, --no-unknown +-- and --no-corresponding-renames mtn_setup() @@ -9,38 +10,87 @@ check(get("expected-no-unchanged.stdout" check(get("expected-no-ignored.stdout")) check(get("expected-no-unknown.stdout")) check(get("expected-no-unchanged.stdout")) +check(get("expected-renames-both.stdout")) +check(get("expected-renames-source.stdout")) +check(get("expected-renames-target.stdout")) +check(get("expected-renames-target-no-ignored.stdout")) +check(get("expected-renames-target-no-unknown.stdout")) -include ("common/test_utils_inventory.lua") +include("common/test_utils_inventory.lua") -mkdir ("source") +mkdir("source") addfile("source/source_1", "source_1") addfile("source/source_2", "source_2") commit() writefile("source/ignored_1", "ignored_1") writefile("source/unknown_1", "unknown_1") -writefile ("source/source_2", "source_2 changed") +writefile("source/source_2", "source_2 changed") +-- -- First with no options +-- check(mtn("automate", "inventory", "source"), 0, true, false) canonicalize("stdout") -check (readfile("expected-none.stdout") == readfile("stdout")) +check(readfile("expected-none.stdout") == readfile("stdout")) +-- +-- check --no-ignored, --no-unchanged, --no-unknown +-- +check(mtn("automate", "inventory", "source", "--no-unknown"), 0, true, false) +canonicalize("stdout") +check(readfile("expected-no-unknown.stdout") == readfile("stdout")) + +check(mtn("automate", "inventory", "source", "--no-unchanged"), 0, true, false) +canonicalize("stdout") +check(readfile("expected-no-unchanged.stdout") == readfile("stdout")) + check(mtn("automate", "inventory", "source", "--no-ignored"), 0, true, false) canonicalize("stdout") -check (readfile("expected-no-ignored.stdout") == readfile("stdout")) +check(readfile("expected-no-ignored.stdout") == readfile("stdout")) --- make sure 'automate stdio' handles inventory options +-- make sure 'automate stdio' handles at least one of the inventory options as well check(mtn("automate", "stdio"), 0, true, false, "o10:no-ignored0:e l9:inventory6:sourcee") canonicalize("stdout") -check (("0:0:l:364:" .. readfile("expected-no-ignored.stdout")) == readfile("stdout")) +check(("0:0:l:364:" .. readfile("expected-no-ignored.stdout")) == readfile("stdout")) -check(mtn("automate", "inventory", "source", "--no-unknown"), 0, true, false) +-- +-- now check --no-corresponding-renames +-- +check(mtn("mv", "source", "target"), 0, false, false) + +check(mtn("automate", "inventory", "source"), 0, true, false) canonicalize("stdout") -check (readfile("expected-no-unknown.stdout") == readfile("stdout")) +check(readfile("expected-renames-both.stdout") == readfile("stdout")) -check(mtn("automate", "inventory", "source", "--no-unchanged"), 0, true, false) +check(mtn("automate", "inventory", "target"), 0, true, false) canonicalize("stdout") -check (readfile("expected-no-unchanged.stdout") == readfile("stdout")) +check(readfile("expected-renames-both.stdout") == readfile("stdout")) +check(mtn("automate", "inventory", "source", "--no-corresponding-renames"), 0, true, false) +canonicalize("stdout") +check(readfile("expected-renames-source.stdout") == readfile("stdout")) + +check(mtn("automate", "inventory", "target", "--no-corresponding-renames"), 0, true, false) +canonicalize("stdout") +check(readfile("expected-renames-target.stdout") == readfile("stdout")) + +-- +-- check how --no-corresponding-renames works with the other options +-- + +-- since we restrict to the rename target, all nodes in there should be +-- marked as changed +check(mtn("automate", "inventory", "target", "--no-corresponding-renames", "--no-unchanged"), 0, true, false) +canonicalize("stdout") +check(readfile("expected-renames-target.stdout") == readfile("stdout")) + +check(mtn("automate", "inventory", "target", "--no-corresponding-renames", "--no-ignored"), 0, true, false) +canonicalize("stdout") +check(readfile("expected-renames-target-no-ignored.stdout") == readfile("stdout")) + +check(mtn("automate", "inventory", "target", "--no-corresponding-renames", "--no-unknown"), 0, true, false) +canonicalize("stdout") +check(readfile("expected-renames-target-no-unknown.stdout") == readfile("stdout")) + -- end of file ============================================================ --- tests/automate_inventory_options/test_hooks.lua 4c7ad3157746b50af10102b317498c574345d102 +++ tests/automate_inventory_options/test_hooks.lua 65969e7f3ca931595755a65fddbf4032ad76b7a3 @@ -1,7 +1,10 @@ function ignore_file(name) function ignore_file(name) - if (name == "source/ignored_1") then return true end + if (name == "source/ignored_1" or + name == "target/ignored_1") then + return true + end return false end function get_passphrase(keyid) - return keyid + return keyid end