fix handling of hidden files with `remove-ext`

pull/12/merge
Matthew Butterick 8 years ago
parent 32174aac2e
commit 78c788ae17

@ -64,19 +64,29 @@
(define pat (regexp (format "^~a" (regexp-quote starter))))
(and (regexp-match pat str) #t))
(define (path-hidden? path)
((->string (file-name-from-path path)) . starts-with? . "."))
;; with `remove-ext` and `remove-ext*`,
;; the policy is to pass through hidden files
;; though I can't remember why.
(define (do what path)
(define reversed-path-elements (reverse (explode-path path)))
(apply build-path `(,@(reverse (cdr reversed-path-elements))
,(if (eq? what 'hide)
(format ".~a" (->string (car reversed-path-elements)))
(regexp-replace #rx"^." (->string (car reversed-path-elements)) "")))))
;; take one extension off path
(define+provide+safe (remove-ext x)
(pathish? . -> . path?)
(let ([path (->path x)])
;; `path-replace-suffix` incorrectly thinks any leading dot counts as a file extension
;; when it might be a hidden path.
;; so handle hidden paths specially.
;; this is fixed in later Racket versions with `path-replace-extension`
(if (path-hidden? path)
path
(do 'hide (path-replace-suffix (do 'unhide path) ""))
(path-replace-suffix path ""))))

@ -151,24 +151,24 @@
(check-equal? (add-ext (string->path "foo") "txt") (string->path "foo.txt"))
(check-equal? (remove-ext foo-path) foo-path)
(check-equal? (remove-ext (->path ".foo.txt")) (->path ".foo.txt"))
(check-equal? (remove-ext (->path ".foo.txt")) (->path ".foo"))
(check-equal? (remove-ext foo.txt-path) foo-path)
(check-equal? (remove-ext foo.bar.txt-path) foo.bar-path)
(check-not-equal? (remove-ext foo.bar.txt-path) foo-path) ; does not remove all extensions
;; test remove-ext on paths that have "." prefix
(check-equal? (remove-ext (->path "./foo.txt.bar")) (->path "./foo.txt"))
(check-equal? (remove-ext (->path "../foo.txt.bar")) (->path "../foo.txt"))
(check-equal? (remove-ext (->path "/hidden/file/.foo.txt.bar")) (->path "/hidden/file/.foo.txt.bar")) ; hidden file won't change
(check-equal? (remove-ext (->path "/hidden/file/.foo.txt.bar")) (->path "/hidden/file/.foo.txt"))
(check-equal? (remove-ext* foo-path) foo-path)
(check-equal? (remove-ext* foo.txt-path) foo-path)
(check-equal? (remove-ext* (->path ".foo.txt")) (->path ".foo.txt"))
(check-equal? (remove-ext* (->path ".foo.txt")) (->path ".foo"))
(check-not-equal? (remove-ext* foo.bar.txt-path) foo.bar-path) ; removes more than one ext
(check-equal? (remove-ext* foo.bar.txt-path) foo-path)
;; test remove-ext* on paths that have "." prefix
(check-equal? (remove-ext* (->path "./foo.txt.bar")) (->path "./foo"))
(check-equal? (remove-ext* (->path "../foo.txt.bar")) (->path "../foo"))
(check-equal? (remove-ext* (->path "/hidden/file/.foo.txt.bar")) (->path "/hidden/file/.foo.txt.bar")) ; hidden file won't change
(check-equal? (remove-ext* (->path "/hidden/file/.foo.txt.bar")) (->path "/hidden/file/.foo"))
(check-true (has-binary-ext? "foo.MP3"))
(check-false (has-binary-ext? "foo.py"))

Loading…
Cancel
Save