package system: change syntax of a GitHub package source to "git://..."
Besides changing the URL scheme, the tag or branch is optional and specified as a fragment (inspired by npm). Also, any subpath is expressed as a "path=..." query (which similarly avoids giving a different meaning to URLs than `git' itself would). The repository name can have a ".git" suffix. The "github://..." format is still supported for compatibility, but `--type github' adds "git://..." instead of "github://..." if neither is already present (which is incompatible, since branches and tags are handled differently for the two forms). Closes PR 13656 (See the PR for a discussion and my rationale for this choice.)
This commit is contained in:
parent
33c1a7349d
commit
e1efd2d98f
|
@ -370,10 +370,10 @@ on GitHub, then
|
||||||
repository for your package}. After that, your @tech{package source}
|
repository for your package}. After that, your @tech{package source}
|
||||||
is:
|
is:
|
||||||
|
|
||||||
@inset{@exec{github://github.com/@nonterm{user}/@nonterm{package}/@nonterm{branch}}}
|
@inset{@exec{git://github.com/@nonterm{user}/@nonterm{package}}}
|
||||||
|
|
||||||
Typically, @nonterm{branch} will be @exec{master}, but you may wish to use
|
If you want the package to be @nonterm{branch} instead of @exec{master},
|
||||||
different branches for releases and development.
|
then add @filepath{#@nonterm{branch}} to the end of the package source.
|
||||||
|
|
||||||
Whenever you
|
Whenever you
|
||||||
|
|
||||||
|
|
|
@ -187,25 +187,33 @@ is the directory name.}
|
||||||
@item{a remote URL naming a GitHub repository -- The format for such
|
@item{a remote URL naming a GitHub repository -- The format for such
|
||||||
URLs is:
|
URLs is:
|
||||||
|
|
||||||
@inset{@exec{github://github.com/}@nonterm{user}@exec{/}@nonterm{repo}@;
|
@inset{@exec{git://github.com/}@nonterm{user}@exec{/}@nonterm{repo}@;
|
||||||
@exec{/}@nonterm{branch-or-tag}@exec{/}@nonterm{subpath}}
|
@optional{@exec{.git}}@optional{@exec{/}}@optional{@exec{?path=}@nonterm{path}}@;
|
||||||
|
@optional{@exec{#}@nonterm{tag}}}
|
||||||
|
|
||||||
where @nonterm{subpath} is optional and can contain multiple
|
where @nonterm{path} can contain multiple @litchar{/}-separated
|
||||||
@litchar{/}-separated elements.
|
elements to form a path within the repository, and defaults to the
|
||||||
|
empty path. The @nonterm{tag} can be a branch or tag, and it
|
||||||
|
defaults to @exec{master}.
|
||||||
|
|
||||||
For example, @filepath{github://github.com/game/tic-tac-toe/master/}
|
For example, @filepath{git://github.com/game/tic-tac-toe#master}
|
||||||
is a GitHub package source.
|
is a GitHub package source.
|
||||||
|
|
||||||
|
For backward compatibility, an older format is also supported:
|
||||||
|
|
||||||
|
@inset{@exec{github://github.com/}@nonterm{user}@exec{/}@nonterm{repo}@;
|
||||||
|
@exec{/}@nonterm{tag}@optional{@exec{/}@nonterm{path}}}
|
||||||
|
|
||||||
The @exec{zip}-formatted archive for the repository (generated by
|
The @exec{zip}-formatted archive for the repository (generated by
|
||||||
GitHub for every branch and tag) is used as a remote URL archive path,
|
GitHub for every branch and tag) is used as a remote URL archive path,
|
||||||
except the @tech{checksum} is the hash identifying the branch (or
|
except the @tech{checksum} is the hash identifying the branch (or
|
||||||
tag).
|
tag).
|
||||||
|
|
||||||
A package source is inferred to be a GitHub reference when it
|
A package source is inferred to be a GitHub reference when it
|
||||||
starts with @litchar{github://}; a package source that is otherwise
|
starts with @litchar{git://} or @litchar{github://}; a package source that is otherwise
|
||||||
specified as a GitHub reference is automatically prefixed with
|
specified as a GitHub reference is automatically prefixed with
|
||||||
@filepath{github://github.com/}. The inferred package name
|
@filepath{git://github.com/}. The inferred package name
|
||||||
is the last element of @nonterm{subpath} if it is
|
is the last element of @nonterm{path} if it is
|
||||||
non-empty, otherwise the inferred name is @nonterm{repo}.}
|
non-empty, otherwise the inferred name is @nonterm{repo}.}
|
||||||
|
|
||||||
@item{a @tech{package name} -- A @tech{package catalog} is
|
@item{a @tech{package name} -- A @tech{package catalog} is
|
||||||
|
|
|
@ -37,10 +37,10 @@
|
||||||
(list
|
(list
|
||||||
(pkg "p1" "http://a" "" "" "" "")))
|
(pkg "p1" "http://a" "" "" "" "")))
|
||||||
|
|
||||||
(set-pkg! "p1" "http://a" "github:a" "adam" "123" "the first package")
|
(set-pkg! "p1" "http://a" "adam" "git:a" "123" "the first package")
|
||||||
(check-equal? (get-pkgs)
|
(check-equal? (get-pkgs)
|
||||||
(list
|
(list
|
||||||
(pkg "p1" "http://a" "github:a" "adam" "123" "the first package")
|
(pkg "p1" "http://a" "adam" "git:a" "123" "the first package")
|
||||||
(pkg "p2" "http://b" "" "" "" "")))
|
(pkg "p2" "http://b" "" "" "" "")))
|
||||||
|
|
||||||
;; reverse order of catalogs:
|
;; reverse order of catalogs:
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
(check-equal? (get-pkgs)
|
(check-equal? (get-pkgs)
|
||||||
(list
|
(list
|
||||||
(pkg "p2" "http://b" "" "" "" "")
|
(pkg "p2" "http://b" "" "" "" "")
|
||||||
(pkg "p1" "http://a" "github:a" "adam" "123" "the first package")))
|
(pkg "p1" "http://a" "adam" "git:a" "123" "the first package")))
|
||||||
|
|
||||||
(check-equal? (get-pkg-tags "p2" "http://b")
|
(check-equal? (get-pkg-tags "p2" "http://b")
|
||||||
'())
|
'())
|
||||||
|
@ -97,6 +97,6 @@
|
||||||
|
|
||||||
(check-equal? (get-pkgs)
|
(check-equal? (get-pkgs)
|
||||||
(list
|
(list
|
||||||
(pkg "p1" "http://a" "github:a" "adam" "123" "the first package")))
|
(pkg "p1" "http://a" "adam" "git:a" "123" "the first package")))
|
||||||
|
|
||||||
(delete-file (current-pkg-catalog-file)))
|
(delete-file (current-pkg-catalog-file)))
|
||||||
|
|
|
@ -91,10 +91,24 @@
|
||||||
(check-equal-values? (parse "github://github.com/fish/master" 'github #rx"three") (values #f 'github #f))
|
(check-equal-values? (parse "github://github.com/fish/master" 'github #rx"three") (values #f 'github #f))
|
||||||
(check-equal-values? (parse "github://github.com/racket/fish.more/release" 'github) (values #f 'github #t))
|
(check-equal-values? (parse "github://github.com/racket/fish.more/release" 'github) (values #f 'github #t))
|
||||||
|
|
||||||
(check-equal-values? (parse "racket/fish/master" 'github) (values "fish" 'github #t))
|
(check-equal-values? (parse "git://not-github.com/racket/fish" #f #rx"github.com") (values #f 'github #f))
|
||||||
(check-equal-values? (parse "racket/fish/master/" 'github) (values "fish" 'github #t))
|
(check-equal-values? (parse "git://github.com/racket/fish" #f) (values "fish" 'github #t))
|
||||||
(check-equal-values? (parse "racket/fish" 'github #rx"three") (values #f 'github #f))
|
(check-equal-values? (parse "git://github.com/racket/fish/" #f) (values "fish" 'github #t))
|
||||||
(check-equal-values? (parse "fish" 'github #rx"three") (values #f 'github #f))
|
(check-equal-values? (parse "git://github.com/racket/fish.git" #f) (values "fish" 'github #t))
|
||||||
|
(check-equal-values? (parse "git://github.com/racket/fish.git/" #f) (values "fish" 'github #t))
|
||||||
|
(check-equal-values? (parse "git://github.com/racket/fish.rkt" #f) (values #f 'github #t))
|
||||||
|
(check-equal-values? (parse "git://github.com/racket/fish#release" #f) (values "fish" 'github #t))
|
||||||
|
(check-equal-values? (parse "git://github.com/racket/fish?path=catfish#release" #f) (values "catfish" 'github #t))
|
||||||
|
(check-equal-values? (parse "git://github.com/racket/fish?path=catfish/" #f) (values "catfish" 'github #t))
|
||||||
|
(check-equal-values? (parse "git://github.com/racket/fish?path=catfish/bill" #f) (values "bill" 'github #t))
|
||||||
|
(check-equal-values? (parse "git://github.com/racket/fish/master" 'github #rx"two") (values #f 'github #f))
|
||||||
|
(check-equal-values? (parse "git://github.com/racket/fish.more" 'github) (values #f 'github #t))
|
||||||
|
|
||||||
|
(check-equal-values? (parse "racket/fish" 'github) (values "fish" 'github #t))
|
||||||
|
(check-equal-values? (parse "racket/fish.git" 'github) (values "fish" 'github #t))
|
||||||
|
(check-equal-values? (parse "racket/fish/" 'github) (values "fish" 'github #t))
|
||||||
|
(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 "file://fish.plt" #f) (values "fish" 'file #t))
|
(check-equal-values? (parse "file://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:///root/fish.plt" #f) (values "fish" 'file #t))
|
||||||
|
|
|
@ -16,17 +16,17 @@
|
||||||
(pkg-tests
|
(pkg-tests
|
||||||
(shelly-begin
|
(shelly-begin
|
||||||
(shelly-install "remote/github"
|
(shelly-install "remote/github"
|
||||||
"github://github.com/jeapostrophe/galaxy/master/tests/planet2/test-pkgs/planet2-test1")
|
"git://github.com/jeapostrophe/galaxy?path=tests/planet2/test-pkgs/planet2-test1")
|
||||||
(shelly-install "remote/github with slash"
|
(shelly-install "remote/github with slash"
|
||||||
"github://github.com/jeapostrophe/galaxy/master/tests/planet2/test-pkgs/planet2-test1/")
|
"git://github.com/jeapostrophe/galaxy?path=tests/planet2/test-pkgs/planet2-test1/")
|
||||||
(shelly-install "remote/github with auto prefix"
|
(shelly-install "remote/github with auto prefix"
|
||||||
"--type github jeapostrophe/galaxy/master/tests/planet2/test-pkgs/planet2-test1/")
|
"--type github jeapostrophe/galaxy?path=tests/planet2/test-pkgs/planet2-test1/")
|
||||||
|
|
||||||
(hash-set! *index-ht-1* "planet2-test1-github-different-checksum"
|
(hash-set! *index-ht-1* "planet2-test1-github-different-checksum"
|
||||||
(hasheq 'checksum
|
(hasheq 'checksum
|
||||||
"23eeaee731e72a39bddbacdf1ed6cce3bcf423a5"
|
"23eeaee731e72a39bddbacdf1ed6cce3bcf423a5"
|
||||||
'source
|
'source
|
||||||
"github://github.com/jeapostrophe/galaxy/master/tests/planet2/test-pkgs/planet2-test1/"))
|
"git://github.com/jeapostrophe/galaxy?path=tests/planet2/test-pkgs/planet2-test1/"))
|
||||||
|
|
||||||
(with-fake-root
|
(with-fake-root
|
||||||
(shelly-case
|
(shelly-case
|
||||||
|
|
|
@ -838,9 +838,9 @@
|
||||||
pkg))
|
pkg))
|
||||||
(cond
|
(cond
|
||||||
[(and (eq? type 'github)
|
[(and (eq? type 'github)
|
||||||
(not (regexp-match? #rx"^github://" pkg)))
|
(not (regexp-match? #rx"^git(?:hub)?://" pkg)))
|
||||||
;; Add "github://github.com/"
|
;; Add "git://github.com/"
|
||||||
(stage-package/info (string-append "github://github.com/" pkg) type
|
(stage-package/info (string-append "git://github.com/" pkg) type
|
||||||
pkg-name
|
pkg-name
|
||||||
#:given-checksum given-checksum
|
#:given-checksum given-checksum
|
||||||
check-sums? download-printf
|
check-sums? download-printf
|
||||||
|
|
|
@ -107,15 +107,15 @@
|
||||||
(validate-name s complain #f)
|
(validate-name s complain #f)
|
||||||
(values (and (regexp-match? rx:package-name s) s) 'name)]
|
(values (and (regexp-match? rx:package-name s) s) 'name)]
|
||||||
[(and (eq? type 'github)
|
[(and (eq? type 'github)
|
||||||
(not (regexp-match? #rx"^github://" s)))
|
(not (regexp-match? #rx"^git(?:hub)?://" s)))
|
||||||
(package-source->name+type
|
(package-source->name+type
|
||||||
(string-append "github://github.com/" s)
|
(string-append "git://github.com/" s)
|
||||||
'github)]
|
'github)]
|
||||||
[(if type
|
[(if type
|
||||||
(or (eq? type 'github)
|
(or (eq? type 'github)
|
||||||
(eq? type 'file-url)
|
(eq? type 'file-url)
|
||||||
(eq? type 'dir-url))
|
(eq? type 'dir-url))
|
||||||
(regexp-match? #rx"^(https?|github)://" s))
|
(regexp-match? #rx"^(https?|github|git)://" s))
|
||||||
(define url (with-handlers ([exn:fail? (lambda (exn) #f)])
|
(define url (with-handlers ([exn:fail? (lambda (exn) #f)])
|
||||||
(string->url s)))
|
(string->url s)))
|
||||||
(define-values (name name-type)
|
(define-values (name name-type)
|
||||||
|
@ -124,25 +124,40 @@
|
||||||
(cond
|
(cond
|
||||||
[(if type
|
[(if type
|
||||||
(eq? type 'github)
|
(eq? type 'github)
|
||||||
(equal? (url-scheme url) "github"))
|
(or (equal? (url-scheme url) "github")
|
||||||
(unless (equal? (url-scheme url) "github")
|
(equal? (url-scheme url) "git")))
|
||||||
(complain "URL scheme is not 'github'"))
|
(unless (or (equal? (url-scheme url) "github")
|
||||||
|
(equal? (url-scheme url) "git"))
|
||||||
|
(complain "URL scheme is not 'git' or 'github'"))
|
||||||
(define name
|
(define name
|
||||||
(and (cor (pair? p)
|
(and (cor (pair? p)
|
||||||
(complain "URL path is empty"))
|
(complain "URL path is empty"))
|
||||||
(cor (equal? "github.com" (url-host url))
|
(cor (equal? "github.com" (url-host url))
|
||||||
(complain "URL host is not 'github.com'"))
|
(complain "URL host is not 'github.com'"))
|
||||||
(let ([p (if (equal? "" (path/param-path (last p)))
|
(if (equal? (url-scheme url) "git")
|
||||||
(reverse (cdr (reverse p)))
|
;; git://
|
||||||
p)])
|
(and (cor (or (= (length p) 2)
|
||||||
(and (cor ((length p) . >= . 3)
|
(and (= (length p) 3)
|
||||||
(complain "URL does not have at least three path elements"))
|
(equal? "" (path/param-path (caddr p)))))
|
||||||
(validate-name
|
(complain "URL does not have two path elements (name and repo)"))
|
||||||
(if (= (length p) 3)
|
(let ([a (assoc 'path (url-query url))])
|
||||||
(path/param-path (second (reverse p)))
|
(define sub (and a (cdr a) (string-split (cdr a) "/")))
|
||||||
(last-non-empty p))
|
(if (pair? sub)
|
||||||
complain-name
|
(validate-name (last sub) complain-name #t)
|
||||||
#t)))))
|
(let ([s (path/param-path (cadr p))])
|
||||||
|
(validate-name (regexp-replace #rx"[.]git$" s "") complain-name #t)))))
|
||||||
|
;; github://
|
||||||
|
(let ([p (if (equal? "" (path/param-path (last p)))
|
||||||
|
(reverse (cdr (reverse p)))
|
||||||
|
p)])
|
||||||
|
(and (cor ((length p) . >= . 3)
|
||||||
|
(complain "URL does not have at least three path elements"))
|
||||||
|
(validate-name
|
||||||
|
(if (= (length p) 3)
|
||||||
|
(path/param-path (second (reverse p)))
|
||||||
|
(last-non-empty p))
|
||||||
|
complain-name
|
||||||
|
#t))))))
|
||||||
(values name (or type 'github))]
|
(values name (or type 'github))]
|
||||||
[(if type
|
[(if type
|
||||||
(eq? type 'file-url)
|
(eq? type 'file-url)
|
||||||
|
|
|
@ -53,7 +53,17 @@
|
||||||
(define github-client_secret (make-parameter #f))
|
(define github-client_secret (make-parameter #f))
|
||||||
|
|
||||||
(define (split-github-url pkg-url)
|
(define (split-github-url pkg-url)
|
||||||
(map path/param-path (url-path/no-slash pkg-url)))
|
(if (equal? (url-scheme pkg-url) "github")
|
||||||
|
;; github://
|
||||||
|
(map path/param-path (url-path/no-slash pkg-url))
|
||||||
|
;; git://
|
||||||
|
(let* ([paths (map path/param-path (url-path/no-slash pkg-url))])
|
||||||
|
(list* (car paths)
|
||||||
|
(regexp-replace* #rx"[.]git$" (cadr paths) "")
|
||||||
|
(or (url-fragment pkg-url) "master")
|
||||||
|
(let ([a (assoc 'path (url-query pkg-url))])
|
||||||
|
(or (and a (cdr a) (string-split (cdr a) "/"))
|
||||||
|
null))))))
|
||||||
|
|
||||||
(define (package-url->checksum pkg-url-str [query empty]
|
(define (package-url->checksum pkg-url-str [query empty]
|
||||||
#:download-printf [download-printf void]
|
#:download-printf [download-printf void]
|
||||||
|
@ -61,7 +71,7 @@
|
||||||
(define pkg-url
|
(define pkg-url
|
||||||
(string->url pkg-url-str))
|
(string->url pkg-url-str))
|
||||||
(match (url-scheme pkg-url)
|
(match (url-scheme pkg-url)
|
||||||
["github"
|
[(or "github" "git")
|
||||||
(match-define (list* user repo branch path)
|
(match-define (list* user repo branch path)
|
||||||
(split-github-url pkg-url))
|
(split-github-url pkg-url))
|
||||||
(define api-u
|
(define api-u
|
||||||
|
|
Loading…
Reference in New Issue
Block a user