Skip to content

Commit 9a2070d

Browse files
committed
Support space and backslash characters in runfile filenames.
Bazel supports them with bazelbuild/bazel#23331. Step 2: support them for manifest-based runfiles.
1 parent a944e73 commit 9a2070d

File tree

3 files changed

+39
-9
lines changed

3 files changed

+39
-9
lines changed

elisp/runfiles/runfiles-test.el

+11-2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,17 @@
5454
"phst_rules_elisp/elisp/runfiles/test-manifest"))
5555
(runfiles (elisp/runfiles/make :manifest manifest
5656
:directory "/invalid/")))
57-
(should (equal (elisp/runfiles/rlocation "testäα𝐴🐈'.txt" runfiles)
58-
"/:/runfiles/testäα𝐴🐈'.txt"))))
57+
(pcase-dolist (`(,source ,target)
58+
'(("testäα𝐴🐈'.txt"
59+
"/:/runfiles/testäα𝐴🐈'.txt")
60+
("target-with-space"
61+
"/:/runfiles/with space\\and backslash")
62+
("target-with-newline"
63+
"/:/runfiles/with\nnewline\\and backslash")
64+
("source with space,\nnewline,\\and backslash"
65+
"/:/runfiles/with space,\nnewline,\\and backslash")))
66+
(ert-info (source :prefix "Source: ")
67+
(should (equal (elisp/runfiles/rlocation source runfiles) target))))))
5968

6069
(ert-deftest elisp/runfiles/make/empty-file ()
6170
(let* ((manifest (elisp/runfiles/rlocation

elisp/runfiles/runfiles.el

+25-7
Original file line numberDiff line numberDiff line change
@@ -501,13 +501,31 @@ Return an object of type ‘elisp/runfiles/runfiles--manifest’."
501501
;; Perform the same parsing as
502502
;; https://github.com/bazelbuild/bazel/blob/6.4.0/tools/cpp/runfiles/runfiles_src.cc#L241.
503503
(while (not (eobp))
504-
(pcase (buffer-substring-no-properties (point) (line-end-position))
505-
((rx bos (let key (+ (not (any ?\n ?\s))))
506-
?\s (let value (* nonl)) eos)
507-
;; Runfiles are always local, so quote them unconditionally.
508-
(puthash key (if (string-empty-p value) :empty (concat "/:" value))
509-
manifest))
510-
(other (signal 'elisp/runfiles/syntax-error (list filename other))))
504+
(let ((line (buffer-substring-no-properties
505+
(point) (line-end-position)))
506+
(escaped (eql (following-char) ?\s)))
507+
(cl-flet* ((syntax-error ()
508+
(signal 'elisp/runfiles/syntax-error
509+
(list filename line)))
510+
(unescape (string &rest other)
511+
(let ((pairs `(,@other ("\\n" . "\n") ("\\b" . "\\"))))
512+
(replace-regexp-in-string
513+
(rx ?\\ (? anychar))
514+
(lambda (seq)
515+
(or (cdr (assoc seq pairs)) (syntax-error)))
516+
string :fixedcase :literal))))
517+
(pcase (if escaped (substring-no-properties line 1) line)
518+
((rx bos (let key (+ (not (any ?\n ?\s))))
519+
?\s (let value (* nonl)) eos)
520+
(when escaped
521+
(cl-callf unescape key '("\\s" . " "))
522+
(cl-callf unescape value))
523+
(puthash key
524+
;; Runfiles are always local, so quote them
525+
;; unconditionally.
526+
(if (string-empty-p value) :empty (concat "/:" value))
527+
manifest))
528+
(_ (syntax-error)))))
511529
(forward-line)))
512530
(elisp/runfiles/manifest--make filename manifest)))
513531

elisp/runfiles/test-manifest

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
__init__.py
22
foo/bar runfiles/foo/bar
33
testäα𝐴🐈'.txt /runfiles/testäα𝐴🐈'.txt
4+
target-with-space /runfiles/with space\and backslash
5+
target-with-newline /runfiles/with\nnewline\band backslash
6+
source\swith\sspace,\nnewline,\band\sbackslash /runfiles/with space,\nnewline,\band backslash

0 commit comments

Comments
 (0)