@table @code
@item --with-source=@var{source}
-Use @var{source} as the source of the corresponding package.
+@itemx --with-source=@var{package}=@var{source}
+@itemx --with-source=@var{package}@@@var{version}=@var{source}
+Use @var{source} as the source of @var{package}, and @var{version} as
+its version number.
@var{source} must be a file name or a URL, as for @command{guix
download} (@pxref{Invoking guix download}).
-The ``corresponding package'' is taken to be the one specified on the
-command line the name of which matches the base of @var{source}---e.g.,
+When @var{package} is omitted,
+it is taken to be the package name specified on the
+command line that matches the base of @var{source}---e.g.,
if @var{source} is @code{/src/guile-2.0.10.tar.gz}, the corresponding
-package is @code{guile}. Likewise, the version string is inferred from
+package is @code{guile}.
+
+Likewise, when @var{version} is omitted, the version string is inferred from
@var{source}; in the previous example, it is @code{2.0.10}.
This option allows users to try out versions of packages other than the
@example
$ git clone git://git.sv.gnu.org/guix.git
-$ guix build guix --with-source=./guix
+$ guix build guix --with-source=guix@@1.0=./guix
@end example
@item --with-input=@var{package}=@var{replacement}
#:use-module (guix packages)
#:use-module (guix grafts)
+ #:use-module (guix utils)
+
;; Use the procedure that destructures "NAME-VERSION" forms.
- #:use-module ((guix utils) #:hide (package-name->name+version))
- #:use-module ((guix build utils) #:select (package-name->name+version))
+ #:use-module ((guix build utils)
+ #:select ((package-name->name+version
+ . hyphen-package-name->name+version)))
#:use-module (guix monads)
#:use-module (guix gexp)
(define register-root*
(store-lift register-root))
-(define (package-with-source store p uri)
+(define (numeric-extension? file-name)
+ "Return true if FILE-NAME ends with digits."
+ (string-every char-set:hex-digit (file-extension file-name)))
+
+(define (tarball-base-name file-name)
+ "Return the \"base\" of FILE-NAME, removing '.tar.gz' or similar
+extensions."
+ ;; TODO: Factorize.
+ (cond ((not (file-extension file-name))
+ file-name)
+ ((numeric-extension? file-name)
+ file-name)
+ ((string=? (file-extension file-name) "tar")
+ (file-sans-extension file-name))
+ ((file-extension file-name)
+ =>
+ (match-lambda
+ ("scm" file-name)
+ (else (tarball-base-name (file-sans-extension file-name)))))
+ (else
+ file-name)))
+
+(define* (package-with-source store p uri #:optional version)
"Return a package based on P but with its source taken from URI. Extract
the new package's version number from URI."
- (define (numeric-extension? file-name)
- ;; Return true if FILE-NAME ends with digits.
- (string-every char-set:hex-digit (file-extension file-name)))
-
- (define (tarball-base-name file-name)
- ;; Return the "base" of FILE-NAME, removing '.tar.gz' or similar
- ;; extensions.
- ;; TODO: Factorize.
- (cond ((not (file-extension file-name))
- file-name)
- ((numeric-extension? file-name)
- file-name)
- ((string=? (file-extension file-name) "tar")
- (file-sans-extension file-name))
- ((file-extension file-name)
- (tarball-base-name (file-sans-extension file-name)))
- (else
- file-name)))
-
(let ((base (tarball-base-name (basename uri))))
- (let-values (((name version)
- (package-name->name+version base)))
+ (let-values (((_ version*)
+ (hyphen-package-name->name+version base)))
(package (inherit p)
- (version (or version (package-version p)))
+ (version (or version version*
+ (package-version p)))
;; Use #:recursive? #t to allow for directories.
(source (download-to-store store uri
matching URIs given in SOURCES."
(define new-sources
(map (lambda (uri)
- (cons (package-name->name+version (basename uri))
- uri))
+ (match (string-index uri #\=)
+ (#f
+ ;; Determine the package name and version from URI.
+ (call-with-values
+ (lambda ()
+ (hyphen-package-name->name+version
+ (tarball-base-name (basename uri))))
+ (lambda (name version)
+ (list name version uri))))
+ (index
+ ;; What's before INDEX is a "PKG@VER" or "PKG" spec.
+ (call-with-values
+ (lambda ()
+ (package-name->name+version (string-take uri index)))
+ (lambda (name version)
+ (list name version
+ (string-drop uri (+ 1 index))))))))
sources))
(lambda (store obj)
(result '()))
(match obj
((? package? p)
- (let ((source (assoc-ref sources (package-name p))))
- (if source
- (package-with-source store p source)
- p)))
+ (match (assoc-ref sources (package-name p))
+ ((version source)
+ (package-with-source store p source version))
+ (#f
+ p)))
(_
obj)))))
(string-contains (get-output-string port)
"had no effect"))))))
+(test-assert "options->transformation, with-source, PKG=URI"
+ (let* ((p (dummy-package "foo"))
+ (s (search-path %load-path "guix.scm"))
+ (f (string-append "foo=" s))
+ (t (options->transformation `((with-source . ,f)))))
+ (with-store store
+ (let ((new (t store p)))
+ (and (not (eq? new p))
+ (string=? (package-name new) (package-name p))
+ (string=? (package-version new)
+ (package-version p))
+ (string=? (package-source new)
+ (add-to-store store (basename s) #t
+ "sha256" s)))))))
+
+(test-assert "options->transformation, with-source, PKG@VER=URI"
+ (let* ((p (dummy-package "foo"))
+ (s (search-path %load-path "guix.scm"))
+ (f (string-append "foo@42.0=" s))
+ (t (options->transformation `((with-source . ,f)))))
+ (with-store store
+ (let ((new (t store p)))
+ (and (not (eq? new p))
+ (string=? (package-name new) (package-name p))
+ (string=? (package-version new) "42.0")
+ (string=? (package-source new)
+ (add-to-store store (basename s) #t
+ "sha256" s)))))))
+
(test-assert "options->transformation, with-input"
(let* ((p (dummy-package "guix.scm"
(inputs `(("foo" ,(specification->package "coreutils"))