summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2013-02-15 15:06:01 +0100
committerNicolas Goaziou <n.goaziou@gmail.com>2013-02-15 15:06:01 +0100
commita8e48bd3a8139d6a15881061c28ca63751a213d0 (patch)
tree05f038e3bcf5eb9afd03e149b0b8cc0847237464
parent5bceb621424c9d8fda93b9c5cbef2c8bccaa59de (diff)
downloadorg-mode-a8e48bd3a8139d6a15881061c28ca63751a213d0.tar.gz
Prevent export to file from overwriting current file
* lisp/ox.el (org-export-output-file-name): Add a protection when output file name is the same as the original org. * testing/lisp/test-ox.el: Add tests.
-rw-r--r--lisp/ox.el70
-rw-r--r--testing/lisp/test-ox.el37
2 files changed, 75 insertions, 32 deletions
diff --git a/lisp/ox.el b/lisp/ox.el
index 564ebe3..a7ebe5a 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -2962,38 +2962,44 @@ directory.
When optional argument VISIBLE-ONLY is non-nil, don't export
contents of hidden elements.
-Return file name as a string, or nil if it couldn't be
-determined."
- (let ((base-name
- ;; File name may come from EXPORT_FILE_NAME subtree property,
- ;; assuming point is at beginning of said sub-tree.
- (file-name-sans-extension
- (or (and subtreep
- (org-entry-get
- (save-excursion
- (ignore-errors (org-back-to-heading) (point)))
- "EXPORT_FILE_NAME" t))
- ;; File name may be extracted from buffer's associated
- ;; file, if any.
- (let ((visited-file (buffer-file-name (buffer-base-buffer))))
- (and visited-file (file-name-nondirectory visited-file)))
- ;; Can't determine file name on our own: Ask user.
- (let ((read-file-name-function
- (and org-completion-use-ido 'ido-read-file-name)))
- (read-file-name
- "Output file: " pub-dir nil nil nil
- (lambda (name)
- (string= (file-name-extension name t) extension))))))))
- ;; Build file name. Enforce EXTENSION over whatever user may have
- ;; come up with. PUB-DIR, if defined, always has precedence over
- ;; any provided path.
- (cond
- (pub-dir
- (concat (file-name-as-directory pub-dir)
- (file-name-nondirectory base-name)
- extension))
- ((file-name-absolute-p base-name) (concat base-name extension))
- (t (concat (file-name-as-directory ".") base-name extension)))))
+Return file name as a string."
+ (let* ((visited-file (buffer-file-name (buffer-base-buffer)))
+ (base-name
+ ;; File name may come from EXPORT_FILE_NAME subtree
+ ;; property, assuming point is at beginning of said
+ ;; sub-tree.
+ (file-name-sans-extension
+ (or (and subtreep
+ (org-entry-get
+ (save-excursion
+ (ignore-errors (org-back-to-heading) (point)))
+ "EXPORT_FILE_NAME" t))
+ ;; File name may be extracted from buffer's associated
+ ;; file, if any.
+ (and visited-file (file-name-nondirectory visited-file))
+ ;; Can't determine file name on our own: Ask user.
+ (let ((read-file-name-function
+ (and org-completion-use-ido 'ido-read-file-name)))
+ (read-file-name
+ "Output file: " pub-dir nil nil nil
+ (lambda (name)
+ (string= (file-name-extension name t) extension)))))))
+ (output-file
+ ;; Build file name. Enforce EXTENSION over whatever user
+ ;; may have come up with. PUB-DIR, if defined, always has
+ ;; precedence over any provided path.
+ (cond
+ (pub-dir
+ (concat (file-name-as-directory pub-dir)
+ (file-name-nondirectory base-name)
+ extension))
+ ((file-name-absolute-p base-name) (concat base-name extension))
+ (t (concat (file-name-as-directory ".") base-name extension)))))
+ ;; If writing to OUTPUT-FILE would overwrite original file, append
+ ;; EXTENSION another time to final name.
+ (if (and visited-file (file-equal-p visited-file output-file))
+ (concat output-file extension)
+ output-file)))
(defun org-export-expand-include-keyword (&optional included dir)
"Expand every include keyword in buffer.
diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index 05693fc..ad40493 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -421,6 +421,43 @@ text
(should (equal (org-export-as 'test nil nil 'body-only) "Text\n"))
(should (equal (org-export-as 'test) "BEGIN\nText\nEND")))))
+(ert-deftest test-org-export/output-file-name ()
+ "Test `org-export-output-file-name' specifications."
+ ;; Export from a file: name is built from original file name.
+ (should
+ (org-test-with-temp-text-in-file "Test"
+ (equal (concat (file-name-as-directory ".")
+ (file-name-nondirectory
+ (file-name-sans-extension (buffer-file-name))))
+ (file-name-sans-extension (org-export-output-file-name ".ext")))))
+ ;; When exporting to subtree, check EXPORT_FILE_NAME property first.
+ (should
+ (org-test-with-temp-text-in-file
+ "* Test\n :PROPERTIES:\n :EXPORT_FILE_NAME: test\n :END:"
+ (equal (org-export-output-file-name ".ext" t) "./test.ext")))
+ ;; From a buffer not associated to a file, too.
+ (should
+ (org-test-with-temp-text
+ "* Test\n :PROPERTIES:\n :EXPORT_FILE_NAME: test\n :END:"
+ (equal (org-export-output-file-name ".ext" t) "./test.ext")))
+ ;; When provided name is absolute, preserve it.
+ (should
+ (org-test-with-temp-text
+ (format "* Test\n :PROPERTIES:\n :EXPORT_FILE_NAME: %s\n :END:"
+ (expand-file-name "test"))
+ (file-name-absolute-p (org-export-output-file-name ".ext" t))))
+ ;; When PUB-DIR argument is provided, use it.
+ (should
+ (org-test-with-temp-text-in-file "Test"
+ (equal (file-name-directory
+ (org-export-output-file-name ".ext" nil "dir/"))
+ "dir/")))
+ ;; When returned name would overwrite original file, add EXTENSION
+ ;; another time.
+ (should
+ (org-test-at-id "75282ba2-f77a-4309-a970-e87c149fe125"
+ (equal (org-export-output-file-name ".org") "./normal.org.org"))))
+
(ert-deftest test-org-export/expand-include ()
"Test file inclusion in an Org buffer."
;; Error when file isn't specified.