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

Reply via email to