Ok, I've implemented a 'fix' for this behaviour. I believe that mtn rename is now more consistent with mv(1). The attached patch includes updates for the code, docs and tests. The diff is against revision b78672c7f625a5875db79b4a27567e751e1103bc
The log message I used locally is: * Corrected the way mtn rename works such that it is more consistent with the way mv(1) works. Eg: if moving to a directory the source item is nested in the directory and the directory added if necessary (assuming other checks pass). As an aside (and I haven't tested at all), were keys and permissions that existed on venge.net moved over directly to monotone.ca? Thanks -Ben On 7/25/07, Nathaniel Smith <[EMAIL PROTECTED]> wrote: > On Thu, Jul 26, 2007 at 09:18:32AM +1000, William Uther wrote: > > I agree that things seems inconsistent given that example. I'm not > > sure if we want case 1 to behave like case 2; I'd go with the other > > way around. I'm not sure I like this 'magic add' semantics (but I'm > > not horribly opposed to it either). Case 4 should return a user error. > > I know I'm usually the one haranguing against magic, but I'm actually > pro- magic add. The reason being, in this case the user's intentions > are totally clear to the program, and the program's results are quite > obvious to the user. We all know the "stupid program, if you knew > what I wanted then why didn't you do it?" feeling, and it's nice not > to invoke it more than absolutely necessary. (It is, of course, > absolutely necessary in all sorts of cases where the user's request > *is* ambiguous, no matter what they think...) > > -- Nathaniel > > -- > - Don't let your informants burn anything. > - Don't grow old. > - Be good grad students. > -- advice of Murray B. Emeneau on the occasion of his 100th birthday > > > _______________________________________________ > Monotone-devel mailing list > Monotone-devel@nongnu.org > http://lists.nongnu.org/mailman/listinfo/monotone-devel > -- --------------------------------------------------------------------------------------------------------------------------- Ben Walton <[EMAIL PROTECTED]> When one person suffers from a delusion, it is called insanity. When many people suffer from a delusion it is called Religion. Robert M. Pirsig, Zen and the Art of Motorcycle Maintenance ---------------------------------------------------------------------------------------------------------------------------
# # old_revision [b78672c7f625a5875db79b4a27567e751e1103bc] # # patch "cmd_ws_commit.cc" # from [b29545c7fd88a94d14d3b6955505e7e179c70d73] # to [2b4ccaed7ccea9d8cb763bae8c7672cd5b5804ac] # # patch "monotone.texi" # from [15d2c02056078f0291a85fbd817f92f0fd540a3a] # to [9fe7b51e75a4f6cd42e0591fbee0952ee322bc1d] # # patch "tests/rename_file_to_dir/__driver__.lua" # from [f6eee8a739b375232f503815fbd3ab0d12c0d5c0] # to [df79dacc55885c68c5cc4b03686c6093181f2d08] # # patch "tests/ws_ops_with_wrong_node_type/__driver__.lua" # from [2a1b24ab18279249e23f2035f69352b950ba4226] # to [03a8a667a4e0da6917d7f00774021fe19e117207] # # patch "work.cc" # from [d602424dc046f080220d23b5dc663b93b573284a] # to [8ccb08cdc7afd8db1c33770ae69ab827c5a96ce4] # ============================================================ --- cmd_ws_commit.cc b29545c7fd88a94d14d3b6955505e7e179c70d73 +++ cmd_ws_commit.cc 2b4ccaed7ccea9d8cb763bae8c7672cd5b5804ac @@ -444,7 +444,8 @@ CMD(rename, "rename", "mv", CMD_REF(work app.require_workspace(); - file_path dst_path = file_path_external(args.back()); + utf8 dstr = args.back(); + file_path dst_path = file_path_external(dstr); set<file_path> src_paths; for (size_t i = 0; i < args.size()-1; i++) @@ -452,6 +453,15 @@ CMD(rename, "rename", "mv", CMD_REF(work file_path s = file_path_external(idx(args, i)); src_paths.insert(s); } + + //this catches the case where the user specifies a directory 'by convention' + //that doesn't exist. the code in perform_rename already handles the proper + //cases for more than one source item. + if (src_paths.size() == 1 && dstr()[dstr().size() -1] == '/') + if (get_path_status(*src_paths.begin()) != path::directory) + N(get_path_status(dst_path) == path::directory, + F(_("The specified target directory %s/ doesn't exist.")) % dst_path); + app.work.perform_rename(src_paths, dst_path, app.opts.bookkeep_only); } ============================================================ --- monotone.texi 15d2c02056078f0291a85fbd817f92f0fd540a3a +++ monotone.texi 9fe7b51e75a4f6cd42e0591fbee0952ee322bc1d @@ -4360,7 +4360,11 @@ @section Workspace as addition, removal, or renaming of files. This command also moves any attributes on @var{src} to @var{dst}; see @ref{File Attributes} for more details, and, unless the @option{--bookkeep-only} option is supplied, it -will rename the files immediately in the filesystem. +will rename the files immediately in the filesystem. In the case where [EMAIL PROTECTED] must be a directory (multiple @var{src} items), exists +physically in the filesystem as a directory or is specified as a +directory by convention (a trailing /), it will be automatically added +to the workspace if it is not already versioned. @item mtn commit @item mtn ci ============================================================ --- tests/rename_file_to_dir/__driver__.lua f6eee8a739b375232f503815fbd3ab0d12c0d5c0 +++ tests/rename_file_to_dir/__driver__.lua df79dacc55885c68c5cc4b03686c6093181f2d08 @@ -1,14 +1,16 @@ mtn_setup() mtn_setup() --- this test is a bug report --- the situation where a file is renamed to a dir should be trapped and --- reported with N(...) or something +-- this used to be a bug report, but the semantics have now been changed such +-- that if dest is a dir and exists (doesn't have to be versioned), then +-- the result of mtn mv file dir is dir/file as it would be with a posix mv(1) +-- the side effect is that dir will be added to the roster as if 'by magic' addfile("file", "file") commit() mkdir("dir") +check(mtn("rename", "--bookkeep-only", "file", "dir"), 0, false, false) +-- status and diff will now complain about missing files +check(mtn("status"), 1, false, false) +check(mtn("diff"), 1, false, false) -check(mtn("rename", "--bookkeep-only", "file", "dir"), 1, false, false) -check(mtn("status"), 0, false, false) -check(mtn("diff"), 0, false, false) ============================================================ --- tests/ws_ops_with_wrong_node_type/__driver__.lua 2a1b24ab18279249e23f2035f69352b950ba4226 +++ tests/ws_ops_with_wrong_node_type/__driver__.lua 03a8a667a4e0da6917d7f00774021fe19e117207 @@ -16,6 +16,10 @@ mkdir("dir2") -- running a recursive add what's supposed to be a file, but is actually a -- dir... mkdir("dir2") +check(mtn("rename", "--bookkeep-only", "file", "dir2"), 0, false, false) +-- should now be already added (this is a soft error now. see stderr to +-- ensure proper response +check(mtn("add", "dir2"), 0, false, true) +check(qgrep("skipping dir2, already accounted for in workspace", "stderr")) +-- should have happened already in the --bookkeep-only version above. +check(mtn("rename", "file", "dir2"), 1, false, false) -check(mtn("rename", "--bookkeep-only", "file", "dir2"), 1, false, false) -check(mtn("add", "dir2"), 0, false, false) -check(mtn("rename", "file", "dir2"), 0, false, false) ============================================================ --- work.cc d602424dc046f080220d23b5dc663b93b573284a +++ work.cc 8ccb08cdc7afd8db1c33770ae69ab827c5a96ce4 @@ -1435,31 +1435,39 @@ workspace::perform_rename(set<file_path> { // "rename SRC DST" case file_path const & src = *srcs.begin(); + file_path dpath = dst; - N(!directory_exists(dst), - F("destination dir %s/ is not versioned (perhaps add it?)") % dst); - N(!src.empty(), F("cannot rename the workspace root (try '%s pivot_root' instead)") % ui.prog_name); N(new_roster.has_node(src), F("source file %s is not versioned") % src); - renames.insert(make_pair(src, dst)); - add_parent_dirs(dst, new_roster, nis, db, lua); + //this allows the 'magic add' of a non-versioned directory to happen in + //all cases. previously, mtn mv fileA dir/ woudl fail if dir/ wasn't + //versioned whereas mtn mv fileA dir/fileA would add dir/ if necessary + //and then reparent fileA. + if (get_path_status(dst) == path::directory) + dpath = dst / src.basename(); + else + { + //this handles the case where: + // touch foo + // mtn mv foo bar/foo where bar doesn't exist + file_path parent = dst.dirname(); + N(get_path_status(parent) == path::directory, + F("destination path's parent directory %s/ doesn't exist") % parent); + } + + renames.insert(make_pair(src, dpath)); + add_parent_dirs(dpath, new_roster, nis, db, lua); } else { // "rename SRC1 [SRC2 ...] DSTDIR" case - N(new_roster.has_node(dst), - F("destination dir %s/ is not versioned (perhaps add it?)") % dst); + N(get_path_status(dst) == path::directory, + F("destination %s/ is not a directory") % dst); - N(is_dir_t(new_roster.get_node(dst)), - (srcs.size() > 1 - ? F("destination %s is a file, not a directory") - : F("destination %s already exists in the workspace manifest")) - % dst); - for (set<file_path>::const_iterator i = srcs.begin(); i != srcs.end(); i++) { @@ -1474,6 +1482,8 @@ workspace::perform_rename(set<file_path> F("destination %s already exists in the workspace manifest") % d); renames.insert(make_pair(*i, d)); + + add_parent_dirs(d, new_roster, nis, db, lua); } }
_______________________________________________ Monotone-devel mailing list Monotone-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/monotone-devel