 SOLUTION: for each dir, umark all its contents (but not the dir
 itself) before running mv."
   (interactive)
+    (svn-status-mv-cp "mv" "Rename" "Move" "mv"))
+
+(defun svn-status-cp ()
+  "See `svn-status-mv'"
+  (interactive)
+  (svn-status-mv-cp "cp" "Copy" "Copy" "cp"))
+
+(defun svn-status-mv-cp (command singleprompt manyprompt fallback)
+  "Run svn COMMAND on marked files, prompting for destination
+
+This function acts on `svn-status-marked-files': at the prompt the
+user can enter a new file name, or an existing directory: this is used as the argument for svn COMMAND.
+   COMMAND      --- string saying what to do: \"mv\" or \"cp\"
+   SINGLEPROMPT --- string at start of prompt when one file marked
+   MANYPROMPT   --- string at start of prompt when multiple files marked
+   FALLBACK     --- If any marked file is unversioned, use this instead of 'svn COMMAND'"
   (let* ((marked-files (svn-status-marked-files))
          (num-of-files (length marked-files))
          dest)
     (if (= 1 num-of-files)
-        ;; one file to rename, prompt for new name, or directory to move the
-        ;; file into.
-        (setq dest (read-file-name (format "Rename %s to: "
-                                           (svn-status-line-info->filename (car marked-files)))
-                                   (svn-status-directory-containing-point t)
-                                   (svn-status-line-info->full-path (car marked-files))))
+        ;; one file to act on: new name, or directory to hold results
+        (setq dest (read-file-name
+                    (format "%s %s to: " singleprompt
+                            (svn-status-line-info->filename (car marked-files)))
+                    (svn-status-directory-containing-point t)
+                    (svn-status-line-info->full-path (car marked-files))))
+      ;;TODO: (when file-exists-p but-no-dir-p dest (error "%s already exists" dest))
       ;;multiple files selected, so prompt for existing directory to mv them into.
-      (setq dest (svn-read-directory-name (format "Move %d files to directory: " num-of-files)
-                                          (svn-status-directory-containing-point t) nil t))
+      (setq dest (svn-read-directory-name
+                  (format "%s %d files to directory: " manyprompt num-of-files)
+                  (svn-status-directory-containing-point t) nil t))
       (unless (file-directory-p dest)
         (error "%s is not a directory" dest)))
     (when (string= dest "")
-      (error "No destination entered; no files moved"))
+      (error "No destination entered"))
     (unless (string-match "^[^:/]+://" dest) ; Is it a URI?
       (setq dest (file-relative-name dest)))
-;
+
     ;;do the move: svn mv only lets us move things once at a time, so
     ;;we need to run svn mv once for each file (hence second arg to
     ;;svn-run is nil.)

    ;;TODO: before doing any moving, For every marked directory,
    ;;ensure none of its contents are also marked, since we dont want
    ;;to move both file *and* its parent...
    ;; what about hidden files?? what if user marks a dir+contents, then presses `_' ??
;;   ;one solution:
;;      (dolist (original marked-files)
;;          (when (svn-status-line-info->directory-p original)

              (let ((dirname (directory-file-name dir)))
                (if (not (member dirname dir-set))
                    (setq dir-set (cons dirname dir-set)))))
          (setq svn-status-info
                (cons (svn-status-make-line-info path
                                                 (gethash path old-ui-information)
                                                 svn-file-mark
                                                 svn-property-mark
                                                 local-rev
                                                 last-change-rev
                                                 author
                                                 svn-update-mark
                                                 svn-wc-locked-mark
                                                 svn-with-history-mark
                                                 svn-switched-mark
                                                 svn-repo-locked-mark)
                      svn-status-info))
          (setq revision-width (max revision-width
                                    (length (number-to-string local-rev))
                                    (length (number-to-string last-change-rev))))
