Currently, between CFFI-GROVEL and ASDF, neither normalizes pathnames with a dot in :NAME and NIL in :TYPE.
(cffi-grovel:grovel-file "grovel.cffi")
in a system definition may cause an error under SBCL in ASDF/CACHE:NORMALIZE-NAMESTRING when it calls NAMESTRING on the value of CFFI-GROVEL::EXE-FILENAME:
Calling
(cffi-grovel::exe-filename #p"grovel.cffi.lisp")
returns
#<pathname (with no namestring) :HOST #<sb-impl::unix-host {10002ACE43}> :DEVICE nil :DIRECTORY (:relative ".") :NAME "grovel.cffi" :TYPE nil :VERSION :newest>
to ASDF/ACTION:COMPUTE-ACTION-STAMP which can't deal with it when called with :JUST-DONE NIL.
Backtrace: http://report.quicklisp.org/cl-libssh2/2014-09-26/failtail.txt
One solution is to make CFFI-GROVEL::EXE-FILENAME normalize resulting pathname: https://github.com/cffi/cffi/pull/52
Another is to make ASDF/CACHE:NORMALIZE-NAMESTRING call NATIVE-NAMESTRING instead of NAMESTRING.
Who should be responsible for normalizing such a pathname, ASDF of CFFI-GROVEL?
Orivej Desh wrote:
Currently, between CFFI-GROVEL and ASDF, neither normalizes pathnames with a dot in :NAME and NIL in :TYPE.
(cffi-grovel:grovel-file "grovel.cffi")
in a system definition may cause an error under SBCL in ASDF/CACHE:NORMALIZE-NAMESTRING when it calls NAMESTRING on the value of CFFI-GROVEL::EXE-FILENAME:
Calling
(cffi-grovel::exe-filename #p"grovel.cffi.lisp")
returns
#<pathname (with no namestring) :HOST #<sb-impl::unix-host {10002ACE43}> :DEVICE nil :DIRECTORY (:relative ".") :NAME "grovel.cffi" :TYPE nil :VERSION :newest>
to ASDF/ACTION:COMPUTE-ACTION-STAMP which can't deal with it when called with :JUST-DONE NIL.
Backtrace: http://report.quicklisp.org/cl-libssh2/2014-09-26/failtail.txt
One solution is to make CFFI-GROVEL::EXE-FILENAME normalize resulting pathname: https://github.com/cffi/cffi/pull/52
Another is to make ASDF/CACHE:NORMALIZE-NAMESTRING call NATIVE-NAMESTRING instead of NAMESTRING.
Who should be responsible for normalizing such a pathname, ASDF of CFFI-GROVEL?
Two things:
1. REPLICATION:
Would you please let me know how to replicate this error?
Looks like you are triggering this through use of some code that's internal to ... CFFI? QUICKLISP?
I was hoping that (ql:quickload "libssh2") would get this for me, but not in my current client.
2. Is this simply an SBCL bug? I.e., there's nothing to stop me from making an executable called foo.bar where "bar" is not a file type. I mean, my file system doesn't have a real notion of filetype, except for mime type, does it? So why is this an error:
CL-USER> (make-pathname :name "foo.bar" :type nil) #<PATHNAME (with no namestring) :HOST #<SB-IMPL::UNIX-HOST {10002BE793}> :DEVICE NIL :DIRECTORY NIL :NAME "foo.bar" :TYPE NIL :VERSION NIL>
CL-USER> (namestring (make-pathname :name "foo.bar" :type nil)) ; Evaluation aborted on #<SIMPLE-ERROR "too many dots in the name: ~S" {100638D463}>.
Without taking a ton of time to grovel the ANSI spec, my guess is that all this stuff is implementation-specific, and so we can't say that this is a bug.
But SBCL seems internally not-so-consistent, because I can use one of these "erroneous" pathnames to find a file:
CL-USER> (make-pathname :directory '(:absolute "tmp") :name "foo.blort" :type nil) #<PATHNAME (with no namestring) :HOST #<SB-IMPL::UNIX-HOST {10002BE793}> :DEVICE NIL :DIRECTORY (:ABSOLUTE "tmp") :NAME "foo.blort" :TYPE NIL :VERSION NIL> CL-USER> (probe-file (make-pathname :directory '(:absolute "tmp") :name "foo.blort" :type nil)) #P"/private/tmp/foo.blort"
at which time it gets put into an acceptable form.... CL-USER> (namestring (probe-file (make-pathname :directory '(:absolute "tmp") :name "foo.blort" :type nil))) "/private/tmp/foo.blort"
thanks, r
Dear Orivej,
I believe this is a bug in CFFI, and ASDF cannot do much about it. I'm copying the CFFI-devel mailing-list.
I'm not convinced that these pathnames with invalid namestring would have a valid native-namestring (did you try?), and using native-namestring in asdf/cache:normalize-namestring would be quite impractical, since the function CL:FILE-WRITE-DATE that we subsequently use requires a Lisp namestring.
The correct thing to do would be for CFFI to assume ASDF3 (which has been out for almost 2 years and has since been adopted by all maintained implementations), and use this definition:
(defun exe-filename (defaults) (let ((defaults (uiop:ensure-pathname defaults :namestring :native :want-non-wild t :want-file t))) ;; YMMV (uiop:subpathname defaults (uiop:parse-unix-namestring (pathname-name defaults) :type *exe-extension*)))
NB: if ASDF3 is adopted, the #+sbcl and other such kluges in cffi.asd could also be replaced by :if-feature :sbcl, the defmethod for operation-done-p should be dropped, and the defmethod perform could be replaced by: (defsystem "cffi" ... :in-order-to ((test-op (test-op "cffi-tests")))) and cffi-tests could similarly use an inline method :perform (test-op (o c) ...) instead of a defmethod.
PS: the reason why SBCL (and many other implementations) have unprintable pathnames is because of the read-write consistency requirements for pathnames, which for the CLHS (see *print-readably* entry) specifies must be WRITE-n in a way that they must be read back as a "similar" object, which section 3.2.4.2.2 specifies as component-wise similarity, so that (make-pathname :name "foo.bar" :type nil) MUST NOT have the same readable representation as (make-pathname :name "foo" :type "bar").
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org The most exciting phrase to hear in science, the one that heralds new discoveries, is not "Eureka!" (I found it!) but "That's funny ..." — Isaac Asimov
On Tue, Nov 25, 2014 at 11:24 AM, Orivej Desh c@orivej.org wrote:
Currently, between CFFI-GROVEL and ASDF, neither normalizes pathnames with a dot in :NAME and NIL in :TYPE.
(cffi-grovel:grovel-file "grovel.cffi")
in a system definition may cause an error under SBCL in ASDF/CACHE:NORMALIZE-NAMESTRING when it calls NAMESTRING on the value of CFFI-GROVEL::EXE-FILENAME:
Calling
(cffi-grovel::exe-filename #p"grovel.cffi.lisp")
returns
#<pathname (with no namestring) :HOST #<sb-impl::unix-host {10002ACE43}> :DEVICE nil :DIRECTORY (:relative ".") :NAME "grovel.cffi" :TYPE nil :VERSION :newest>
to ASDF/ACTION:COMPUTE-ACTION-STAMP which can't deal with it when called with :JUST-DONE NIL.
Backtrace: http://report.quicklisp.org/cl-libssh2/2014-09-26/failtail.txt
One solution is to make CFFI-GROVEL::EXE-FILENAME normalize resulting pathname: https://github.com/cffi/cffi/pull/52
Another is to make ASDF/CACHE:NORMALIZE-NAMESTRING call NATIVE-NAMESTRING instead of NAMESTRING.
Who should be responsible for normalizing such a pathname, ASDF of CFFI-GROVEL?
- REPLICATION:
Would you please let me know how to replicate this error?
I was hoping that (ql:quickload "libssh2") would get this for me, but not in my current client.
I can replicate it reliable by cleaning (renaming, actually) ~/.cache/common-lisp and loading libssh2. Is there another way to ensure that COMPUTE-ACTION-STAMP is called with :JUST-DONE NIL? (I don't understand how exactly this affects JUST-DONE, but it does.)
* * *
I'm not convinced that these pathnames with invalid namestring would have a valid native-namestring (did you try?)
They have:
(uiop:native-namestring (make-pathname :name "a.b" :type nil)) => "a.b"
using native-namestring in asdf/cache:normalize-namestring would be quite impractical, since the function CL:FILE-WRITE-DATE that we subsequently use requires a Lisp namestring.
I anticipated this would be a problem. So, NATIVE-NAMESTRING is not acceptable.
I believe this is a bug in CFFI, and ASDF cannot do much about it. I'm copying the CFFI-devel mailing-list.
I hoped that ASDF would smooth out working with pathnames for CFFI-GROVEL as much as possible; providing UIOP seems to be this much.
(defun exe-filename (defaults) (let ((defaults (uiop:ensure-pathname defaults :namestring :native :want-non-wild t :want-file t))) ;; YMMV (uiop:subpathname defaults (uiop:parse-unix-namestring (pathname-name defaults) :type *exe-extension*)))
Thank you for this example.
If DEFAULTS is a pathname of an existing file, ENSURE-PATHNAME seems unnecessary. Under this assumption, the following definition appears equivalent:
(defun exe-filename (defaults) (uiop:parse-unix-namestring (pathname-name defaults) :type *exe-extension* :defaults defaults))
(N.B. Neither definition prepends "./" to relative paths.)