package manager: adjust parsing of file:// URLs

For some reason, I previously made the package manager parse file URLs
by stripping away "file://" and treating the rest directly as a
path. Maybe it was to support relative paths, or maybe it was to
implicitly disallow query and fragment parts of the URL, but it seems
like a terrible idea; I've switched to `string->url` plus `url->path`.

As a result, parsing now implicitly allows and ignores query and
fragment parts of a "file://" URL. That's intended as a feature,
allowing extra information to be attached to a path in, for example,
a catalog.
This commit is contained in:
Matthew Flatt 2014-12-04 07:56:11 -07:00
parent 7b5d6fa130
commit e7264d2d98
4 changed files with 21 additions and 8 deletions

View File

@ -127,6 +127,7 @@ The valid archive formats
are (currently) @filepath{.zip}, @filepath{.tar}, @filepath{.tgz}, are (currently) @filepath{.zip}, @filepath{.tar}, @filepath{.tgz},
@filepath{.tar.gz}, and @filepath{.tar.gz}, and
@filepath{.plt}. @filepath{.plt}.
Any query or fragments parts of a @litchar{file://} URL are ignored.
For example, @filepath{~/tic-tac-toe.zip} is an archive package For example, @filepath{~/tic-tac-toe.zip} is an archive package
source, and its @tech{checksum} would be inside source, and its @tech{checksum} would be inside
@ -147,12 +148,16 @@ package name is the filename without its suffix.
@history[#:changed "6.0.1.12" @history[#:changed "6.0.1.12"
@elem{Changed treatment of an archive that contains all @elem{Changed treatment of an archive that contains all
content within a top-level directory.}]} content within a top-level directory.}
#:changed "6.1.1.5"
@elem{Changed @litchar{file://} parsing to accept a general
URL and ignore any query or fragment.}]}
@; ---------------------------------------- @; ----------------------------------------
@item{a local directory (as a plain path or @litchar{file://} URL) @item{a local directory (as a plain path or @litchar{file://} URL)
--- The name of the package is the name of the --- The name of the package is the name of the
directory. The @tech{checksum} is not present. directory. The @tech{checksum} is not present.
Any query or fragments parts of a @litchar{file://} URL are ignored.
For example, For example,
@filepath{~/tic-tac-toe/} is a directory package source. @filepath{~/tic-tac-toe/} is a directory package source.
@ -162,7 +167,11 @@ to a directory only when it does not have a file-archive suffix, does
not match the grammar of a package name, and either starts with starts not match the grammar of a package name, and either starts with starts
with @litchar{file://} or does not start with @litchar{file://} or does not start
with alphabetic characters followed by @litchar{://}. The inferred with alphabetic characters followed by @litchar{://}. The inferred
package name is the directory name.} package name is the directory name.
@history[#:changed "6.1.1.5"
@elem{Changed @litchar{file://} parsing to accept a general
URL and ignore any query or fragment.}]}
@item{a remote URL naming an archive --- This type follows the same @item{a remote URL naming an archive --- This type follows the same
rules as a local file path, but the archive and @tech{checksum} files are rules as a local file path, but the archive and @tech{checksum} files are

View File

@ -147,10 +147,12 @@
(check-equal-values? (parse "racket/fish/x" 'github #rx"two") (values #f 'github #f)) (check-equal-values? (parse "racket/fish/x" 'github #rx"two") (values #f 'github #f))
(check-equal-values? (parse "fish" 'github #rx"two") (values #f 'github #f)) (check-equal-values? (parse "fish" 'github #rx"two") (values #f 'github #f))
(check-equal-values? (parse "file://fish.plt" #f) (values "fish" 'file #t)) (check-equal-values? (parse "file://fish.plt" #f) (values #f 'dir #t)) ; missing root means an empty path
(check-equal-values? (parse "file:///root/fish.plt" #f) (values "fish" 'file #t)) (check-equal-values? (parse "file:///root/fish.plt" #f) (values "fish" 'file #t))
(check-equal-values? (parse "file://fish" #f) (values "fish" 'dir #t)) (check-equal-values? (parse "file://fish" #f) (values #f 'dir #t)) ; missing root means an empty path
(check-equal-values? (parse "file:///root/fish" #f) (values "fish" 'dir #t)) (check-equal-values? (parse "file:///root/fish" #f) (values "fish" 'dir #t))
(check-equal-values? (parse "file:///root/fish.zip?ignored=yes#alsoIgnored" #f) (values "fish" 'file #t))
(check-equal-values? (parse "file:///root/fish?ignored=yes#alsoIgnored" #f) (values "fish" 'dir #t))
(check-equal-values? (parse "random://racket-lang.org/fish.plt" #f #rx"scheme") (values #f #f #f)) (check-equal-values? (parse "random://racket-lang.org/fish.plt" #f #rx"scheme") (values #f #f #f))

View File

@ -256,8 +256,10 @@
(values (validate-name name complain-name #f) (values (validate-name name complain-name #f)
(or type (and name-type)))] (or type (and name-type)))]
[(and (not type) [(and (not type)
(regexp-match #rx"^file://(.*)$" s)) (regexp-match #rx"^file://" s))
=> (lambda (m) (parse-path (cadr m)))] => (lambda (m)
;; Note that we're ignoring a query & fragment, if any:
(parse-path (url->path (string->url s))))]
[(and (not type) [(and (not type)
(regexp-match? #rx"^[a-zA-Z]*://" s)) (regexp-match? #rx"^[a-zA-Z]*://" s))
(complain "unrecognized URL scheme") (complain "unrecognized URL scheme")

View File

@ -535,8 +535,8 @@
#f ; no git-dir #f ; no git-dir
#f ; no clean? #f ; no clean?
given-checksum ; if a checksum is provided, just use it given-checksum ; if a checksum is provided, just use it
(directory->module-paths pkg pkg-name metadata-ns) (directory->module-paths pkg-path pkg-name metadata-ns)
(directory->additional-installs pkg pkg-name metadata-ns))] (directory->additional-installs pkg-path pkg-name metadata-ns))]
[else [else
(define pkg-dir (define pkg-dir
(if in-place? (if in-place?