Document string-prefix-p
[bpt/emacs.git] / lisp / dired-aux.el
index b090969..d6a4a78 100644 (file)
@@ -1,6 +1,6 @@
 ;;; dired-aux.el --- less commonly used parts of dired
 
-;; Copyright (C) 1985-1986, 1992, 1994, 1998, 2000-2011
+;; Copyright (C) 1985-1986, 1992, 1994, 1998, 2000-2012
 ;;   Free Software Foundation, Inc.
 
 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>.
@@ -347,7 +347,7 @@ This calls touch."
                  ;; Do the operation and record failures.
                  failures (nconc (apply function (append args pending))
                                  failures)
-                 ;; Transfer the elemens of PENDING onto PAST
+                 ;; Transfer the elements of PENDING onto PAST
                  ;; and clear it out.  Now PAST contains the first N files
                  ;; specified (for some N), and FILES contains the rest.
                  past (nconc past pending)
@@ -576,8 +576,11 @@ file name added at the end of COMMAND (separated by a space).
 
 `*' and `?' when not surrounded by whitespace have no special
 significance for `dired-do-shell-command', and are passed through
-normally to the shell, but you must confirm first.  To pass `*' by
-itself to the shell as a wildcard, type `*\"\"'.
+normally to the shell, but you must confirm first.
+
+If you want to use `*' as a shell wildcard with whitespace around
+it, write `*\"\"' in place of just `*'.  This is equivalent to just
+`*' in the shell, but avoids Dired's special handling.
 
 If COMMAND produces output, it goes to a separate buffer.
 
@@ -605,16 +608,16 @@ can be produced by `dired-get-marked-files', for example."
       current-prefix-arg
       files)))
   (let* ((on-each (not (string-match dired-star-subst-regexp command)))
-        (subst (not (string-match dired-quark-subst-regexp command)))
-        (star (not (string-match "\\*" command)))
-        (qmark (not (string-match "\\?" command))))
+        (no-subst (not (string-match dired-quark-subst-regexp command)))
+        (star (string-match "\\*" command))
+        (qmark (string-match "\\?" command)))
     ;; Get confirmation for wildcards that may have been meant
     ;; to control substitution of a file name or the file name list.
-    (if (cond ((not (or on-each subst))
+    (if (cond ((not (or on-each no-subst))
               (error "You can not combine `*' and `?' substitution marks"))
-             ((and star (not on-each))
+             ((and star on-each)
               (y-or-n-p "Confirm--do you mean to use `*' as a wildcard? "))
-             ((and qmark (not subst))
+             ((and qmark no-subst)
               (y-or-n-p "Confirm--do you mean to use `?' as a wildcard? "))
              (t))
        (if on-each
@@ -927,8 +930,7 @@ return t; if SYM is q or ESC, return nil."
                 (concat (apply 'format prompt args)
                         (if help-form
                             (format " [Type yn!q or %s] "
-                                    (key-description
-                                     (char-to-string help-char)))
+                                    (key-description (vector help-char)))
                           " [Type y, n, q or !] ")))
           (set sym (setq char (read-char-choice prompt char-choices)))
           (if (memq char '(?y ?\s ?!)) t)))))
@@ -1262,6 +1264,8 @@ Special value `always' suppresses confirmation."
 
 (defun dired-copy-file-recursive (from to ok-flag &optional
                                       preserve-time top recursive)
+  (when (file-subdir-of-p to from)
+    (error "Cannot copy `%s' into its subdirectory `%s'" from to))
   (let ((attrs (file-attributes from)))
     (if (and recursive
             (eq t (car attrs))
@@ -1428,10 +1432,30 @@ ESC or `q' to not overwrite any of the remaining files,
                   (cond  ((integerp marker-char) marker-char)
                          (marker-char (dired-file-marker from)) ; slow
                          (t nil))))
-           (when (and (file-directory-p from)
-                      (file-directory-p to)
-                      (eq file-creator 'dired-copy-file))
-             (setq to (file-name-directory to)))
+            ;; Handle the `dired-copy-file' file-creator specially
+            ;; When copying a directory to another directory or
+            ;; possibly to itself or one of its subdirectories.
+            ;; e.g "~/foo/" => "~/test/"
+            ;; or "~/foo/" =>"~/foo/"
+            ;; or "~/foo/ => ~/foo/bar/")
+            ;; In this case the 'name-constructor' have set the destination
+            ;; TO to "~/test/foo" because the old emacs23 behavior
+            ;; of `copy-directory' was to not create the subdirectory
+            ;; and instead copy the contents.
+            ;; With the new behavior of `copy-directory'
+            ;; (similar to the `cp' shell command) we don't
+            ;; need such a construction of the target directory,
+            ;; so modify the destination TO to "~/test/" instead of "~/test/foo/".
+            (let ((destname (file-name-directory to)))
+              (when (and (file-directory-p from)
+                         (file-directory-p to)
+                         (eq file-creator 'dired-copy-file))
+                (setq to destname))
+              ;; If DESTNAME and FROM are the same directory or
+              ;; If DESTNAME is a subdirectory of FROM, return error.
+              (and (file-subdir-of-p destname from)
+                   (error "Cannot copy `%s' into its subdirectory `%s'"
+                          from to)))
             (condition-case err
                 (progn
                   (funcall file-creator from to dired-overwrite-confirmed)
@@ -1490,7 +1514,7 @@ ARG as in `dired-get-marked-files'.
 Optional arg MARKER-CHAR as in `dired-create-files'.
 Optional arg OP1 is an alternate form for OPERATION if there is
   only one file.
-Optional arg HOW-TO determiness how to treat the target.
+Optional arg HOW-TO determines how to treat the target.
   If HOW-TO is nil, use `file-directory-p' to determine if the
    target is a directory.  If so, the marked file(s) are created
    inside that directory.  Otherwise, the target is a plain file;