The unified diff between revisions [220e18d5..] and [95c3202d..] is displayed below. It can also be downloaded as a raw diff.
#
#
# rename "contrib/mtnopt"
# to "util/mtnopt"
#
# rename "tests/clone_-b_no_dir"
# to "tests/clone_branch_no_dir"
#
# add_dir "tests/automate_get_options"
#
# add_dir "tests/automate_get_workspace_root"
#
# add_dir "tests/automate_show_conflicts"
#
# add_dir "tests/automate_show_conflicts_defaults"
#
# add_dir "tests/resolve_duplicate_name_conflict"
#
# add_dir "tests/util_mtnopt"
#
# add_dir "util"
#
# add_file "contrib/monotone-inotify.lua"
# content [c4941ceb6ec5981cc88f375533dace72b7284fcf]
#
# add_file "tests/automate_get_options/__driver__.lua"
# content [441807940397c9106b117ba8ce6caf273e0b7f1c]
#
# add_file "tests/automate_get_workspace_root/__driver__.lua"
# content [437c9b81ebdc37c489d62c3652eef3016d282441]
#
# add_file "tests/automate_inventory_ignore_dirs/expected_2.stderr"
# content [139fa2659365d1899a757ff8ef6191e6263064fe]
#
# add_file "tests/automate_inventory_ignore_dirs/expected_2.stdout"
# content [cd896018adbe95b59dd286c8f78080bb99073af7]
#
# add_file "tests/automate_show_conflicts/__driver__.lua"
# content [d5373d214d4fa6ce9e622aae99ff03f23e5e433b]
#
# add_file "tests/automate_show_conflicts/expected-attribute-attached.stdout"
# content [4ceb87a115b7810e89c6b39cf6564f3d64f4cc61]
#
# add_file "tests/automate_show_conflicts/expected-attribute-detached.stdout"
# content [40c709752502f9976b78f252e7bf7346e879255c]
#
# add_file "tests/automate_show_conflicts/expected-content-attached.stdout"
# content [6c39a0131b22693f4086fb68970e827a3241a287]
#
# add_file "tests/automate_show_conflicts/expected-content-detached.stdout"
# content [fb8495a17d8f6a59572cb87703c7f05af418b65d]
#
# add_file "tests/automate_show_conflicts/expected-directory-loop.stdout"
# content [de5f4fbfee1d8fdafde73535041ddde66207eb2a]
#
# add_file "tests/automate_show_conflicts/expected-duplicate-add-rename.stdout"
# content [960c1810ffd09fb5fb6e7623dd5740c623d2e46a]
#
# add_file "tests/automate_show_conflicts/expected-duplicate-adds.stdout"
# content [f62b2ef38c303a56d63f23849907a5e9a4c0af8c]
#
# add_file "tests/automate_show_conflicts/expected-duplicate-name-multiple-name-missing-root.stdout"
# content [97246345a094fdb4d824196a148ff03f163372fd]
#
# add_file "tests/automate_show_conflicts/expected-duplicate-renames.stdout"
# content [fcefa7860a93fb5a21ea56045a22c1d7085702eb]
#
# add_file "tests/automate_show_conflicts/expected-invalid-add.stdout"
# content [979bcb70f07c8c1bd1257abaac3ccc838685df16]
#
# add_file "tests/automate_show_conflicts/expected-invalid-rename.stdout"
# content [03f20ce606834c98052f061d9db45e98199e69e5]
#
# add_file "tests/automate_show_conflicts/expected-missing-root.stdout"
# content [94b47debd3848a1369db6c4c45123448f34f5766]
#
# add_file "tests/automate_show_conflicts/expected-multiple-name-plus-directory-loop.stdout"
# content [fb19db164690da0bfacc3023861bfbde3e0a6756]
#
# add_file "tests/automate_show_conflicts/expected-multiple-name-plus-duplicate-name.stdout"
# content [9fd3b1c4abfcf81218e7f1114cb110e9bdf63ab5]
#
# add_file "tests/automate_show_conflicts/expected-multiple-name-plus-orphan.stdout"
# content [11b1c86e6b665778c54def56ed4b25d9d2c672c2]
#
# add_file "tests/automate_show_conflicts/expected-multiple-names.stdout"
# content [9cdc729aed940d5504888465e20bb4ca30f8d5ba]
#
# add_file "tests/automate_show_conflicts/expected-orphaned-add.stdout"
# content [a935d1c389fa30701f15e2c01cd880ee3a1c8620]
#
# add_file "tests/automate_show_conflicts/expected-orphaned-rename.stdout"
# content [6096fa729c8ef741b7a64a7405984f601906c5bb]
#
# add_file "tests/automate_show_conflicts/expected-unrelated-projects.stdout"
# content [ee0741479e34ee1343e029dec1e206ca171716b4]
#
# add_file "tests/automate_show_conflicts_defaults/__driver__.lua"
# content [e89d6a7bdb7752205b89c8ac32d112030b254e48]
#
# add_file "tests/merge_with_conflicting_name_and_renamed_dir/expected.stdout"
# content [2e696c102e7388389e5117fd0cba1e736bef7ee3]
#
# add_file "tests/resolve_duplicate_name_conflict/__driver__.lua"
# content [fd81c83e6371e4065e784cb8dbf3b2bdf0c0d0cb]
#
# add_file "tests/util_mtnopt/__driver__.lua"
# content [746362d46856f53db9e04871879d73443cb7204b]
#
# patch "HACKING"
# from [b05dd82114101d138b4d85bd2cb401f8e9c98572]
# to [a94eadea2457641d2d23ddd8dab732b207197bfb]
#
# patch "Makefile.am"
# from [4bd4212a2e021abffa9f0151375e47988fd0c7ce]
# to [f38db1b6891b304f75527eb30853aa570ff15b4d]
#
# patch "NEWS"
# from [49a8c5b13ad1c7c93ad0499e5ab119e8fd8ce313]
# to [72bf0457e290fdae5f440ce81c7531fc65a88fc4]
#
# patch "asciik.cc"
# from [0682f911f2598d229d218fd28cc5964534bd3c65]
# to [8d87e9368e3f3ebd63df11e12610ac90ac2ee4e5]
#
# patch "automate.cc"
# from [b23eced8b6c237fd768369cf7d32ba6119f19fe4]
# to [c8d93c4266411e0dbee70e4144e2ac6c395c7789]
#
# patch "basic_io.cc"
# from [0e2ba2ebec547db8ee201b40856cbce01c8b38d1]
# to [5aacaa8dcf17e4113dbaf2e91b476a9b795ccbf5]
#
# patch "basic_io.hh"
# from [7978cce5b4f235c365101530ac8f8924a0516565]
# to [6b126a5b42e3eba99b5aa01b73d3b2f7ffce5b1c]
#
# patch "cmd_automate.cc"
# from [5f2e7462ce88f6f22c58a847c09e26a02e73a533]
# to [c196131d03786caa8968ea9e090142a375e364f1]
#
# patch "cmd_files.cc"
# from [3b7d2bf25e05b220868e16b7c7a05dd4a3d8d204]
# to [4476e4cbb2f0c770c4b043a0f507c76d739c6d0a]
#
# patch "cmd_merging.cc"
# from [387dcaa87e0c05f96894845520ed4ee46e227880]
# to [c00d7dd2a1dd4dda7da812ae6216b6ee391238b9]
#
# patch "cmd_netsync.cc"
# from [92564b21090c2ebc23734588bcaad5a6740b1c2f]
# to [6b39feccad350c30a4d3900619e180c47a01d0fc]
#
# patch "contrib/monotone.bash_completion"
# from [2c9594b25c576fec99b3502e41e5a07fb10191a1]
# to [5aff6649ff0ce10a7a993d891bc0033d23030593]
#
# patch "database.cc"
# from [9e10e5d55233691379b3c4855ff77de8aced5ada]
# to [0e55fc85ea2dfec7e34ed8de385881c60ea4316f]
#
# patch "diff_patch.cc"
# from [06f64d5def0166740f243dedf7fd6776662a0978]
# to [211424b28fdc3a5dcdae5a781feea97e1e915326]
#
# patch "diff_patch.hh"
# from [2f4ccb77db4094b7de55931464331e22537cf560]
# to [8386bfd9dc62a30e7173fca60d27adab6d02167b]
#
# patch "examples/display_branches.lua"
# from [f4d7d76a47fd04699f36fa079e801ab8d7e74dc6]
# to [656dc06747a5e55e1c1300b32bb25f13e140b758]
#
# patch "lru_writeback_cache.hh"
# from [615df6d41efa986779fcf78b3dab09c8217ea18a]
# to [fa05b036a2b82fe0b799c27168a75feee26e7692]
#
# patch "lua-testsuite.lua"
# from [8254404e53c3ad822023d7d80b059519e2694eba]
# to [41e44b694e1d68e32ba5bf9bca044a11f48f1028]
#
# patch "luaext_parse_basic_io.cc"
# from [e0dd6eaf52ad9523b67eae29bf67b26afd09f628]
# to [1e504c774c37a0a8b924146bf4c8b972d2134ff4]
#
# patch "merge.cc"
# from [4ebc61395a485c9eb2b2fd6e67eafa199fe5b39e]
# to [9059000487b5a7e6e6390175c376b45ca4f251f0]
#
# patch "monotone.texi"
# from [fa1738710d397b1262e70e512619f71f90157abf]
# to [c6f295ff19bdc6a6fc1fe1d4ec1a43d500f782dc]
#
# patch "netsync.cc"
# from [2302612f5e4d92846a2ec32a842efb077f09384d]
# to [22eda2f383261b7bb48b44fa3f77bee10a4e2f3b]
#
# patch "options_list.hh"
# from [8432925aa61ab0032d712f7a7fbb043b109f7bcb]
# to [a2b3cbf33d9686a72ab80da09489e9ea3bf5ee33]
#
# patch "paths.cc"
# from [d850c3efae62041b8003589817387e5877f63b01]
# to [dde6659e387c8890c96278ea29e3196bdf588139]
#
# patch "po/de.po"
# from [d99c2c2aeec39b1a0e19eac4969cb2879162bd7f]
# to [647bb39531da2f94d8788f5f0652215dbb4db5f4]
#
# patch "po/es.po"
# from [1731631569878c1ed69f324e17e2d3185fbd38be]
# to [8990a30618f02e101aaf8d73473e7e35931a69bf]
#
# patch "po/sv.po"
# from [4b3ea1556de493e41d5d8a3e82958a21b022b832]
# to [11a792b4d8a48302738edf51a3230b66c0b21725]
#
# patch "roster.cc"
# from [932a1eaa645faae04e0523ac971c997bcdeacb4f]
# to [9cebdc581039f2d117abc2c90c4230b2c9635166]
#
# patch "roster_merge.cc"
# from [b2fca269f9de878a4c50a48f2f437cc385db52a7]
# to [9bb39c2c87f92180b0a5db5697ff6ea15b82d25b]
#
# patch "roster_merge.hh"
# from [fb803cd207c21b77a69115552a6820664b607ba5]
# to [48d9aa743811732826e3f855a5759c1d61416984]
#
# patch "tester.cc"
# from [da1589e5c3cc77aa51b5658a71b613e6b1ec64db]
# to [144b85b2298949c9bbc303644bf972c36fd80c26]
#
# patch "tests/automate_cert/__driver__.lua"
# from [21c1631cb67da926ed7fdc1995db5dae2130bb05]
# to [a7f8e71581aa02eb61dcde8d6030eaa2a91aca8f]
#
# patch "tests/automate_heads/__driver__.lua"
# from [7b00f82a3172485381d6845352d14c1eacc29b3e]
# to [3e517ef05655a049ac5c0c121942e1e66cc1e209]
#
# patch "tests/automate_identify/__driver__.lua"
# from [41b1aa7f4bc84e92f8b3dddb0b135e3def94aae3]
# to [88f42966d628b429faff486d1001cb517476ebef]
#
# patch "tests/automate_inventory/__driver__.lua"
# from [e12ed1600e4dc846891575fd758971461ff8512f]
# to [3dfb9ba03b255abf9470e6242d016f98fc4b4429]
#
# patch "tests/automate_inventory_ignore_dirs/__driver__.lua"
# from [96a76f43b12f8d6113c7ce0f43a4fc473bf042c3]
# to [6233a5c18211c0718b96af2800b393076a7585ae]
#
# patch "tests/automate_inventory_ignore_dirs/expected.stderr"
# from [41fc6d7fb22c6a3040b0ba0c7708be080a4a8716]
# to [5a2123381f2129c6ea4b4a2646a35da60663d635]
#
# patch "tests/automate_inventory_ignore_dirs/local_hooks.lua"
# from [e6cf0fd64140311801fb6ecc380cdeb7dfd3e1ac]
# to [1fcc22bbcc34898a69aaafcdeec3c06bf69c152f]
#
# patch "tests/automate_inventory_options/__driver__.lua"
# from [8e5f7502832947e0046dd024081501e3954b0f6b]
# to [a5b9f432caf66ce4e5de60641dc8c018b54bf0c1]
#
# patch "tests/automate_inventory_options/expected-no-ignored.stdout"
# from [84cbd13b0b318aec4666e1037e206ead17fd4a07]
# to [8d87531d633398ec074c79a1196ab3fe3461437c]
#
# patch "tests/automate_inventory_options/expected-no-unchanged.stdout"
# from [a8d26be14f5a35ce9bf0d4e1ae187ccac67798e6]
# to [098d4e5d46fd9f072d9fe4b5ce57fa297806b09c]
#
# patch "tests/automate_inventory_options/expected-no-unknown.stdout"
# from [9d05880af03b2376cad55fd548a75c2e794582db]
# to [6f89120110a15a4979689a11d984037858245f60]
#
# patch "tests/automate_inventory_options/expected-none.stdout"
# from [5ae35126c2b94ab6d8827179ba22adab576dfc3b]
# to [8b56b8744aa7c03ece83e8f947a989b7afa66ed1]
#
# patch "tests/automate_inventory_options/expected-renames-both.stdout"
# from [82d839d12bd564927eb02d1afd5c87b36bfe8d0b]
# to [30c148e193838a02d0e041f8befc0c7d6b29c646]
#
# patch "tests/automate_inventory_options/expected-renames-target-no-ignored.stdout"
# from [5f9276b122a989d08eef334367323715c25f9d47]
# to [208a14ecc012d3880e47db2af06eef124f83ce1c]
#
# patch "tests/automate_inventory_options/expected-renames-target-no-unknown.stdout"
# from [bc9f2c6714b0ca56740f0b22cc4e8d6f5ed5f0cd]
# to [ae4773015e235754db26b51ceab35cf5944e7a5e]
#
# patch "tests/automate_inventory_options/expected-renames-target.stdout"
# from [956807cb660ef81894a614a0384c010c889327d0]
# to [fc960c1c87ed1111a6dd8dee9a5e9423aaf28c78]
#
# patch "tests/automate_inventory_restricted/__driver__.lua"
# from [ab30596e5444d0134d518cf7e14f40e99a475ae8]
# to [727c314a4b0ed6b29354a650e2f7721f4d753fc0]
#
# patch "tests/automate_keys/__driver__.lua"
# from [42ad71325d1df9437aa6623996367bbeaa28fe93]
# to [31fa511454527e8a340fa29dbcb7a1e4c8cc8cda]
#
# patch "tests/clone_branch_no_dir/__driver__.lua"
# from [6261c4ed37c1a5e10ea7e27aacdf722287ec8682]
# to [79f7583ce446afedfea0330cf7b9ea059f17b2ea]
#
# patch "tests/clone_creates__MTN_log/__driver__.lua"
# from [b55d72be85979711d50af45907e134f18428a405]
# to [8c7d4dfb26d1a16a1607d6fc85fc17c6fca9df5f]
#
# patch "tests/clone_creates_right__MTN_options/__driver__.lua"
# from [99090f6f660254a145fd2d892282bca37a723361]
# to [695c3942a9dfe2396f40ab60b378537c114b8dec]
#
# patch "tests/clone_validates_target_directory/__driver__.lua"
# from [bb4ba95dd27e59251ea97e3e108800223c52874a]
# to [1e23852712399fd277092c8ba08bbd164179e873]
#
# patch "tests/clone_warning_with_multiple_heads/__driver__.lua"
# from [7185de1271934179a95cf11aa12b561404323c61]
# to [365ab7fea2b251874a264a9c21ec0ca17770c14c]
#
# patch "tests/common/test_utils_inventory.lua"
# from [d0343ce781bb1284387d194b7a3e50d2b7a52c0d]
# to [780502a124f1af69badad0d2e53b0b957cfa3caa]
#
# patch "tests/conflict_messages/__driver__.lua"
# from [4294e488db07d33260abd6ab276fc85d9c2dd508]
# to [a681cb85649f5e5ce53bad9b8ef8f2300c22d9d8]
#
# patch "tests/merge_with_conflicting_name_and_renamed_dir/__driver__.lua"
# from [a321dc78aef12dc78e2a47ab269f2ccd280f35ff]
# to [8cc726016628bfe2c7a6be98a86e45ccc07e58fa]
#
# patch "work.cc"
# from [0261cdf7dbc3baed0cdfc0e75a3a858f64eefa97]
# to [011e065cb66b572d0e10f382c70949c973e90679]
#
============================================================
--- contrib/monotone-inotify.lua c4941ceb6ec5981cc88f375533dace72b7284fcf
+++ contrib/monotone-inotify.lua c4941ceb6ec5981cc88f375533dace72b7284fcf
@@ -0,0 +1,84 @@
+-- Copyright (c) 2007 by Richard Levitte <richard@levitte.org>
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+--
+-- 1. Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+--
+-- 2. Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+-- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------------------
+-- Usage:
+--
+-- NOTE: THIS SOFTWARE IS ONLY MEANT FOR SERVER PROCESSES!
+-- Anything else will fail miserably!
+--
+-- in your server's monotonerc, add the following include:
+--
+-- include("/PATH/TO/monotone-inotify.lua")
+--
+-- You may want to change the following variables:
+--
+-- MI_flagfile
+-- The absolute path for a file that will simply
+-- be touched by the note_netsync_end hook.
+-- Default: CONFDIR/monotone-netsync-end.flag
+--
+-- WARNING! Do not try to store anything in that
+-- file, it will get erased...
+-------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+-- Variables
+-------------------------------------------------------------------------------
+MI_default_flagfile = get_confdir() .. "/monotone-netsync-end.flag"
+MI_default_debug = false
+
+
+if not MI_flagfile then MI_flagfile = MI_default_flagfile end
+if not MI_debug then MI_debug = MI_default_debug end
+
+-------------------------------------------------------------------------------
+-- Local hack of the note_netsync_* functions
+-------------------------------------------------------------------------------
+push_netsync_notifier(
+ {
+ ["end"] =
+ function (nonce, status,
+ bytes_in, bytes_out,
+ certs_in, certs_out,
+ revs_in, revs_out,
+ keys_in, keys_out,
+ ...)
+ if MI_debug then
+ io.stderr:write("note_netsync_end: ",
+ string.format("%d certs, %d revs, %d keys",
+ certs_in, revs_in, keys_in),
+ "\n")
+ end
+ if certs_in > 0 or revs_in > 0 or keys_in > 0 then
+ if MI_debug then
+ io.stderr:write("note_netsync_end: touching ", MI_flagfile, "\n")
+ end
+ local handle = io.open(MI_flagfile, "w+")
+ io.close(handle)
+ end
+ end
+ })
============================================================
--- tests/automate_get_options/__driver__.lua 441807940397c9106b117ba8ce6caf273e0b7f1c
+++ tests/automate_get_options/__driver__.lua 441807940397c9106b117ba8ce6caf273e0b7f1c
@@ -0,0 +1,20 @@
+
+mtn_setup()
+
+-- We don't check options with paths in them; on Windows, sometimes
+-- the paths have '\' for directory separators, sometimes '/', and we
+-- don't have a way to predict which or fix them.
+check(mtn("automate", "get_option", "branch"), 0, true, false)
+canonicalize("stdout")
+check("testbranch\n" == readfile("stdout"))
+
+check(mtn("automate", "get_option", "key"), 0, true, false)
+canonicalize("stdout")
+check("tester@test.net\n" == readfile("stdout"))
+
+-- Ensure that 'get_options' gets the workspace options even when run via stdio
+check(mtn_ws_opts("automate", "stdio"), 0, true, false, "l10:get_option6:branche")
+canonicalize("stdout")
+check("0:0:l:11:testbranch\n" == readfile("stdout"))
+
+-- end of file
============================================================
--- tests/automate_get_workspace_root/__driver__.lua 437c9b81ebdc37c489d62c3652eef3016d282441
+++ tests/automate_get_workspace_root/__driver__.lua 437c9b81ebdc37c489d62c3652eef3016d282441
@@ -0,0 +1,10 @@
+
+mtn_setup()
+
+local cwd = chdir(".")
+
+mkdir("foo")
+addfile("foo/bar", "text")
+
+check(indir("foo",mtn("automate", "get_workspace_root")), 0, true, false)
+check(qgrep("^"..cwd.."$", "stdout"))
============================================================
--- tests/automate_inventory_ignore_dirs/expected_2.stderr 139fa2659365d1899a757ff8ef6191e6263064fe
+++ tests/automate_inventory_ignore_dirs/expected_2.stderr 139fa2659365d1899a757ff8ef6191e6263064fe
@@ -0,0 +1,6 @@
+ignore_file: 'keys': false
+ignore_file: 'source': false
+ignore_file: 'source/ignored_dir': true
+ignore_file: 'source/ignored_1': true
+ignore_file: 'source/ignored_dir/oops': true
+mtn: warning: 'source/ignored_dir/oops' is both known and ignored; it will be shown as 'missing'. Check .mtn-ignore.
============================================================
--- tests/automate_inventory_ignore_dirs/expected_2.stdout cd896018adbe95b59dd286c8f78080bb99073af7
+++ tests/automate_inventory_ignore_dirs/expected_2.stdout cd896018adbe95b59dd286c8f78080bb99073af7
@@ -0,0 +1,31 @@
+ path "source"
+new_type "directory"
+ fs_type "directory"
+ status "added" "known"
+
+ path "source/ignored_1"
+fs_type "file"
+ status "ignored"
+
+ path "source/ignored_dir"
+new_type "directory"
+ fs_type "directory"
+ status "added" "known"
+
+ path "source/ignored_dir/oops"
+new_type "file"
+ fs_type "none"
+ status "added" "missing"
+ changes "content"
+
+ path "source/source_1"
+new_type "file"
+ fs_type "file"
+ status "added" "known"
+ changes "content"
+
+ path "source/source_2"
+new_type "file"
+ fs_type "file"
+ status "added" "known"
+ changes "content"
============================================================
--- tests/automate_show_conflicts/__driver__.lua d5373d214d4fa6ce9e622aae99ff03f23e5e433b
+++ tests/automate_show_conflicts/__driver__.lua d5373d214d4fa6ce9e622aae99ff03f23e5e433b
@@ -0,0 +1,540 @@
+-- Create the various non-content conflict cases, check that
+-- 'automate show_conflict' displays them properly.
+--
+-- Cases are created in the same way as in conflict_messages/__driver__.lua
+
+mtn_setup()
+
+function setup(branch)
+ remove("_MTN")
+ remove("foo")
+ remove("bar")
+ remove("baz")
+ remove(branch)
+ check(mtn("setup", ".", "--branch", branch), 0, false, false)
+end
+
+function create_second()
+ commit(branch .. "-propagate")
+ second = base_revision()
+ check(mtn("cert", second, "branch", branch))
+end
+
+function check_asc()
+ expected = "expected-" .. branch .. ".stdout"
+ check(get(expected))
+ check(mtn("automate", "show_conflicts", first, second), 0, true, false)
+ canonicalize("stdout")
+ check(readfile(expected) == readfile("stdout"))
+end
+
+-- missing root conflict
+
+branch = "missing-root"
+setup(branch)
+
+mkdir("foo")
+addfile("foo/foo", branch .. "-foofoo")
+commit(branch)
+
+base = base_revision()
+
+check(mtn("co", "--branch", branch, branch), 0, false, false)
+check(indir(branch, mtn("pivot_root", "foo", "bar")), 0, true, true)
+check(indir(branch, mtn("commit", "--message", "commit")), 0, false, false)
+
+first = indir(branch, {base_revision})[1]()
+
+check(mtn("drop", "--recursive", "foo"), 0, false, false)
+
+create_second()
+check_asc()
+
+-- invalid name add
+
+branch = "invalid-add"
+setup(branch)
+
+mkdir("foo")
+addfile("foo/foo", branch .. "-foofoo")
+commit(branch)
+
+base = base_revision()
+
+check(mtn("co", "--branch", branch, branch), 0, false, false)
+check(indir(branch, mtn("pivot_root", "foo", "bar")), 0, true, true)
+check(indir(branch, mtn("commit", "--message", "commit")), 0, false, false)
+
+first = indir(branch, {base_revision})[1]()
+
+mkdir("foo/_MTN")
+addfile("foo/_MTN/foo", branch .. "-foo")
+addfile("foo/_MTN/bar", branch .. "-bar")
+
+create_second()
+check_asc()
+
+
+-- invalid name rename
+
+branch = "invalid-rename"
+setup(branch)
+
+mkdir("foo")
+mkdir("bad")
+addfile("foo/foo", branch .. "-foofoo")
+addfile("bad/_MTN", branch .. "--bar")
+commit(branch)
+
+base = base_revision()
+
+check(mtn("co", "--branch", branch, branch), 0, false, false)
+check(indir(branch, mtn("pivot_root", "foo", "bar")), 0, true, true)
+check(indir(branch, mtn("commit", "--message", "commit")), 0, false, false)
+first = indir(branch, {base_revision})[1]()
+
+check(mtn("mv", "bad/_MTN", "foo/_MTN"), 0, false, false)
+
+create_second()
+check_asc()
+
+
+-- directory loop conflict
+
+branch = "directory-loop"
+setup(branch)
+
+mkdir("foo")
+mkdir("bar")
+addfile("foo/foo", branch .. "-foofoo")
+addfile("bar/bar", branch .. "-barbar")
+commit(branch)
+
+base = base_revision()
+
+check(mtn("mv", "foo", "bar"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+check(mtn("mv", "bar", "foo"), 0, false, false)
+
+create_second()
+check_asc()
+
+
+
+-- orphaned add
+
+branch = "orphaned-add"
+setup(branch)
+
+mkdir("foo")
+addfile("foo/foo", branch .. "-foofoo")
+commit(branch)
+
+base = base_revision()
+
+addfile("foo/bar", branch .. "-foobar")
+commit(branch)
+
+check(mtn("mv", "foo/bar", "foo/baz"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+remove("foo")
+check(mtn("drop", "--recursive", "foo"), 0, false, false)
+
+create_second()
+check_asc()
+
+
+-- orphaned rename
+
+branch = "orphaned-rename"
+setup(branch)
+
+mkdir("foo")
+addfile("foo/foo", branch .. "-foofoo")
+addfile("bar", branch .. "-bar")
+commit(branch)
+
+base = base_revision()
+
+check(mtn("mv", "bar", "foo/bar"), 0, false, false)
+commit(branch)
+check(mtn("mv", "foo/bar", "foo/baz"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+remove("foo")
+check(mtn("drop", "--recursive", "foo"), 0, false, false)
+
+create_second()
+check_asc()
+
+
+
+-- multiple name conflict
+
+branch = "multiple-names"
+setup(branch)
+
+addfile("foo", branch .. "-foo")
+commit(branch)
+base = base_revision()
+
+check(mtn("mv", "foo", "bar"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+check(mtn("mv", "foo", "baz"), 0, false, false)
+
+create_second()
+check_asc()
+
+
+
+-- duplicate name conflict (adds)
+
+branch = "duplicate-adds"
+setup(branch)
+
+addfile("foo", branch .. "-foo")
+commit(branch)
+base = base_revision()
+
+addfile("xxx", branch .. "-xxx")
+commit(branch)
+
+check(mtn("mv", "xxx", "bar"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+addfile("bar", branch .. "-bar2")
+
+create_second()
+check_asc()
+
+
+-- duplicate name conflict (renames)
+
+branch = "duplicate-renames"
+setup(branch)
+
+addfile("foo", branch .. "-foo")
+addfile("bar", branch .. "-bar")
+
+commit(branch)
+base = base_revision()
+
+check(mtn("mv", "foo", "abc"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+check(mtn("mv", "bar", "abc"), 0, false, false)
+
+create_second()
+check_asc()
+
+
+-- duplicate name conflict (add-rename)
+
+branch = "duplicate-add-rename"
+setup(branch)
+
+addfile("foo", branch .. "-foo")
+
+commit(branch)
+base = base_revision()
+
+check(mtn("mv", "foo", "bar"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+addfile("bar", branch .. "-bar")
+
+create_second()
+check_asc()
+
+
+
+-- attribute conflict on attached node
+
+branch = "attribute-attached"
+setup(branch)
+
+addfile("foo", branch .. "-foo")
+check(mtn("attr", "set", "foo", "attr1", "value1"), 0, false, false)
+check(mtn("attr", "set", "foo", "attr2", "value2"), 0, false, false)
+commit(branch)
+base = base_revision()
+
+check(mtn("attr", "set", "foo", "attr1", "valueX"), 0, false, false)
+check(mtn("attr", "set", "foo", "attr2", "valueY"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+check(mtn("attr", "set", "foo", "attr1", "valueZ"), 0, false, false)
+check(mtn("attr", "drop", "foo", "attr2"), 0, false, false)
+
+create_second()
+check_asc()
+
+
+
+-- attribute conflict on detached node
+
+branch = "attribute-detached"
+setup(branch)
+
+addfile("foo", branch .. "-foo")
+check(mtn("attr", "set", "foo", "attr1", "value1"), 0, false, false)
+check(mtn("attr", "set", "foo", "attr2", "value2"), 0, false, false)
+commit(branch)
+base = base_revision()
+
+check(mtn("attr", "set", "foo", "attr1", "valueX"), 0, false, false)
+check(mtn("attr", "set", "foo", "attr2", "valueY"), 0, false, false)
+check(mtn("mv", "foo", "bar"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+check(mtn("attr", "set", "foo", "attr1", "valueZ"), 0, false, false)
+check(mtn("attr", "drop", "foo", "attr2"), 0, false, false)
+check(mtn("mv", "foo", "baz"), 0, false, false)
+
+create_second()
+check_asc()
+
+
+
+-- content conflict on attached node
+
+branch = "content-attached"
+setup(branch)
+
+addfile("foo", branch .. "-foo")
+addfile("bar", branch .. "-bar\none\ntwo\nthree")
+addfile("baz", branch .. "-baz\naaa\nbbb\nccc")
+commit(branch)
+base = base_revision()
+
+writefile("foo", branch .. "-foo first revision")
+writefile("bar", branch .. "-bar\nzero\none\ntwo\nthree")
+writefile("baz", branch .. "-baz\nAAA\nbbb\nccc")
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+writefile("foo", branch .. "-foo second revision")
+writefile("bar", branch .. "-bar\none\ntwo\nthree\nfour")
+writefile("baz", branch .. "-baz\naaa\nbbb\nCCC")
+
+create_second()
+check_asc()
+
+
+-- content conflict on detached node
+
+branch = "content-detached"
+setup(branch)
+
+addfile("foo", branch .. "-foo")
+commit(branch)
+base = base_revision()
+
+writefile("foo", "foo first revision")
+check(mtn("mv", "foo", "bar"), 0, false, false)
+
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+writefile("foo", "foo second revision")
+check(mtn("mv", "foo", "baz"), 0, false, false)
+
+create_second()
+check_asc()
+
+
+-- multiple name plus duplicate name
+
+branch = "multiple-name-plus-duplicate-name"
+setup(branch)
+
+addfile("foo", branch .. "-foo")
+commit(branch)
+base = base_revision()
+
+check(mtn("mv", "foo", "aaa"), 0, false, false)
+addfile("bbb", branch .. "-bbb")
+
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+remove("aaa")
+remove("bbb")
+
+check(mtn("mv", "foo", "bbb"), 0, false, false)
+addfile("aaa", branch .. "-aaa")
+
+-- this doesn't result in a duplicate name conflict because the multiple name
+-- conflict prevents foo from being attached in the result roster
+
+create_second()
+check_asc()
+
+
+-- multiple name plus orphan
+
+branch = "multiple-name-plus-orphan"
+setup(branch)
+
+mkdir("a")
+mkdir("b")
+check(mtn("add", "a"), 0, false, false)
+check(mtn("add", "b"), 0, false, false)
+addfile("foo", branch .. "-foo")
+commit(branch)
+base = base_revision()
+
+check(mtn("mv", "foo", "a"), 0, false, false)
+check(mtn("rm", "b"), 0, false, false)
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+check(mtn("mv", "foo", "b"), 0, false, false)
+check(mtn("rm", "a"), 0, false, false)
+
+-- this doesn't result in an orphan conflict because the multiple name
+-- conflict prevents foo from being attached in the result roster
+
+create_second()
+check_asc()
+
+
+-- multiple name plus directory loop
+
+branch = "multiple-name-plus-directory-loop"
+setup(branch)
+
+mkdir("a")
+mkdir("b")
+mkdir("foo")
+check(mtn("add", "a"), 0, false, false)
+check(mtn("add", "b"), 0, false, false)
+check(mtn("add", "foo"), 0, false, false)
+commit(branch)
+base = base_revision()
+
+check(mtn("mv", "foo", "a"), 0, false, false)
+check(mtn("mv", "b", "a/foo"), 0, false, false)
+
+commit(branch)
+first = base_revision()
+
+revert_to(base)
+
+check(mtn("mv", "foo", "b"), 0, false, false)
+check(mtn("mv", "a", "b/foo"), 0, false, false)
+
+-- this doesn't result in a directory loop conflict because the multiple name
+-- conflict prevents foo from being attached in the result roster
+
+create_second()
+check_asc()
+
+
+
+-- duplicate name plus multiple name plus missing root
+
+-- the old root directory is pivoted out to aaa on one side and bbb on the other
+-- causing a multiple name conflict
+
+-- a new root directory is pivoted in from foo on one side and bar on the other
+-- causing a duplicate name conflict on ""
+
+-- these conflicts leave the root dir detached causing a missing root conflict
+
+branch = "duplicate-name-multiple-name-missing-root"
+setup(branch)
+
+mkdir("foo")
+mkdir("bar")
+addfile("foo/foo", branch .. "-foofoo")
+addfile("bar/bar", branch .. "-barbar")
+commit(branch)
+
+base = base_revision()
+
+dir1 = branch .. "-1"
+remove(dir1)
+
+check(mtn("co", "--revision", base, "--branch", branch, dir1), 0, false, false)
+check(indir(dir1, mtn("pivot_root", "foo", "aaa")), 0, true, true)
+check(indir(dir1, mtn("commit", "--message", "commit")), 0, false, false)
+
+first = indir(dir1, {base_revision})[1]()
+
+dir2 = branch .. "-2"
+remove(dir2)
+
+check(mtn("co", "--revision", base, "--branch", branch, dir2), 0, false, false)
+check(indir(dir2, mtn("pivot_root", "bar", "bbb")), 0, true, true)
+check(indir(dir2, mtn("commit", "--message", "commit")), 0, false, false)
+
+second = indir(dir2, {base_revision})[1]()
+
+check(mtn("cert", second, "branch", branch))
+
+check_asc()
+
+
+-- unrelated projects
+
+branch = "unrelated-projects"
+setup(branch)
+
+copy("_MTN/revision", "clean")
+
+addfile("foo", branch .. "-foo first")
+commit(branch)
+
+first = base_revision()
+
+copy("clean", "_MTN/revision")
+
+addfile("foo", branch .. "-foo second")
+
+check(mtn("commit", "--message", "commit", "--branch", branch .. "-propagate"), 0, false, false)
+
+second = base_revision()
+
+check(mtn("cert", second, "branch", branch))
+
+check_asc()
+
+-- end of file
============================================================
--- tests/automate_show_conflicts/expected-attribute-attached.stdout 4ceb87a115b7810e89c6b39cf6564f3d64f4cc61
+++ tests/automate_show_conflicts/expected-attribute-attached.stdout 4ceb87a115b7810e89c6b39cf6564f3d64f4cc61
@@ -0,0 +1,27 @@
+ left [febd58929375e5820fb73dd258d3f53d77014aa9]
+ right [feec4de91f4698bc77f1b50c82ee4513cc47ae8f]
+ancestor [c79cbcfb99f7a5e547815669b150dd3d9a28a598]
+
+ conflict attribute
+ node_type "file"
+ attr_name "attr1"
+ ancestor_name "foo"
+ancestor_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+ left_name "foo"
+ left_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+ left_attr_value "valueX"
+ right_name "foo"
+ right_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+right_attr_value "valueZ"
+
+ conflict attribute
+ node_type "file"
+ attr_name "attr2"
+ ancestor_name "foo"
+ancestor_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+ left_name "foo"
+ left_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+ left_attr_value "valueY"
+ right_name "foo"
+ right_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+right_attr_state "dropped"
============================================================
--- tests/automate_show_conflicts/expected-attribute-detached.stdout 40c709752502f9976b78f252e7bf7346e879255c
+++ tests/automate_show_conflicts/expected-attribute-detached.stdout 40c709752502f9976b78f252e7bf7346e879255c
@@ -0,0 +1,39 @@
+ left [67ba83fd417fede6cb6de14d90783e93261e5210]
+ right [2654ad872bf18d40260aaf59e8ce0058bf54bddd]
+ancestor [d81bb87785fa1bbe11aed1ca6d3340d288b61b78]
+
+ conflict multiple_names
+ left_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+ left_name "bar"
+ left_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+ right_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+ right_name "baz"
+ right_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+
+ conflict attribute
+ node_type "file"
+ attr_name "attr1"
+ ancestor_name "foo"
+ancestor_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+ left_name "bar"
+ left_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+ left_attr_value "valueX"
+ right_name "baz"
+ right_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+right_attr_value "valueZ"
+
+ conflict attribute
+ node_type "file"
+ attr_name "attr2"
+ ancestor_name "foo"
+ancestor_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+ left_name "bar"
+ left_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+ left_attr_value "valueY"
+ right_name "baz"
+ right_file_id [e80910e54d0bdea1b6d295ada320b87aaf9fdc23]
+right_attr_state "dropped"
============================================================
--- tests/automate_show_conflicts/expected-content-attached.stdout 6c39a0131b22693f4086fb68970e827a3241a287
+++ tests/automate_show_conflicts/expected-content-attached.stdout 6c39a0131b22693f4086fb68970e827a3241a287
@@ -0,0 +1,30 @@
+ left [0b9e5111f3e13ccb1727bc936aff962020dc9809]
+ right [49d6a10f5f09b064a35f1700966795ae698f0555]
+ancestor [7d854bf031420b7a5c1cafcb908f1020593196a8]
+
+ conflict content
+ node_type "file"
+ ancestor_name "bar"
+ancestor_file_id [f0ef49fe92167fe2a086588019ffcff7ea561786]
+ left_name "bar"
+ left_file_id [08cd878106a93ce2ef036a32499c1432adb3ee0d]
+ right_name "bar"
+ right_file_id [0cf419dd93d38b2daaaf1f5e0f3ec647745b9690]
+
+ conflict content
+ node_type "file"
+ ancestor_name "baz"
+ancestor_file_id [55320c8cee4b87edb47ec6d7e678af53eed2c717]
+ left_name "baz"
+ left_file_id [4ba6aabe8949871079bb70b5ae0cd64d502def46]
+ right_name "baz"
+ right_file_id [ac923b3bc65d6638cdee243bd46b57d3e14ce4ee]
+
+ conflict content
+ node_type "file"
+ ancestor_name "foo"
+ancestor_file_id [26798f895189be8aa9a366011e3253c738966010]
+ left_name "foo"
+ left_file_id [e6b176b142ff08e09a1d8f836b5c65d9f650c0ef]
+ right_name "foo"
+ right_file_id [5d4daf4aff681dfcb97cca561ec06298489fafa3]
============================================================
--- tests/automate_show_conflicts/expected-content-detached.stdout fb8495a17d8f6a59572cb87703c7f05af418b65d
+++ tests/automate_show_conflicts/expected-content-detached.stdout fb8495a17d8f6a59572cb87703c7f05af418b65d
@@ -0,0 +1,24 @@
+ left [7a4c8dae08866a0c65a5a136eeca82f85e028837]
+ right [40a6208fa7406a393823d33aecae509c80db37b4]
+ancestor [936159c798b9bb3f5d0f871a0dda158a844e9348]
+
+ conflict multiple_names
+ left_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [50bf338804db2685a575124c8c8371d06b65c523]
+ left_name "bar"
+ left_file_id [f1bb6fff2ad16d67143d89fc374ede7abec5d437]
+ right_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [50bf338804db2685a575124c8c8371d06b65c523]
+ right_name "baz"
+ right_file_id [b966b2d35b99e456cb0c55e4573ef0b1b155b4a9]
+
+ conflict content
+ node_type "file"
+ ancestor_name "foo"
+ancestor_file_id [50bf338804db2685a575124c8c8371d06b65c523]
+ left_name "bar"
+ left_file_id [f1bb6fff2ad16d67143d89fc374ede7abec5d437]
+ right_name "baz"
+ right_file_id [b966b2d35b99e456cb0c55e4573ef0b1b155b4a9]
============================================================
--- tests/automate_show_conflicts/expected-directory-loop.stdout de5f4fbfee1d8fdafde73535041ddde66207eb2a
+++ tests/automate_show_conflicts/expected-directory-loop.stdout de5f4fbfee1d8fdafde73535041ddde66207eb2a
@@ -0,0 +1,11 @@
+ left [be04cb44902df12f3b36bf0efabba784547ccd34]
+ right [7cd48d9599eee2a67e8c510112659c0d313fb1df]
+ancestor [08ccbb14523a09d342568ce27a1b9f631d42aa9c]
+
+ conflict directory_loop_created
+ left_type "renamed directory"
+ancestor_name "foo"
+ left_name "bar/foo"
+ right_type "renamed directory"
+ancestor_name "bar"
+ right_name "foo/bar"
============================================================
--- tests/automate_show_conflicts/expected-duplicate-add-rename.stdout 960c1810ffd09fb5fb6e7623dd5740c623d2e46a
+++ tests/automate_show_conflicts/expected-duplicate-add-rename.stdout 960c1810ffd09fb5fb6e7623dd5740c623d2e46a
@@ -0,0 +1,13 @@
+ left [446ea80c3f78fca1cfdb84aad55939f4e635ddc0]
+ right [367cb265f641ead9834f497ff3cbcb2b85ffe1fa]
+ancestor [d9ff68aa530d581731b0e5739b3494963cd89e91]
+
+ conflict duplicate_name
+ left_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [c6864a8456855c48afe83488a47501fe8b94bd57]
+ left_name "bar"
+ left_file_id [c6864a8456855c48afe83488a47501fe8b94bd57]
+ right_type "added file"
+ right_name "bar"
+ right_file_id [c809d71002ec57a2f1d10221f05993012a491436]
============================================================
--- tests/automate_show_conflicts/expected-duplicate-adds.stdout f62b2ef38c303a56d63f23849907a5e9a4c0af8c
+++ tests/automate_show_conflicts/expected-duplicate-adds.stdout f62b2ef38c303a56d63f23849907a5e9a4c0af8c
@@ -0,0 +1,11 @@
+ left [36e62406e9792ad64f7af73c5192d2e4e53306c8]
+ right [2b96f8e6ed2bb566c22ebcbdd06d34d1043c237f]
+ancestor [56cafb3485be6d40923bacaddcd19cde63433028]
+
+ conflict duplicate_name
+ left_type "added file"
+ left_name "bar"
+ left_file_id [ba4637112ee3e55a6106d647d6c4e04a6643f8eb]
+ right_type "added file"
+ right_name "bar"
+right_file_id [fe6d523f607e2f2fc0f0defad3bda0351a95a337]
============================================================
--- tests/automate_show_conflicts/expected-duplicate-name-multiple-name-missing-root.stdout 97246345a094fdb4d824196a148ff03f163372fd
+++ tests/automate_show_conflicts/expected-duplicate-name-multiple-name-missing-root.stdout 97246345a094fdb4d824196a148ff03f163372fd
@@ -0,0 +1,25 @@
+ left [254fd127afd769a33979a843f5e3d8f2457097e6]
+ right [6e0b7ffd0171d72db85dfc54234a78a35dd76cf3]
+ancestor [5bc669f00cf90b76dd38077827565b624d823756]
+
+ conflict missing_root
+ left_type "pivoted root"
+ancestor_name "foo"
+ right_type "pivoted root"
+ancestor_name "bar"
+
+ conflict multiple_names
+ left_type "renamed directory"
+ancestor_name ""
+ left_name "aaa"
+ right_type "renamed directory"
+ancestor_name ""
+ right_name "bbb"
+
+ conflict duplicate_name
+ left_type "renamed directory"
+ancestor_name "foo"
+ left_name ""
+ right_type "renamed directory"
+ancestor_name "bar"
+ right_name ""
============================================================
--- tests/automate_show_conflicts/expected-duplicate-renames.stdout fcefa7860a93fb5a21ea56045a22c1d7085702eb
+++ tests/automate_show_conflicts/expected-duplicate-renames.stdout fcefa7860a93fb5a21ea56045a22c1d7085702eb
@@ -0,0 +1,15 @@
+ left [1fc2275efef8645a25e267ae47686e57e50ca1e1]
+ right [497d6e99c8b79ef5848aa862154f496432f07709]
+ancestor [680280e4dcc9fcf60721e6ac9157d98ac5f94c37]
+
+ conflict duplicate_name
+ left_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [918f3642b57a5e2dd13ee874e3dc2518a53ab4b4]
+ left_name "abc"
+ left_file_id [918f3642b57a5e2dd13ee874e3dc2518a53ab4b4]
+ right_type "renamed file"
+ ancestor_name "bar"
+ancestor_file_id [bdf46a521d5f1dd54c31dda15e99ff6b0c80394a]
+ right_name "abc"
+ right_file_id [bdf46a521d5f1dd54c31dda15e99ff6b0c80394a]
============================================================
--- tests/automate_show_conflicts/expected-invalid-add.stdout 979bcb70f07c8c1bd1257abaac3ccc838685df16
+++ tests/automate_show_conflicts/expected-invalid-add.stdout 979bcb70f07c8c1bd1257abaac3ccc838685df16
@@ -0,0 +1,9 @@
+ left [507f1209e78415722129e65633a8d6a9dd6003f1]
+ right [cdf9a4171d1d386f9ecb83218a11df6c5fa75c6c]
+ancestor [36e6935d3fddf349ef829125e8b6d41ea85d1db8]
+
+ conflict invalid_name
+ left_type "pivoted root"
+ancestor_name "foo"
+ right_type "added directory"
+ right_name "foo/_MTN"
============================================================
--- tests/automate_show_conflicts/expected-invalid-rename.stdout 03f20ce606834c98052f061d9db45e98199e69e5
+++ tests/automate_show_conflicts/expected-invalid-rename.stdout 03f20ce606834c98052f061d9db45e98199e69e5
@@ -0,0 +1,12 @@
+ left [2bf9335ed387a7f1f082b0bc5ecdffa303d8393f]
+ right [459c32f4c7b4676d47e23aff2bd67c1e2eae5f09]
+ancestor [e7f711a68627ccae4aded5907fc80516ea1215fd]
+
+ conflict invalid_name
+ left_type "pivoted root"
+ ancestor_name "foo"
+ right_type "renamed file"
+ ancestor_name "bad/_MTN"
+ancestor_file_id [629d9e5d254241abf4b46f108fb53189e314e41d]
+ right_name "foo/_MTN"
+ right_file_id [629d9e5d254241abf4b46f108fb53189e314e41d]
============================================================
--- tests/automate_show_conflicts/expected-missing-root.stdout 94b47debd3848a1369db6c4c45123448f34f5766
+++ tests/automate_show_conflicts/expected-missing-root.stdout 94b47debd3848a1369db6c4c45123448f34f5766
@@ -0,0 +1,16 @@
+ left [532ab5011ea9e64aa212d4ea52363b1b8133d5ba]
+ right [b94a03a922c2c281a88d8988db64e76a32edb6a1]
+ancestor [ead03530f5fefe50c9010157c42c0ebe18086559]
+
+ conflict missing_root
+ left_type "pivoted root"
+ancestor_name "foo"
+ right_type "deleted directory"
+ancestor_name "foo"
+
+ conflict orphaned_directory
+ right_type "deleted directory"
+ancestor_name ""
+ left_type "renamed directory"
+ancestor_name ""
+ left_name "bar"
============================================================
--- tests/automate_show_conflicts/expected-multiple-name-plus-directory-loop.stdout fb19db164690da0bfacc3023861bfbde3e0a6756
+++ tests/automate_show_conflicts/expected-multiple-name-plus-directory-loop.stdout fb19db164690da0bfacc3023861bfbde3e0a6756
@@ -0,0 +1,11 @@
+ left [4e25e44deef167f640248e542916736b649e3044]
+ right [0b37ed4689ee191cdd4bd26e5233511329b17032]
+ancestor [27169065f28ccfb64678ac168b3805796bd9e5ae]
+
+ conflict multiple_names
+ left_type "renamed directory"
+ancestor_name "foo"
+ left_name "a/foo"
+ right_type "renamed directory"
+ancestor_name "foo"
+ right_name "b/foo"
============================================================
--- tests/automate_show_conflicts/expected-multiple-name-plus-duplicate-name.stdout 9fd3b1c4abfcf81218e7f1114cb110e9bdf63ab5
+++ tests/automate_show_conflicts/expected-multiple-name-plus-duplicate-name.stdout 9fd3b1c4abfcf81218e7f1114cb110e9bdf63ab5
@@ -0,0 +1,15 @@
+ left [424a7237e21522fd09878f486acbb8807cae59e6]
+ right [ef9b007adf6e49cc6b7e5317d860fb5716f418e9]
+ancestor [621e8ed86b46adcc57cd6abec90ecc41481a3e3b]
+
+ conflict multiple_names
+ left_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [eaf183d079563812d0c6860225ea9e4e0e2ebc20]
+ left_name "aaa"
+ left_file_id [eaf183d079563812d0c6860225ea9e4e0e2ebc20]
+ right_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [eaf183d079563812d0c6860225ea9e4e0e2ebc20]
+ right_name "bbb"
+ right_file_id [eaf183d079563812d0c6860225ea9e4e0e2ebc20]
============================================================
--- tests/automate_show_conflicts/expected-multiple-name-plus-orphan.stdout 11b1c86e6b665778c54def56ed4b25d9d2c672c2
+++ tests/automate_show_conflicts/expected-multiple-name-plus-orphan.stdout 11b1c86e6b665778c54def56ed4b25d9d2c672c2
@@ -0,0 +1,15 @@
+ left [0c9b6d79dc8842d0440be2b10a8bf4015d1114b9]
+ right [894db59b5fe6bcc4a22cfc1e06e5865b2bd888b1]
+ancestor [e487f26d5c464b381743e394923b7fd44b00705e]
+
+ conflict multiple_names
+ left_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [f53efd5c0abb89e4c292f9c0e5709e0cd95aec4a]
+ left_name "a/foo"
+ left_file_id [f53efd5c0abb89e4c292f9c0e5709e0cd95aec4a]
+ right_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [f53efd5c0abb89e4c292f9c0e5709e0cd95aec4a]
+ right_name "b/foo"
+ right_file_id [f53efd5c0abb89e4c292f9c0e5709e0cd95aec4a]
============================================================
--- tests/automate_show_conflicts/expected-multiple-names.stdout 9cdc729aed940d5504888465e20bb4ca30f8d5ba
+++ tests/automate_show_conflicts/expected-multiple-names.stdout 9cdc729aed940d5504888465e20bb4ca30f8d5ba
@@ -0,0 +1,15 @@
+ left [872b02c3aaa3b8ee6acf7e00e67108d5aaa8cb31]
+ right [bf62726ad7c36e553cb8906906866962786e52c0]
+ancestor [560b97068441495b17d8924f6122a1c47213a08b]
+
+ conflict multiple_names
+ left_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [3dc9e2f630ea9c3e60e8947d41c4150b88340ea0]
+ left_name "bar"
+ left_file_id [3dc9e2f630ea9c3e60e8947d41c4150b88340ea0]
+ right_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [3dc9e2f630ea9c3e60e8947d41c4150b88340ea0]
+ right_name "baz"
+ right_file_id [3dc9e2f630ea9c3e60e8947d41c4150b88340ea0]
============================================================
--- tests/automate_show_conflicts/expected-orphaned-add.stdout a935d1c389fa30701f15e2c01cd880ee3a1c8620
+++ tests/automate_show_conflicts/expected-orphaned-add.stdout a935d1c389fa30701f15e2c01cd880ee3a1c8620
@@ -0,0 +1,10 @@
+ left [140a1d712e5e7368dc88766144e0975746f27b9a]
+ right [872259407b5e1445c6b463768243ddaf531bd73a]
+ancestor [cce148761e33b0abbaa1c072ee913dcc23d7bfc3]
+
+ conflict orphaned_file
+ right_type "deleted directory"
+ancestor_name "foo"
+ left_type "added file"
+ left_name "foo/baz"
+ left_file_id [f5122a7f896cb2dd7ecaa84be89c94ab09c15101]
============================================================
--- tests/automate_show_conflicts/expected-orphaned-rename.stdout 6096fa729c8ef741b7a64a7405984f601906c5bb
+++ tests/automate_show_conflicts/expected-orphaned-rename.stdout 6096fa729c8ef741b7a64a7405984f601906c5bb
@@ -0,0 +1,12 @@
+ left [4ceae2a74d9d0d7341d2cd01a71c9e84eb1fefa7]
+ right [16a19ace8ec26cd2ed13c7e727a3021e82a2204f]
+ancestor [b5f52dbc0dc530adffbdd140a7de5b129cf74f29]
+
+ conflict orphaned_file
+ right_type "deleted directory"
+ ancestor_name "foo"
+ left_type "renamed file"
+ ancestor_name "bar"
+ancestor_file_id [ac4c6d06436632e017bb7d3ea241734e8899f8ce]
+ left_name "foo/baz"
+ left_file_id [ac4c6d06436632e017bb7d3ea241734e8899f8ce]
============================================================
--- tests/automate_show_conflicts/expected-unrelated-projects.stdout ee0741479e34ee1343e029dec1e206ca171716b4
+++ tests/automate_show_conflicts/expected-unrelated-projects.stdout ee0741479e34ee1343e029dec1e206ca171716b4
@@ -0,0 +1,11 @@
+ left [161e426c3b0c3f98d0be225f69d6f893ce8e0442]
+ right [0e3260f51acd1e98c40666557eb6c0eefeae5f02]
+ancestor []
+
+conflict missing_root
+
+ conflict duplicate_name
+ left_type "added directory"
+ left_name ""
+right_type "added directory"
+right_name ""
============================================================
--- tests/automate_show_conflicts_defaults/__driver__.lua e89d6a7bdb7752205b89c8ac32d112030b254e48
+++ tests/automate_show_conflicts_defaults/__driver__.lua e89d6a7bdb7752205b89c8ac32d112030b254e48
@@ -0,0 +1,80 @@
+-- Test 'automate show_conflicts' argument defaults
+--
+-- See automate_show_conflicts for all conflict cases
+
+mtn_setup()
+include ("common/test_utils_inventory.lua")
+
+-- Get a non-empty base revision, then create three heads
+addfile("randomfile", "blah blah blah")
+commit("testbranch", "base_1")
+base_1 = base_revision()
+
+-- Abe adds conflict files
+addfile("checkout.sh", "checkout.sh abe 1")
+addfile("thermostat.c", "thermostat westinghouse")
+commit("testbranch", "abe_1")
+abe_1 = base_revision()
+
+revert_to(base_1)
+
+-- Beth adds non-conflict files
+addfile("user_guide.text", "really cool stuff")
+commit("testbranch", "base_2")
+base_2 = base_revision()
+
+-- Beth adds conflict files
+addfile("checkout.sh", "checkout.sh beth 1")
+addfile("thermostat.c", "thermostat honeywell beth")
+commit("testbranch", "beth_1")
+beth_1 = base_revision()
+
+revert_to(base_2)
+
+-- Chuck adds conflict files
+addfile("checkout.sh", "checkout.sh beth 1")
+addfile("thermostat.c", "thermostat honeywell chuck")
+commit("testbranch", "chuck_1")
+chuck_1 = base_revision()
+
+-- Check that 'automate show_conflicts' picks the same heads to
+-- compare first as 'merge' does. Use workspace options
+check(mtn("merge"), 1, false, false)
+-- mtn: [left] 19ab79c40805c9dc5e25d0b6fa5134291e0b42d9 = beth_1
+-- mtn: [right] d8a8bc9623c1ff9c0a5c082e40f0ff8ec6b43e72 = chuck_1
+
+check(mtn_ws_opts("automate", "show_conflicts"), 0, true, false)
+parsed = parse_basic_io(readfile("stdout"))
+
+check_basic_io_line (1, parsed[1], "left", beth_1)
+check_basic_io_line (2, parsed[2], "right", chuck_1)
+check_basic_io_line (3, parsed[3], "ancestor", base_2)
+
+-- In mtn 0.40 and earlier, this was broken, because automate stdio
+-- did not re-read the workspace options for each command, so the
+-- branch was null.
+check(mtn("automate", "stdio"), 0, true, false, "l14:show_conflictse")
+parsed = parse_basic_io(string.sub (readfile("stdout"), 11))
+check_basic_io_line (1, parsed[1], "left", beth_1)
+check_basic_io_line (2, parsed[2], "right", chuck_1)
+check_basic_io_line (3, parsed[3], "ancestor", base_2)
+
+-- Check that 'automate show_conflicts' works outside workspace when options are specified
+non_ws_dir = make_temp_dir()
+check(indir(non_ws_dir, mtn_outside_ws("automate", "show_conflicts", "--branch=testbranch")), 0, true, false)
+
+parsed = parse_basic_io(readfile("stdout"))
+
+check_basic_io_line (1, parsed[1], "left", beth_1)
+check_basic_io_line (2, parsed[2], "right", chuck_1)
+check_basic_io_line (3, parsed[3], "ancestor", base_2)
+
+-- Check error message when outside workspace when branch not specified
+check(indir(non_ws_dir, mtn_outside_ws("automate", "show_conflicts")), 1, false, true)
+check(qgrep("misuse: please specify a branch, with --branch=BRANCH", "stderr"))
+
+-- Check error message for wrong arg count
+check(indir(non_ws_dir, mtn_outside_ws("automate", "show_conflicts", "rev1")), 1, false, true)
+check(qgrep("wrong argument count", "stderr"))
+
+-- end of file
============================================================
--- tests/merge_with_conflicting_name_and_renamed_dir/expected.stdout 2e696c102e7388389e5117fd0cba1e736bef7ee3
+++ tests/merge_with_conflicting_name_and_renamed_dir/expected.stdout 2e696c102e7388389e5117fd0cba1e736bef7ee3
@@ -0,0 +1,11 @@
+ left [3e5ae9c2084d1ab530cd9690bac5e45ee6db7ade]
+ right [e7d401d9de91696feaf17569337d10ed6e02a9b5]
+ancestor [51ccdc67277ec1461e1140df66fd00d56db3e7b5]
+
+ conflict duplicate_name
+ left_type "added file"
+ left_name "foo/x"
+ left_file_id [75e12a4830b87d440b8ecadbdbcdf20842278d30]
+ right_type "added file"
+ right_name "bar/x"
+right_file_id [53059abba1a72c7aff34a3eaf7fef10ed65541ce]
============================================================
--- tests/resolve_duplicate_name_conflict/__driver__.lua fd81c83e6371e4065e784cb8dbf3b2bdf0c0d0cb
+++ tests/resolve_duplicate_name_conflict/__driver__.lua fd81c83e6371e4065e784cb8dbf3b2bdf0c0d0cb
@@ -0,0 +1,69 @@
+-- Test/demonstrate handling of a duplicate name conflict; Abe and
+-- Beth add files with the same names.
+--
+-- For checkout.sh, the user intent is that there be
+-- one file with that name; the contents should be merged.
+--
+-- For thermostat.c, there should be two files;
+-- thermostat-westinghouse.c and thermostat-honeywell.c
+
+mtn_setup()
+include ("common/test_utils_inventory.lua")
+
+-- Get a non-empty base revision
+addfile("randomfile", "blah blah blah")
+commit()
+base = base_revision()
+
+-- Abe adds conflict files
+addfile("checkout.sh", "checkout.sh abe 1")
+addfile("thermostat.c", "thermostat westinghouse")
+commit("testbranch", "abe_1")
+abe_1 = base_revision()
+
+revert_to(base)
+
+-- Beth adds files, and attempts to merge
+addfile("checkout.sh", "checkout.sh beth 1")
+addfile("thermostat.c", "thermostat honeywell")
+commit("testbranch", "beth_1")
+beth_1 = base_revision()
+
+-- This fails due to duplicate name conflicts
+check(mtn("merge"), 1, false, false)
+
+-- Beth fixes the conflicts.
+--
+-- For checkout.sh, she retrieves Abe's version to merge with hers,
+-- using 'automate get_file_of'. This requires knowing the revision id
+-- of Abe's commit, which we get from 'automate show_conflicts'.
+--
+-- For thermostat.c, she renames her version, letting Abe rename his.
+
+check (mtn("automate", "show_conflicts"), 0, true, false)
+parsed = parse_basic_io(readfile("stdout"))
+
+-- The Lua parser returns the 'conflict <symbol>' line as two lines
+-- with no values, so the line count here seems odd.
+check_basic_io_line (1, parsed[1], "left", abe_1) -- 1337..
+check_basic_io_line (2, parsed[2], "right", beth_1) -- d5f1..
+check_basic_io_line (3, parsed[3], "ancestor", base)
+
+check_basic_io_line (8, parsed[8], "left_file_id", "61b8d4fb0e5d78be111f691b955d523c782fa92e")
+
+-- mtn is not up to actually doing the merge of checkout.sh yet, so we
+-- just drop beth's version
+
+check (mtn ("drop", "checkout.sh"), 0, false, false)
+check (mtn ("rename", "thermostat.c", "thermostat-honeywell.c"), 0, false, false)
+commit()
+
+-- This succeeds
+check(mtn("merge"), 0, false, false)
+
+check(mtn("update"), 0, false, false)
+
+check("checkout.sh abe 1" == readfile("checkout.sh"))
+
+-- end of file
+
============================================================
--- tests/util_mtnopt/__driver__.lua 746362d46856f53db9e04871879d73443cb7204b
+++ tests/util_mtnopt/__driver__.lua 746362d46856f53db9e04871879d73443cb7204b
@@ -0,0 +1,21 @@
+mtn_setup()
+
+-- Make sure we test the monotone source for mtnopt, not whatever the
+-- user happens to have in PATH
+getstd ("../util/mtnopt", "mtnopt")
+
+normalized_testroot = normalize_path (test.root)
+
+-- check default operation
+
+-- MinGW does not process the shebang in mtnopt; must invoke sh directly
+-- Vista will probably need to skip this test
+check({"/bin/sh", "./mtnopt"}, 0, true)
+check(qgrep('^MTN_database="' .. normalized_testroot .. '/test.db";$', "stdout"))
+check(qgrep('^MTN_branch="testbranch";$', "stdout"))
+
+-- check operation with a specific key and just returning the value
+check({'/bin/sh', './mtnopt', '-v', '-kbranch'}, 0, true)
+check(not qgrep('^' .. normalized_testroot .. '/test.db$', "stdout"))
+check(qgrep('^testbranch$', "stdout"))
+
============================================================
--- HACKING b05dd82114101d138b4d85bd2cb401f8e9c98572
+++ HACKING a94eadea2457641d2d23ddd8dab732b207197bfb
@@ -31,7 +31,7 @@ The appropriate astyle options are:
The appropriate astyle options are:
-astyle --style=gnu -s2 -p
+astyle --style=gnu -s2 -p
monotone's source includes a number of third party libraries. These have
been imported from upstream, and should retain the original coding style of
@@ -283,7 +283,7 @@ have a convention for their position and
Because many functions take some of these objects as arguments, we
have a convention for their position and order: all such arguments
-appear first within the overall argument list, and in the order of
+appear first within the overall argument list, and in the order of
the list below.
* "app_state" is being phased out; it used to be an umbrella object
@@ -302,6 +302,9 @@ the list below.
appear in function arguments. Instead, pass down specific fields
that are relevant to the lower-level code.
+ * When adding new options, separate words with dash "-" not
+ underscore "_"; dash is easier to type.
+
* "lua_hooks" holds the Lua interpreter handle and all the associated
state, in particular all the hook functions that the user may
override. It is, unfortunately, not possible to pass around single
============================================================
--- Makefile.am 4bd4212a2e021abffa9f0151375e47988fd0c7ce
+++ Makefile.am f38db1b6891b304f75527eb30853aa570ff15b4d
@@ -344,6 +344,8 @@ EXTRA_PROGRAMS =
noinst_PROGRAMS = txt2c
EXTRA_PROGRAMS =
+bin_SCRIPTS = mtnopt
+
mtn_SOURCES = $(MOST_SOURCES) monotone.cc
nodist_mtn_SOURCES = std_hooks.c schema.c
@@ -720,6 +722,10 @@ txt2c: txt2c.cc
cmp -s $@.tmp $@ || mv -f $@.tmp $@
rm -f $@.tmp
+# Support for scripts
+%: util/%
+ cp $< $@
+
# This construct causes --strip-trailing to be applied only when
# generating package_revision.c.
TXT2CFLAGS =
============================================================
--- NEWS 49a8c5b13ad1c7c93ad0499e5ab119e8fd8ce313
+++ NEWS 72bf0457e290fdae5f440ce81c7531fc65a88fc4
@@ -1,23 +1,47 @@
-??? ??? ?? ???????? UTC 2008
+??? ??? ?? ??:??:?? UTC ????
- 0.41 release
+ 0.41 release.
+ Changes
+
+ - mtn clone now takes a branch argument rather than a branch option
+ which is more what people expect given the the fact that
+ mtn push/pull/sync do not use a branch option either
+
+ - mtn automate inventory will show the birth revision for any file
+ that has been committed.
+
Bugs fixed
- - If the options --db or --keydir were previously specified for a
+ - If the options --db or --keydir were previously specified for a
command which was executed inside a workspace and one or both
- option arguments were invalid (f.e. invalid paths), they were
+ option arguments were invalid (f.e. invalid paths), they were
still written to _MTN/options of the particular workspace.
- This lead to errors on any subsequent command which used these
+ This lead to errors on any subsequent command which used these
options. This bug is fixed in so far that basic file type
checks are applied on both options, so its no longer possible
to set non-existing paths accidently or use a path to a directory
as option argument for --db.
- - If a key clash occurs on a netsync operation, i.e. two different
- keys with the same key id are encountered, mtn now fails cleanly
+ - If a key clash occurs on a netsync operation, i.e. two different
+ keys with the same key id are encountered, mtn now fails cleanly
and provides further guidance how to proceed.
-
+
+ - It was previously not possible to clone a branch / database
+ anonymously; this has been fixed.
+
+ - automate identified was broken in 0.40 when used over stdio, i.e.
+ the output of the command did not get into the right output
+ channel; this has been fixed
+
+ New features
+
+ - Add 'automate show_conflicts' command
+
+ - Add 'automate get_workspce_root' command
+
+ Internal
+
Fri Apr 11 22:50:44 UTC 2008
0.40 release.
============================================================
--- asciik.cc 0682f911f2598d229d218fd28cc5964534bd3c65
+++ asciik.cc 8d87e9368e3f3ebd63df11e12610ac90ac2ee4e5
@@ -118,6 +118,7 @@ Loop:
#include "project.hh"
#include "database.hh"
#include "revision.hh"
+#include "transforms.hh"
using std::insert_iterator;
using std::max;
@@ -272,13 +273,13 @@ asciik::try_draw(vector<revision_id> con
set<pair<size_t, size_t> > preservation_links;
bool have_shift = false;
- for (size_t i = 0; i < curr_items; ++i)
+ for (size_t i = 0; i < curr_items; ++i)
{
- if (idx(curr_row, i) != ghost)
+ if (idx(curr_row, i) != ghost)
{
vector<revision_id>::const_iterator found =
find(next_row.begin(), next_row.end(), idx(curr_row, i));
- if (found != next_row.end())
+ if (found != next_row.end())
{
size_t j = distance(next_row.begin(), found);
size_t d = i>j ? i-j : j-i;
@@ -394,6 +395,6 @@ CMD(asciik, "asciik", "", CMD_REF(debug)
set<revision_id> parents;
db.get_revision_parents(*rev, parents);
parents.erase(ghost); // remove the fake parent that root nodes have
- graph.print(*rev, parents, rev->inner()());
+ graph.print(*rev, parents, encode_hexenc(rev->inner()()));
}
}
============================================================
--- automate.cc b23eced8b6c237fd768369cf7d32ba6119f19fe4
+++ automate.cc c8d93c4266411e0dbee70e4144e2ac6c395c7789
@@ -17,7 +17,7 @@
#include <boost/bind.hpp>
#include <boost/function.hpp>
-#include <boost/lexical_cast.hpp>
+#include "lexical_cast.hh"
#include <boost/tuple/tuple.hpp>
#include "app_state.hh"
@@ -830,6 +830,7 @@ namespace
symbol const old_path("old_path");
symbol const new_path("new_path");
symbol const status("status");
+ symbol const birth("birth");
symbol const changes("changes");
}
}
@@ -879,7 +880,17 @@ inventory_determine_states(workspace & w
if (item.fs_type == path::nonexistent)
{
if (item.new_node.exists)
- states.push_back("missing");
+ {
+ states.push_back("missing");
+
+ // If this node is in a directory that is ignored in .mtn-ignore,
+ // we will output this warning. Note that we don't detect a known
+ // file that is ignored but not in an ignored directory.
+ if (work.ignore_file(fs_path))
+ W(F("'%s' is both known and ignored; "
+ "it will be shown as 'missing'. Check .mtn-ignore.")
+ % fs_path);
+ }
}
else // exists on filesystem
{
@@ -960,6 +971,23 @@ inventory_determine_changes(inventory_it
}
}
+static revision_id
+inventory_determine_birth(inventory_item const & item,
+ roster_t const & old_roster,
+ marking_map const & old_marking)
+{
+ revision_id rid;
+ if (old_roster.has_node(item.new_node.id))
+ {
+ node_t node = old_roster.get_node(item.new_node.id);
+ marking_map::const_iterator m = old_marking.find(node->self);
+ I(m != old_marking.end());
+ marking_t mark = m->second;
+ rid = mark.birth_revision;
+ }
+ return rid;
+}
+
// Name: inventory
// Arguments: [PATH]...
// Added in: 1.0
@@ -995,6 +1023,7 @@ CMD_AUTOMATE(inventory, N_("[PATH]...")
F("this command can only be used in a single-parent workspace"));
roster_t new_roster, old_roster = parent_roster(parents.begin());
+ marking_map old_marking = parent_marking(parents.begin());
temp_node_id_source nis;
work.get_current_roster_shape(db, nis, new_roster);
@@ -1052,6 +1081,9 @@ CMD_AUTOMATE(inventory, N_("[PATH]...")
vector<string> changes;
inventory_determine_changes(item, old_roster, changes);
+ revision_id birth_revision =
+ inventory_determine_birth(item, old_roster, old_marking);
+
bool is_tracked =
find(states.begin(), states.end(), "unknown") == states.end() &&
find(states.begin(), states.end(), "ignored") == states.end();
@@ -1113,6 +1145,9 @@ CMD_AUTOMATE(inventory, N_("[PATH]...")
//
// finally output the previously recorded states and changes
//
+ if (!birth_revision.inner()().empty())
+ st.push_binary_pair(syms::birth, birth_revision.inner());
+
I(!states.empty());
st.push_str_multi(syms::status, states);
@@ -1248,7 +1283,7 @@ CMD_AUTOMATE(get_current_revision, N_("[
excluded, join_words(execid));
rev.check_sane();
N(rev.is_nontrivial(), F("no changes to commit"));
-
+
calculate_ident(rev, ident);
write_revision(rev, dat);
@@ -2220,6 +2255,27 @@ CMD_AUTOMATE(drop_db_variables, N_("DOMA
}
}
+// Name: drop_db_variables
+// Arguments:
+// none
+// Changes:
+// 8.0 (added)
+// Purpose:
+// To show the path of the workspace root for the current directory.
+// Output format:
+// A path
+// Error conditions:
+// a runtime exception is thrown if the current directory isn't part
+// of a workspace.
+CMD_AUTOMATE(get_workspace_root, "",
+ N_("Prints the workspace root for the current directory"),
+ "",
+ options::opts::none)
+{
+ workspace work(app);
+ output << get_current_working_dir() << '\n';
+}
+
// Local Variables:
// mode: C++
// fill-column: 76
============================================================
--- basic_io.cc 0e2ba2ebec547db8ee201b40856cbce01c8b38d1
+++ basic_io.cc 5aacaa8dcf17e4113dbaf2e91b476a9b795ccbf5
@@ -97,6 +97,15 @@ void basic_io::stanza::push_str_pair(sym
indent = k().size();
}
+void basic_io::stanza::push_str_pair(symbol const & k, symbol const & v)
+{
+ // Note that this value is a symbol, not a string; the Lua basic_io parser
+ // will return this pair as two lines with no values.
+ entries.push_back(make_pair(k, v()));
+ if (k().size() > indent)
+ indent = k().size();
+}
+
void basic_io::stanza::push_file_pair(symbol const & k, file_path const & v)
{
push_str_pair(k, v.as_internal());
============================================================
--- basic_io.hh 7978cce5b4f235c365101530ac8f8924a0516565
+++ basic_io.hh 6b126a5b42e3eba99b5aa01b73d3b2f7ffce5b1c
@@ -258,6 +258,7 @@ namespace basic_io
void push_binary_triple(symbol const & k, std::string const & n,
id const & v);
void push_str_pair(symbol const & k, std::string const & v);
+ void push_str_pair(symbol const & k, symbol const & v);
void push_str_triple(symbol const & k, std::string const & n,
std::string const & v);
void push_file_pair(symbol const & k, file_path const & v);
============================================================
--- cmd_automate.cc 5f2e7462ce88f6f22c58a847c09e26a02e73a533
+++ cmd_automate.cc c196131d03786caa8968ea9e090142a375e364f1
@@ -18,6 +18,7 @@
#include "lua.hh"
#include "lua_hooks.hh"
#include "database.hh"
+#include "work.hh"
using std::istream;
using std::make_pair;
@@ -40,6 +41,10 @@ namespace commands {
string const & desc,
options::options_type const & opts) :
command(name, "", CMD_REF(automate), false, false, params, abstract,
+ // We set use_workspace_options true, because all automate
+ // commands need a database, and they expect to get the database
+ // name from the workspace options, even if they don't need a
+ // workspace for anything else.
desc, true, opts, false)
{
}
@@ -419,6 +424,16 @@ CMD_AUTOMATE(stdio, "",
automate const * acmd = reinterpret_cast< automate const * >(cmd);
opts = options::opts::globals() | acmd->opts();
+
+ if (cmd->use_workspace_options())
+ {
+ // Re-read the ws options file, rather than just copying
+ // the options from the previous apts.opts object, because
+ // the file may have changed due to user activity.
+ workspace::check_ws_format();
+ workspace::get_ws_options(app.opts);
+ }
+
opts.instantiate(&app.opts).from_key_value_pairs(params);
// set a fixed ticker type regardless what the user wants to
============================================================
--- cmd_files.cc 3b7d2bf25e05b220868e16b7c7a05dd4a3d8d204
+++ cmd_files.cc 4476e4cbb2f0c770c4b043a0f507c76d739c6d0a
@@ -245,7 +245,7 @@ CMD_AUTOMATE(identify, N_("PATH"),
id ident;
calculate_ident(dat, ident);
- cout << ident << '\n';
+ output << ident << '\n';
}
static void
============================================================
--- cmd_merging.cc 387dcaa87e0c05f96894845520ed4ee46e227880
+++ cmd_merging.cc c00d7dd2a1dd4dda7da812ae6216b6ee391238b9
@@ -1,3 +1,4 @@
+// Copyright (C) 2008 Stephen Leake <stephen_leake@stephe-leake.org>
// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
//
// This program is made available under the GNU GPL version 2.0 or
@@ -12,6 +13,7 @@
#include <iostream>
#include <iomanip>
+#include "basic_io.hh"
#include "cmd.hh"
#include "diff_patch.hh"
#include "merge.hh"
@@ -365,6 +367,49 @@ merge_two(options & opts, lua_hooks & lu
P(F("[merged] %s") % merged);
}
+typedef std::pair<revision_id, revision_id> revpair;
+typedef set<revision_id>::const_iterator rid_set_iter;
+
+// Subroutine of 'merge' and 'automate show_conflicts'; find first pair of
+// heads to merge.
+static revpair
+find_heads_to_merge(database & db, set<revision_id> const heads)
+{
+ I(heads.size() > 2);
+ map<revision_id, revpair> heads_for_ancestor;
+ set<revision_id> ancestors;
+
+ // For every pair of heads, determine their merge ancestor, and
+ // remember the ancestor->head mapping.
+ for (rid_set_iter i = heads.begin(); i != heads.end(); ++i)
+ for (rid_set_iter j = i; j != heads.end(); ++j)
+ {
+ // It is not possible to initialize j to i+1 (set iterators
+ // expose neither operator+ nor a nondestructive next() method)
+ if (j == i)
+ continue;
+
+ revision_id ancestor;
+ find_common_ancestor_for_merge(db, *i, *j, ancestor);
+
+ // More than one pair might have the same ancestor (e.g. if we
+ // have three heads all with the same parent); as this table
+ // will be recalculated on every pass, we just take the first
+ // one we find.
+ if (ancestors.insert(ancestor).second)
+ safe_insert(heads_for_ancestor, std::make_pair(ancestor, revpair(*i, *j)));
+ }
+
+ // Erasing ancestors from ANCESTORS will now produce a set of merge
+ // ancestors each of which is not itself an ancestor of any other
+ // merge ancestor.
+ erase_ancestors(db, ancestors);
+ I(ancestors.size() > 0);
+
+ // Take the first ancestor from the above set.
+ return heads_for_ancestor[*ancestors.begin()];
+}
+
// should merge support --message, --message-file? It seems somewhat weird,
// since a single 'merge' command may perform arbitrarily many actual merges.
// (Possibility: append the --message/--message-file text to the synthetic
@@ -378,9 +423,6 @@ CMD(merge, "merge", "", CMD_REF(tree), "
key_store keys(app);
project_t project(db);
- typedef std::pair<revision_id, revision_id> revpair;
- typedef set<revision_id>::const_iterator rid_set_iter;
-
if (args.size() != 0)
throw usage(execid);
@@ -404,8 +446,6 @@ CMD(merge, "merge", "", CMD_REF(tree), "
// avoid failure after lots of work
cache_user_key(app.opts, app.lua, db, keys);
- map<revision_id, revpair> heads_for_ancestor;
- set<revision_id> ancestors;
size_t pass = 1, todo = heads.size() - 1;
// If there are more than two heads to be merged, on each iteration we
@@ -425,43 +465,12 @@ CMD(merge, "merge", "", CMD_REF(tree), "
P(F("merge %d / %d:") % pass % todo);
P(F("calculating best pair of heads to merge next"));
- // For every pair of heads, determine their merge ancestor, and
- // remember the ancestor->head mapping.
- for (rid_set_iter i = heads.begin(); i != heads.end(); ++i)
- for (rid_set_iter j = i; j != heads.end(); ++j)
- {
- // It is not possible to initialize j to i+1 (set iterators
- // expose neither operator+ nor a nondestructive next() method)
- if (j == i)
- continue;
+ revpair p = find_heads_to_merge(db, heads);
- revision_id ancestor;
- find_common_ancestor_for_merge(db, *i, *j, ancestor);
-
- // More than one pair might have the same ancestor (e.g. if we
- // have three heads all with the same parent); as this table
- // will be recalculated on every pass, we just take the first
- // one we find.
- if (ancestors.insert(ancestor).second)
- safe_insert(heads_for_ancestor, std::make_pair(ancestor, revpair(*i, *j)));
- }
-
- // Erasing ancestors from ANCESTORS will now produce a set of merge
- // ancestors each of which is not itself an ancestor of any other
- // merge ancestor.
- erase_ancestors(db, ancestors);
- I(ancestors.size() > 0);
-
- // Take the first ancestor from the above set and merge its
- // corresponding pair of heads.
- revpair p = heads_for_ancestor[*ancestors.begin()];
-
merge_two(app.opts, app.lua, project, keys,
p.first, p.second, app.opts.branchname, string("merge"),
std::cout, false);
- ancestors.clear();
- heads_for_ancestor.clear();
project.get_branch_heads(app.opts.branchname, heads,
app.opts.ignore_suspend_certs);
pass++;
@@ -812,69 +821,179 @@ CMD(explicit_merge, "explicit_merge", ""
std::cout, false);
}
-CMD(show_conflicts, "show_conflicts", "", CMD_REF(informative), N_("REV REV"),
- N_("Shows what conflicts need resolution between two revisions"),
- N_("The conflicts are calculated based on the two revisions given in "
- "the REV parameters."),
- options::opts::none)
+namespace
{
- database db(app);
- project_t project(db);
+ namespace syms
+ {
+ symbol const ancestor("ancestor");
+ symbol const left("left");
+ symbol const right("right");
+ }
+}
- if (args.size() != 2)
- throw usage(execid);
- revision_id l_id, r_id;
- complete(app.opts, app.lua, project, idx(args,0)(), l_id);
- complete(app.opts, app.lua, project, idx(args,1)(), r_id);
+static void
+show_conflicts_core (database & db, revision_id const & l_id, revision_id const & r_id, bool const basic_io, std::ostream & output)
+{
N(!is_ancestor(db, l_id, r_id),
F("%s is an ancestor of %s; no merge is needed.")
% l_id % r_id);
N(!is_ancestor(db, r_id, l_id),
F("%s is an ancestor of %s; no merge is needed.")
% r_id % l_id);
- roster_t l_roster, r_roster;
+ shared_ptr<roster_t> l_roster = shared_ptr<roster_t>(new roster_t());
+ shared_ptr<roster_t> r_roster = shared_ptr<roster_t>(new roster_t());
marking_map l_marking, r_marking;
- db.get_roster(l_id, l_roster, l_marking);
- db.get_roster(r_id, r_roster, r_marking);
+ db.get_roster(l_id, *l_roster, l_marking);
+ db.get_roster(r_id, *r_roster, r_marking);
set<revision_id> l_uncommon_ancestors, r_uncommon_ancestors;
- db.get_uncommon_ancestors(l_id, r_id,
- l_uncommon_ancestors,
- r_uncommon_ancestors);
+ db.get_uncommon_ancestors(l_id, r_id, l_uncommon_ancestors, r_uncommon_ancestors);
roster_merge_result result;
- roster_merge(l_roster, l_marking, l_uncommon_ancestors,
- r_roster, r_marking, r_uncommon_ancestors,
+ roster_merge(*l_roster, l_marking, l_uncommon_ancestors,
+ *r_roster, r_marking, r_uncommon_ancestors,
result);
// note that left and right are in the order specified on the command line
- // they are not in lexical order as they are with other merge commands
- // so they may appear swapped here. perhaps we should sort left and right
- // before using them?
+ // they are not in lexical order as they are with other merge commands so
+ // they may appear swapped here. The user may have done that deliberately,
+ // especially via automate, so we don't sort them here.
- P(F("[left] %s") % l_id);
- P(F("[right] %s") % r_id);
+ basic_io::stanza st;
+ if (basic_io)
+ {
+ st.push_binary_pair(syms::left, l_id.inner());
+ st.push_binary_pair(syms::right, r_id.inner());
+ }
+ else
+ {
+ P(F("[left] %s") % l_id);
+ P(F("[right] %s") % r_id);
+ }
+
if (result.is_clean())
{
- P(F("no conflicts detected"));
+ if (basic_io)
+ {
+ basic_io::printer pr;
+ pr.print_stanza(st);
+ output.write(pr.buf.data(), pr.buf.size());
+ }
+ else
+ P(F("no conflicts detected"));
}
else
{
content_merge_database_adaptor adaptor(db, l_id, r_id,
l_marking, r_marking);
- result.report_missing_root_conflicts(l_roster, r_roster, adaptor);
- result.report_invalid_name_conflicts(l_roster, r_roster, adaptor);
- result.report_directory_loop_conflicts(l_roster, r_roster, adaptor);
+ {
+ basic_io::printer pr;
+ st.push_binary_pair(syms::ancestor, adaptor.lca.inner());
+ pr.print_stanza(st);
+ output.write(pr.buf.data(), pr.buf.size());
+ }
- result.report_orphaned_node_conflicts(l_roster, r_roster, adaptor);
- result.report_multiple_name_conflicts(l_roster, r_roster, adaptor);
- result.report_duplicate_name_conflicts(l_roster, r_roster, adaptor);
+ // The basic_io routines in roster_merge.cc access these rosters via
+ // the adaptor.
+ adaptor.cache_roster (l_id, l_roster);
+ adaptor.cache_roster (r_id, r_roster);
- result.report_attribute_conflicts(l_roster, r_roster, adaptor);
- result.report_file_content_conflicts(l_roster, r_roster, adaptor);
+ result.report_missing_root_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
+ result.report_invalid_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
+ result.report_directory_loop_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
+
+ result.report_orphaned_node_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
+ result.report_multiple_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
+ result.report_duplicate_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
+
+ result.report_attribute_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
+ result.report_file_content_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
}
}
+CMD(show_conflicts, "show_conflicts", "", CMD_REF(informative), N_("REV REV"),
+ N_("Shows what conflicts need resolution between two revisions"),
+ N_("The conflicts are calculated based on the two revisions given in "
+ "the REV parameters."),
+ options::opts::none)
+{
+ database db(app);
+ project_t project(db);
+
+ if (args.size() != 2)
+ throw usage(execid);
+ revision_id l_id, r_id;
+ complete(app.opts, app.lua, project, idx(args,0)(), l_id);
+ complete(app.opts, app.lua, project, idx(args,1)(), r_id);
+
+ show_conflicts_core(db, l_id, r_id, false, std::cout);
+}
+
+// Name: show_conflicts
+// Arguments:
+// Two revision ids (optional, determined from the workspace if not given; there must be exactly two heads)
+// Added in: 7.1
+// Purpose: Prints the conflicts between two revisions, to aid in merging them.
+//
+// Output format: see monotone.texi
+//
+// Error conditions:
+//
+// If the revision IDs are unknown or invalid prints an error message to
+// stderr and exits with status 1.
+//
+// If revision ids are not given, and the current workspace does not have
+// two heads, prints an error message to stderr and exits with status 1.
+//
+CMD_AUTOMATE(show_conflicts, N_("[LEFT_REVID RIGHT_REVID]"),
+ N_("Shows the conflicts between two revisions."),
+ N_("If no arguments are given, LEFT_REVID and RIGHT_REVID default to the "
+ "first two heads that would be chosen by the 'merge' command."),
+ options::opts::branch)
+{
+ database db(app);
+ project_t project(db);
+ revision_id l_id, r_id;
+
+ if (args.size() == 0)
+ {
+ // get ids from heads
+ N(app.opts.branchname() != "",
+ F("please specify a branch, with --branch=BRANCH"));
+
+ set<revision_id> heads;
+ project.get_branch_heads(app.opts.branchname, heads,
+ app.opts.ignore_suspend_certs);
+
+ N(heads.size() >= 2,
+ F("branch '%s' has %d heads; must be at least 2 for show_conflicts") % app.opts.branchname % heads.size());
+
+ if (heads.size() == 2)
+ {
+ set<revision_id>::const_iterator i = heads.begin();
+ l_id = *i;
+ ++i;
+ r_id = *i;
+ }
+ else
+ {
+ revpair p = find_heads_to_merge (db, heads);
+ l_id = p.first;
+ r_id = p.second;
+ }
+ }
+ else if (args.size() == 2)
+ {
+ // get ids from args
+ complete(app.opts, app.lua, project, idx(args,0)(), l_id);
+ complete(app.opts, app.lua, project, idx(args,1)(), r_id);
+ }
+ else
+ N(false, F("wrong argument count"));
+
+ show_conflicts_core(db, l_id, r_id, true, output);
+}
+
CMD(pluck, "pluck", "", CMD_REF(workspace), N_("[-r FROM] -r TO [PATH...]"),
N_("Applies changes made at arbitrary places in history"),
N_("This command takes changes made at any point in history, and "
============================================================
--- cmd_netsync.cc 92564b21090c2ebc23734588bcaad5a6740b1c2f
+++ cmd_netsync.cc 6b39feccad350c30a4d3900619e180c47a01d0fc
@@ -413,14 +413,14 @@ CMD(clone, "clone", "", CMD_REF(network)
};
CMD(clone, "clone", "", CMD_REF(network),
- N_("ADDRESS[:PORTNUMBER] [DIRECTORY]"),
+ N_("ADDRESS[:PORTNUMBER] BRANCH [DIRECTORY]"),
N_("Checks out a revision from a remote database into a directory"),
N_("If a revision is given, that's the one that will be checked out. "
"Otherwise, it will be the head of the branch supplied. "
"If no directory is given, the branch name will be used as directory"),
- options::opts::branch | options::opts::revision)
+ options::opts::revision)
{
- if (args.size() < 1 || args.size() > 2 || app.opts.revision_selectors.size() > 1)
+ if (args.size() < 2 || args.size() > 3 || app.opts.revision_selectors.size() > 1)
throw usage(execid);
revision_id ident;
@@ -428,18 +428,19 @@ CMD(clone, "clone", "", CMD_REF(network)
netsync_connection_info info;
info.client.unparsed = idx(args, 0);
- N(app.opts.branch_given && !app.opts.branchname().empty(),
- F("you must specify a branch to clone"));
+ branch_name branchname(idx(args, 1)());
- if (args.size() == 1)
+ N(!branchname().empty(), F("you must specify a branch to clone"));
+
+ if (args.size() == 2)
{
// No checkout dir specified, use branch name for dir.
- workspace_dir = system_path(app.opts.branchname());
+ workspace_dir = system_path(branchname());
}
else
{
// Checkout to specified dir.
- workspace_dir = system_path(idx(args, 1));
+ workspace_dir = system_path(idx(args, 2));
}
require_path_is_nonexistent
@@ -459,9 +460,12 @@ CMD(clone, "clone", "", CMD_REF(network)
/ bookkeeping_root_component
/ ws_internal_db_file_name);
- // must do this after setting dbname so that _MTN/options is written
- // correctly
+ // this is actually stupid, but app.opts.branchname must be set here
+ // otherwise it will not be written into _MTN/options, in case
+ // a revision is chosen which has multiple branch certs
+ app.opts.branchname = branchname;
workspace::create_workspace(app.opts, app.lua, workspace_dir);
+ app.opts.branchname = branch_name();
database db(app);
if (get_path_status(db.get_filename()) == path::nonexistent)
@@ -472,10 +476,11 @@ CMD(clone, "clone", "", CMD_REF(network)
key_store keys(app);
project_t project(db);
- info.client.include_pattern = globish(app.opts.branchname());
+ info.client.include_pattern = globish(branchname());
info.client.exclude_pattern = globish(app.opts.exclude_patterns);
+
build_client_connection_info(app.opts, app.lua, db, keys,
- info, true, true);
+ info, true, true, false);
if (app.opts.signing_key() == "")
P(F("doing anonymous pull; use -kKEYNAME if you need authentication"));
@@ -492,23 +497,19 @@ CMD(clone, "clone", "", CMD_REF(network)
if (app.opts.revision_selectors.size() == 0)
{
- // use branch head revision
- N(!app.opts.branchname().empty(),
- F("use --revision or --branch to specify what to checkout"));
-
set<revision_id> heads;
- project.get_branch_heads(app.opts.branchname, heads,
+ project.get_branch_heads(branchname, heads,
app.opts.ignore_suspend_certs);
N(heads.size() > 0,
- F("branch '%s' is empty") % app.opts.branchname);
+ F("branch '%s' is empty") % branchname);
if (heads.size() > 1)
{
- P(F("branch %s has multiple heads:") % app.opts.branchname);
+ P(F("branch %s has multiple heads:") % branchname);
for (set<revision_id>::const_iterator i = heads.begin(); i != heads.end(); ++i)
P(i18n_format(" %s")
% describe_revision(project, *i));
- P(F("choose one with '%s checkout -r<id>'") % ui.prog_name);
- E(false, F("branch %s has multiple heads") % app.opts.branchname);
+ P(F("choose one with '%s clone -r<id> SERVER BRANCH'") % ui.prog_name);
+ E(false, F("branch %s has multiple heads") % branchname);
}
ident = *(heads.begin());
}
@@ -517,12 +518,9 @@ CMD(clone, "clone", "", CMD_REF(network)
// use specified revision
complete(app.opts, app.lua, project, idx(app.opts.revision_selectors, 0)(), ident);
- guess_branch(app.opts, project, ident);
- I(!app.opts.branchname().empty());
-
- N(project.revision_is_in_branch(ident, app.opts.branchname),
+ N(project.revision_is_in_branch(ident, branchname),
F("revision %s is not a member of branch %s")
- % ident % app.opts.branchname);
+ % ident % branchname);
}
roster_t empty_roster, current_roster;
============================================================
--- contrib/monotone.bash_completion 2c9594b25c576fec99b3502e41e5a07fb10191a1
+++ contrib/monotone.bash_completion 5aff6649ff0ce10a7a993d891bc0033d23030593
@@ -201,7 +201,7 @@ _monotone() {
--next --no-files --no-graph --no-merges --to' -- $cur ) )
_filedir
;;
- approve | disapprove | comment | tag | testresult | cert | explicit_merge | trusted | update )
+ approve | disapprove | comment | suspend | tag | testresult | cert | explicit_merge | trusted | update )
_monotone_complete revision
;;
ls | list )
@@ -224,7 +224,7 @@ _monotone() {
cat )
_filedir
;;
- push | pull | serve | sync )
+ clone | push | pull | serve | sync )
COMPREPLY=( $(compgen -A hostname -- $cur) )
;;
pubkey | privkey )
@@ -256,7 +256,7 @@ _monotone() {
_monotone_complete file
fi
;;
- push | pull | serve | sync | propagate )
+ clone | push | pull | serve | sync | propagate )
_monotone_branches
;;
* )
@@ -287,10 +287,10 @@ _monotone() {
annotate cat complete diff help list log ls show_conflicts
status
cert passphrase dropkey genkey trusted
- pull push serve sync
+ clone pull push serve sync
privkey pubkey read
cvs_import
- approve comment disapprove tag testresult
+ approve comment disapprove suspend tag testresult
checkout co explicit_merge heads merge merge_into_dir
migrate_workspace propagate refresh_inodeprints setup
set unset
============================================================
--- database.cc 9e10e5d55233691379b3c4855ff77de8aced5ada
+++ database.cc 0e55fc85ea2dfec7e34ed8de385881c60ea4316f
@@ -2162,7 +2162,7 @@ database::get_common_ancestors(std::set<
{
set<revision_id> ancestors, all_common_ancestors;
vector<revision_id> frontier;
- for (set<revision_id>::const_iterator i = revs.begin();
+ for (set<revision_id>::const_iterator i = revs.begin();
i != revs.end(); ++i)
{
I(revision_exists(*i));
@@ -2199,7 +2199,7 @@ database::get_common_ancestors(std::set<
all_common_ancestors = common;
}
}
-
+
for (set<revision_id>::const_iterator i = all_common_ancestors.begin();
i != all_common_ancestors.end(); ++i)
{
@@ -2357,7 +2357,7 @@ database::put_revision(revision_id const
I(rev.made_for == made_for_database);
rev.check_sane();
- // Phase 1: confirm the revision makes sense, and we the required files
+ // Phase 1: confirm the revision makes sense, and the required files
// actually exist
for (edge_map::const_iterator i = rev.edges.begin();
i != rev.edges.end(); ++i)
============================================================
--- diff_patch.cc 06f64d5def0166740f243dedf7fd6776662a0978
+++ diff_patch.cc 211424b28fdc3a5dcdae5a781feea97e1e915326
@@ -495,7 +495,7 @@ content_merge_database_adaptor::content_
revision_id const & right,
marking_map const & left_mm,
marking_map const & right_mm)
- : db(db), left_mm(left_mm), right_mm(right_mm)
+ : db(db), left_rid (left), right_rid (right), left_mm(left_mm), right_mm(right_mm)
{
// FIXME: possibly refactor to run this lazily, as we don't
// need to find common ancestors if we're never actually
@@ -533,6 +533,13 @@ content_merge_database_adaptor::record_m
guard.commit();
}
+void
+content_merge_database_adaptor::cache_roster(revision_id const & rid,
+ boost::shared_ptr<roster_t const> roster)
+{
+ safe_insert(rosters, make_pair(rid, roster));
+};
+
static void
load_and_cache_roster(database & db, revision_id const & rid,
map<revision_id, shared_ptr<roster_t const> > & rmap,
============================================================
--- diff_patch.hh 2f4ccb77db4094b7de55931464331e22537cf560
+++ diff_patch.hh 8386bfd9dc62a30e7173fca60d27adab6d02167b
@@ -64,6 +64,8 @@ content_merge_database_adaptor
{
database & db;
revision_id lca;
+ revision_id left_rid;
+ revision_id right_rid;
marking_map const & left_mm;
marking_map const & right_mm;
std::map<revision_id, boost::shared_ptr<roster_t const> > rosters;
@@ -79,6 +81,9 @@ content_merge_database_adaptor
file_data const & right_data,
file_data const & merged_data);
+ void cache_roster(revision_id const & rid,
+ boost::shared_ptr<roster_t const> roster);
+
void get_ancestral_roster(node_id nid,
revision_id & rid,
boost::shared_ptr<roster_t const> & anc);
============================================================
--- examples/display_branches.lua f4d7d76a47fd04699f36fa079e801ab8d7e74dc6
+++ examples/display_branches.lua 656dc06747a5e55e1c1300b32bb25f13e140b758
@@ -6,41 +6,53 @@
--
-- Released as public domain
-netsync_branches = {}
-function note_netsync_start(nonce)
- netsync_branches[nonce] = {}
-end
-
-function _note_netsync_cert_received(rev_id,key,name,value,nonce)
- if name == "branch" then
- if netsync_branches[nonce][value] == nil then
- netsync_branches[nonce][value] = 1
- else
- netsync_branches[nonce][value] = netsync_branches[nonce][value] + 1
+do
+ netsync_branches = {}
+ function _note_netsync_cert_received(rev_id,key,name,value,nonce)
+ if name == "branch" then
+ if netsync_branches[nonce][value] == nil then
+ netsync_branches[nonce][value] = 1
+ else
+ netsync_branches[nonce][value] = netsync_branches[nonce][value] + 1
+ end
end
end
-end
-function note_netsync_revision_received(new_id,revision,certs,nonce)
- for _, item in pairs(certs)
- do
- _note_netsync_cert_received(new_id,item.key,item.name,item.value,nonce)
- end
-end
+ push_netsync_notifier(
+ {
+ [start] =
+ function (nonce)
+ netsync_branches[nonce] = {}
+ end,
+ [revision_received] =
+ function (new_id,revision,certs,nonce)
+ for _, item in pairs(certs)
+ do
+ _note_netsync_cert_received(new_id,item.key,item.name,item.value,nonce)
+ end
+ end,
+ [cert_received] =
+ function (rev_id,key,name,value,nonce)
+ _note_netsync_cert_received(rev_id,key,name,value,nonce)
+ end,
+ ["end"] =
+ function (nonce, status)
+ -- only try to display results if we got
+ -- at least partial contents
+ if status > 211 then
+ return
+ end
-function note_netsync_cert_received(rev_id,key,name,value,nonce)
- _note_netsync_cert_received(rev_id,key,name,value,nonce)
+ local first = true
+ for item, amount in pairs(netsync_branches[nonce])
+ do
+ if first then
+ io.stderr:write("Affected branches:\n")
+ first = false
+ end
+ io.stderr:write(" ",item," (",amount,")\n")
+ end
+ netsync_branches[nonce] = nil
+ end
+ })
end
-
-function note_netsync_end(nonce)
- local first = true
- for item, amount in pairs(netsync_branches[nonce])
- do
- if first then
- io.stderr:write("Affected branches:\n")
- first = false
- end
- io.stderr:write(" ",item," (",amount,")\n")
- end
- netsync_branches[nonce] = nil
-end
============================================================
--- lru_writeback_cache.hh 615df6d41efa986779fcf78b3dab09c8217ea18a
+++ lru_writeback_cache.hh fa05b036a2b82fe0b799c27168a75feee26e7692
@@ -154,7 +154,7 @@ public:
return (_dirty.find(key) != _dirty.end());
}
- /** @brief Checks for the existance of a key in the cache.
+ /** @brief Checks for the existence of a key in the cache.
* @param key to check for
* @return bool indicating whether or not the key was found.
*/
@@ -193,7 +193,7 @@ public:
/** @brief Inserts a key-data pair into the cache and removes entries if neccessary.
* @param key object key for insertion
* @param data object data for insertion
- * @note This function checks key existance and touches the key if it already exists.
+ * @note This function checks key existence and touches the key if it already exists.
*/
inline void insert_clean(Key const & key, const Data & data)
{
============================================================
--- lua-testsuite.lua 8254404e53c3ad822023d7d80b059519e2694eba
+++ lua-testsuite.lua 41e44b694e1d68e32ba5bf9bca044a11f48f1028
@@ -26,6 +26,25 @@ end
return {monotone_path, "--ssh-sign=no", "--norc", "--rcfile", test.root .. "/test_hooks.lua", unpack(arg)}
end
+function mtn_outside_ws(...)
+ -- Return a mtn command string that is executed outside a workspace,
+ -- but specifies all appropriate options.
+ if monotone_path == nil then
+ monotone_path = os.getenv("mtn")
+ if monotone_path == nil then
+ err("'mtn' environment variable not set")
+ end
+ end
+ return {monotone_path,
+ "--ssh-sign=no",
+ "--norc", "--rcfile", test.root .. "/test_hooks.lua",
+ "--confdir="..test.root,
+ "--db=" .. test.root .. "/test.db",
+ "--keydir", test.root .. "/keys",
+ "--key=tester@test.net",
+ unpack(arg)}
+end
+
-- function preexecute(x)
-- return {"valgrind", "--tool=memcheck", unpack(x)}
-- end
============================================================
--- luaext_parse_basic_io.cc e0dd6eaf52ad9523b67eae29bf67b26afd09f628
+++ luaext_parse_basic_io.cc 1e504c774c37a0a8b924146bf4c8b972d2134ff4
@@ -11,6 +11,9 @@ LUAEXT(parse_basic_io, )
LUAEXT(parse_basic_io, )
{
+ // This has no notion of a 'stanza'. It assumes a 'line' is a symbol
+ // followed by one or more string or hex values. It returns a table of
+ // lines.
vector<pair<string, vector<string> > > res;
const string str(luaL_checkstring(L, -1), lua_strlen(L, -1));
basic_io::input_source in(str, "monotone_parse_basic_io_for_lua");
============================================================
--- merge.cc 4ebc61395a485c9eb2b2fd6e67eafa199fe5b39e
+++ merge.cc 9059000487b5a7e6e6390175c376b45ca4f251f0
@@ -1,4 +1,5 @@
-// Copyright (C) 2005 Nathaniel Smith <njs@pobox.com>
+// Copyright (C) 2008 Stephen Leake <stephen_leake@stephe-leake.org>
+// Copyright (C) 2008 Nathaniel Smith <njs@pobox.com>
//
// This program is made available under the GNU GPL version 2.0 or
// greater. See the accompanying file COPYING for details.
@@ -8,6 +9,7 @@
// PURPOSE.
#include "base.hh"
+#include <iostream>
#include <set>
#include <boost/shared_ptr.hpp>
@@ -141,16 +143,16 @@ resolve_merge_conflicts(lua_hooks & lua,
if (result.has_non_content_conflicts())
{
- result.report_missing_root_conflicts(left_roster, right_roster, adaptor);
- result.report_invalid_name_conflicts(left_roster, right_roster, adaptor);
- result.report_directory_loop_conflicts(left_roster, right_roster, adaptor);
+ result.report_missing_root_conflicts(left_roster, right_roster, adaptor, false, std::cout);
+ result.report_invalid_name_conflicts(left_roster, right_roster, adaptor, false, std::cout);
+ result.report_directory_loop_conflicts(left_roster, right_roster, adaptor, false, std::cout);
- result.report_orphaned_node_conflicts(left_roster, right_roster, adaptor);
- result.report_multiple_name_conflicts(left_roster, right_roster, adaptor);
- result.report_duplicate_name_conflicts(left_roster, right_roster, adaptor);
+ result.report_orphaned_node_conflicts(left_roster, right_roster, adaptor, false, std::cout);
+ result.report_multiple_name_conflicts(left_roster, right_roster, adaptor, false, std::cout);
+ result.report_duplicate_name_conflicts(left_roster, right_roster, adaptor, false, std::cout);
- result.report_attribute_conflicts(left_roster, right_roster, adaptor);
- result.report_file_content_conflicts(left_roster, right_roster, adaptor);
+ result.report_attribute_conflicts(left_roster, right_roster, adaptor, false, std::cout);
+ result.report_file_content_conflicts(left_roster, right_roster, adaptor, false, std::cout);
}
else if (result.has_content_conflicts())
{
@@ -168,7 +170,7 @@ resolve_merge_conflicts(lua_hooks & lua,
P(FP("%d content conflict requires user intervention",
"%d content conflicts require user intervention",
remaining) % remaining);
- result.report_file_content_conflicts(left_roster, right_roster, adaptor);
+ result.report_file_content_conflicts(left_roster, right_roster, adaptor, false, std::cout);
try_to_merge_files(lua, left_roster, right_roster,
result, adaptor, user_merge);
============================================================
--- monotone.texi fa1738710d397b1262e70e512619f71f90157abf
+++ monotone.texi c6f295ff19bdc6a6fc1fe1d4ec1a43d500f782dc
@@ -3011,12 +3011,13 @@ @section Merge Conflicts
@command{explicit_merge}, @command{propagate} and
@command{merge_into_dir} or when using the workspace merge commands
@command{update}, @command{pluck} and @command{merge_into_workspace}.
-The @command{show_conflicts} command can be used to list conflicts
-between database revisions which would be encountered by the database
-merge commands. Unfortunately, this command can't yet list conflicts
-between a database revision and the current workspace revision which
-would be encountered by the workspace merge commands.
+The @command{show_conflicts} and @command{automate show_conflicts}
+commands can be used to list conflicts between database revisions
+which would be encountered by the database merge commands.
+Unfortunately, these commands can't yet list conflicts between a
+database revision and the current workspace.
+
@subsection Conflict Types
Monotone versions both files and directories explicitly and it tracks
@@ -5425,6 +5426,9 @@ @section Informative
This command shows what conflicts would need to be resolved in order to merge
the given revisions.
+
+Note that this does not show conflicts due to update commands, since
+in that case one revision is the workspace.
@end ftable
@@ -6684,6 +6688,8 @@ @section Automation
@itemize
@item
+8.0 -- added the output of the @code{birth} key
+@item
7.0 -- added options @option{--no-ignored}, @option{--no-unknown},
@option{--no-unchanged} and @option{--no-corresponding-renames}
@item
@@ -6712,12 +6718,14 @@ @section Automation
old_type "file"
new_type "file"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "known"
changes "attrs"
path "dropped"
old_type "file"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "dropped"
path "ignored~"
@@ -6728,18 +6736,21 @@ @section Automation
old_type "file"
new_type "file"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "missing"
path "original"
old_type "file"
new_path "renamed"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source"
path "patched"
old_type "file"
new_type "file"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "known"
changes "content"
@@ -6747,6 +6758,7 @@ @section Automation
old_type "file"
new_type "file"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "known"
changes "content" "attrs"
@@ -6754,12 +6766,14 @@ @section Automation
new_type "file"
old_path "original"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_target" "known"
path "unchanged"
old_type "file"
new_type "file"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "known"
path "unknown"
@@ -6775,6 +6789,7 @@ @section Automation
new_type "file"
old_path "unchanged"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
path "unchanged"
@@ -6783,6 +6798,7 @@ @section Automation
new_type "file"
old_path "original"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
@end verbatim
@@ -6796,6 +6812,7 @@ @section Automation
new_type "file"
old_path "unchanged"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
changes "content"
@@ -6805,6 +6822,7 @@ @section Automation
new_type "file"
old_path "original"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
changes "content"
@@ -6818,12 +6836,14 @@ @section Automation
new_path "bar"
new_type "file"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "added" "known"
path "bar"
new_type "file"
old_path "foo"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_target" "known"
@end verbatim
@@ -6836,6 +6856,7 @@ @section Automation
new_type "file"
old_path "baz"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
path "bar"
@@ -6844,6 +6865,7 @@ @section Automation
new_type "file"
old_path "foo"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
path "baz"
@@ -6852,6 +6874,7 @@ @section Automation
new_type "file"
old_path "bar"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
@end verbatim
@@ -6866,6 +6889,7 @@ @section Automation
new_type "file"
old_path "baz"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
changes "content"
@@ -6875,6 +6899,7 @@ @section Automation
new_type "file"
old_path "foo"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
changes "content"
@@ -6884,6 +6909,7 @@ @section Automation
new_type "file"
old_path "bar"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "rename_target" "known"
changes "content"
@end verbatim
@@ -6894,6 +6920,7 @@ @section Automation
path "dropped"
old_type "file"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "dropped" "unknown"
@end verbatim
@@ -6912,12 +6939,14 @@ @section Automation
old_type "file"
new_path "renamed"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source" "unknown"
path "renamed"
new_type "file"
old_path "original"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_target" "missing"
@end verbatim
@@ -6941,12 +6970,14 @@ @section Automation
old_type "file"
new_path "renamed"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source"
path "renamed"
new_type "file"
old_path "original"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_target" "known"
changes "content"
@end verbatim
@@ -6957,12 +6988,14 @@ @section Automation
old_type "file"
new_path "renamed"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source"
path "renamed"
new_type "file"
old_path "original"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_target" "known"
changes "content"
@end verbatim
@@ -6973,6 +7006,7 @@ @section Automation
old_type "file"
new_path "renamed"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source"
@end verbatim
@@ -6982,6 +7016,7 @@ @section Automation
new_type "file"
old_path "original"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_target" "known"
changes "content"
@end verbatim
@@ -6992,6 +7027,7 @@ @section Automation
old_type "file"
new_type "file"
fs_type "directory"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "invalid"
changes "content"
@end verbatim
@@ -7012,24 +7048,28 @@ @section Automation
old_type "directory"
new_path "target"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source"
path "source/a"
old_type "file"
new_path "target/a"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_source"
path "target"
new_type "directory"
old_path "source"
fs_type "file"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_target" "invalid"
path "target/a"
new_type "file"
old_path "source/a"
fs_type "none"
+ birth [cb271687054afd3c2b873c8994f206f08fb240d3]
status "rename_target" "missing"
@end verbatim
@@ -7076,6 +7116,10 @@ @section Automation
manifest.
@option{new_path} is only output for rename sources.
+@item birth
+The identify of the revision that the node was first added in.
+@option{birth} is only output if it exists in a committed revision.
+
@item status
@option{status} is always output. Its value is one or more of:
@@ -7097,6 +7141,10 @@ @section Automation
@var{path} has been deleted in the workspace, but still exists in the revision
manifest.
+A file will also be labeled @option{missing} if it is in a directory
+that is ignored due to a regular expression in @file{.mtn-ignore}, but
+is also in the revision manifest. A warning is issued in this case.
+
@item ignored
@var{path} is ignored by monotone.
@@ -8753,6 +8801,300 @@ @section Automation
@end table
+@item mtn automate show_conflicts [@var{--branch BRANCH}] [@var{left_rev right_rev}]
+
+@table @strong
+@item Arguments:
+
+Optional left and right revision ids.
+
+If no revs are given, they default to the first two heads that would
+be chosen by the @command{merge} command for the current branch. If no
+workspace is present, the branch may be given by the @var{--branch}
+option.
+
+@item Added in:
+
+7.1
+
+@item Purpose:
+
+Show all conflicts between two revisions.
+
+This is intended to be used before a @command{merge}; an external tool
+can guide the user thru resolving each conflict in turn, then do the
+merge.
+
+For more information on conflicts, @ref{Merge Conflicts}.
+
+Note that this cannot be used to show conflicts that would occur in an
+@command{update}, since in that case one revision is the workspace.
+
+@item Sample output:
+
+The output starts by listing the revisions and their common ancestor:
+@verbatim
+ left [532ab5011ea9e64aa212d4ea52363b1b8133d5ba]
+ right [b94a03a922c2c281a88d8988db64e76a32edb6a1]
+ancestor [ead03530f5fefe50c9010157c42c0ebe18086559]
+@end verbatim
+
+Attribute changed in both branches, or dropped in one:
+@verbatim
+ conflict attribute
+ node_type "file"
+ attr_name "attr1"
+ ancestor_name "foo"
+ancestor_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+ left_name "foo"
+ left_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+ left_attr_value "valueX"
+ right_name "foo"
+ right_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+right_attr_value "valueZ"
+
+ conflict attribute
+ node_type "file"
+ attr_name "attr2"
+ ancestor_name "foo"
+ancestor_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+ left_name "foo"
+ left_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+ left_attr_value "valueY"
+ right_name "foo"
+ right_file_id [bab2022ff2ed13501a8a83bcc6bd53f5042141be]
+right_attr_state "dropped"
+@end verbatim
+
+Missing root directory:
+@verbatim
+ conflict missing_root
+ left_type "pivoted root"
+ancestor_name "foo"
+ right_type "deleted directory"
+ancestor_name "foo"
+@end verbatim
+
+Directory deleted and/or renamed:
+@verbatim
+ conflict orphaned_directory
+ right_type "deleted directory"
+ancestor_name ""
+ left_type "renamed directory"
+ancestor_name ""
+ left_name "bar"
+
+ conflict orphaned_file
+ right_type "deleted directory"
+ancestor_name "foo"
+ left_type "added file"
+ left_name "foo/baz"
+ left_file_id [f5122a7f896cb2dd7ecaa84be89c94ab09c15101]
+
+ conflict orphaned_file
+ right_type "deleted directory"
+ ancestor_name "foo"
+ left_type "renamed file"
+ ancestor_name "bar"
+ancestor_file_id [ac4c6d06436632e017bb7d3ea241734e8899f8ce]
+ left_name "foo/baz"
+ left_file_id [ac4c6d06436632e017bb7d3ea241734e8899f8ce]
+
+ conflict multiple_names
+ left_type "renamed directory"
+ancestor_name ""
+ left_name "aaa"
+ right_type "renamed directory"
+ancestor_name ""
+ right_name "bbb"
+
+ conflict duplicate_name
+ left_type "renamed directory"
+ancestor_name "foo"
+ left_name ""
+ right_type "renamed directory"
+ancestor_name "bar"
+ right_name ""
+
+ conflict multiple_names
+ left_type "renamed directory"
+ancestor_name "foo"
+ left_name "a/foo"
+ right_type "renamed directory"
+ancestor_name "foo"
+ right_name "b/foo"
+@end verbatim
+
+Directory loop created:
+@verbatim
+ conflict directory_loop_created
+ left_type "renamed directory"
+ancestor_name "foo"
+ left_name "bar/foo"
+ right_type "renamed directory"
+ancestor_name "bar"
+ right_name "foo/bar"
+@end verbatim
+
+File content changed (this may be resolvable by the internal line
+merger), file also renamed:
+@verbatim
+ conflict content
+ node_type "file"
+ ancestor_name "bar"
+ancestor_file_id [f0ef49fe92167fe2a086588019ffcff7ea561786]
+ left_name "bar"
+ left_file_id [08cd878106a93ce2ef036a32499c1432adb3ee0d]
+ right_name "bar"
+ right_file_id [0cf419dd93d38b2daaaf1f5e0f3ec647745b9690]
+
+ conflict content
+ node_type "file"
+ ancestor_name "foo"
+ancestor_file_id [50bf338804db2685a575124c8c8371d06b65c523]
+ left_name "bar"
+ left_file_id [f1bb6fff2ad16d67143d89fc374ede7abec5d437]
+ right_name "baz"
+ right_file_id [b966b2d35b99e456cb0c55e4573ef0b1b155b4a9]
+@end verbatim
+
+File added and/or renamed:
+@verbatim
+ conflict duplicate_name
+ left_type "added file"
+ left_name "bar"
+ left_file_id [ba4637112ee3e55a6106d647d6c4e04a6643f8eb]
+ right_type "added file"
+ right_name "bar"
+right_file_id [fe6d523f607e2f2fc0f0defad3bda0351a95a337]
+
+ conflict duplicate_name
+ left_type "renamed file"
+ ancestor_name "foo"
+ancestor_file_id [c6864