diff --git a/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui.rkt b/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui.rkt index c5e861519c..a58f9f56e2 100644 --- a/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui.rkt +++ b/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui.rkt @@ -192,6 +192,6 @@ frame) (module+ main - (void (make-pkg-installer)) #; + (void (make-pkg-installer)) (void (make-pkg-gui))) diff --git a/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui/private/by-installed.rkt b/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui/private/by-installed.rkt index 2ace6418a5..bfc6e5a712 100644 --- a/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui/private/by-installed.rkt +++ b/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui/private/by-installed.rkt @@ -3,6 +3,7 @@ racket/gui/base racket/format setup/dirs + net/url pkg/lib pkg string-constants @@ -13,11 +14,30 @@ (struct ipkg (name scope auto? checksum source)) -(define ((ipkg->source dir) ipkg) +(define ((ipkg->desc dir) ipkg) + (define name (ipkg-name ipkg)) (define s (cadr (ipkg-source ipkg))) - (if (not (eq? 'catalog (car (ipkg-source ipkg)))) - (path->string (path->complete-path s dir)) - s)) + (define kind (car (ipkg-source ipkg))) + (case kind + [(catalog) (pkg-desc s 'name name #f #f)] + [(link static-link) + (pkg-desc (path->string (path->complete-path s dir)) kind name #f #f)] + [(url) (pkg-desc s #f name #f #f)] + [(clone) + (define url-str (caddr (ipkg-source ipkg))) + (pkg-desc url-str + 'clone + name + #f + #f + #:path (let loop ([p (path->complete-path s dir)] + [n (length (url-query (string->url url-str)))]) + (cond + [(zero? n) p] + [else (define-values (base name dir?) (split-path p)) + (if (path? base) + (loop base (sub1 n)) + (error "mangled path recorded for a clone"))])))])) (define (source->string s) (format "~a: ~a" @@ -26,7 +46,8 @@ [(url) "URL"] [(link) "Link"] [(static-link) "Static link"] - [(file) "File"]) + [(file) "File"] + [(clone) "Clone"]) (cadr s))) (define (status-string a default-scope) @@ -152,14 +173,9 @@ [(path? scope) scope] [(eq? scope 'installation) (find-pkgs-dir)] [else (find-user-pkgs-dir)])) - ;; Also preserve link kind: - (define kind (car (ipkg-source (car ipkgs)))) - (apply - pkg-install-command - #:scope scope - #:link (eq? 'link kind) - #:static-link (eq? 'static-link kind) - (map (ipkg->source dir) ipkgs)))))])) + (parameterize ([current-pkg-scope scope]) + (with-pkg-lock (pkg-install (map (ipkg->desc dir) ipkgs)))) + (void))))])) (define demote-button (new button% @@ -215,12 +231,7 @@ (not (ipkg-auto? i))))) (send promote-button enable (and same-scope? (for/and ([i (in-list ipkgs)]) - (ipkg-auto? i)) - ;; all 'catalog, 'link, or 'static-link - (let ([kind (car (ipkg-source (car ipkgs)))]) - (and (memq kind '(catalog link static-link)) - (for/and ([i (in-list (cdr ipkgs))]) - (eq? kind (car (ipkg-source i)))))))) + (ipkg-auto? i)))) (send update-button enable (and same-scope? (for/and ([i (in-list ipkgs)]) (not (memq (car (ipkg-source i)) @@ -267,7 +278,7 @@ (if (eq? (car sa) (car sb)) (string (cadr sa) (cadr sb)) (case (car sa) - [(link) #t] + [(link static-link clone) #t] [(catalog) (eq? b 'url)] [(url) #f])))]))))) (set! sorted-installed (list->vector l)) diff --git a/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui/private/by-list.rkt b/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui/private/by-list.rkt index ab0623eca4..63abe8ba32 100644 --- a/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui/private/by-list.rkt +++ b/pkgs/gui-pkg-manager-pkgs/gui-pkg-manager-lib/pkg/gui/private/by-list.rkt @@ -28,6 +28,7 @@ [(catalog) ""] [(link) "="] [(static-link) "="] + [(clone) "="] [(url) "@"]))) (define by-list-panel% diff --git a/pkgs/plt-services/meta/drdr/README-PORTS b/pkgs/plt-services/meta/drdr/README-PORTS index 1cc80b6ad1..4b213a335a 100644 --- a/pkgs/plt-services/meta/drdr/README-PORTS +++ b/pkgs/plt-services/meta/drdr/README-PORTS @@ -9,6 +9,9 @@ others don't accidentally conflict. 8889 - tests/racket/benchmarks/shootout/typed/echo (optimized) 9000 - DrDr Web server 9001 - tests/net +9990 - tests/pkg +9997 - tests/pkg +9998 - tests/pkg 9999 - tests/web-server 19200 - 2htdp/tests ... diff --git a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/getting-started.scrbl b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/getting-started.scrbl index baee369078..477148d7ea 100644 --- a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/getting-started.scrbl +++ b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/getting-started.scrbl @@ -268,8 +268,8 @@ and grows up to become a Git repository that is registered with a @subsection[#:tag "automatic-creation"]{Automatic Creation} -As a convenience, @command-ref{new} can automatically create single -collection packages. +As a convenience, @command-ref{new} can automate the creation of +a @tech{single-collection package}. To create @nonterm{pkg-name}: @commandline{raco pkg new @nonterm{pkg-name}} @@ -307,7 +307,7 @@ it to a @tech{multi-collection package} by restructuring the package directory, so you don't have to worry much about the choice when you get started. -@subsection[#:tag "working-new-pkgs"]{Working with New Packages} +@subsection[#:tag "working-new-pkgs"]{Linking and Developing New Packages} Whether creating a @tech{single-collection package} or a @tech{multi-collection package}, the next step is to link your @@ -392,7 +392,7 @@ Whenever you @commandline{git push} your changes will automatically be discovered by those who use -@exec{raco pkg update} after installing from your +@command-ref{update} after installing from your GitHub-based @tech{package source}. As of Racket version 6.1.1.1, other Git repository services can work @@ -400,6 +400,10 @@ just as well as GitHub---including Gitorious or BitBucket---as long as the server supports either the ``smart'' HTTP(S) protocol or the native Git protocol (but use a @exec{git://} path for the latter). +The Racket package manager provides more support for Git-based +development than just deployment. See @secref["git-workflow"] for more +information. + @; - - - - - - - - - - - - - - - - - - - - - - - - @subsection[#:tag "manual-deploy"]{Manual Deployment} @@ -421,9 +425,9 @@ Your @tech{package source} is then something like Whenever you want to provide a new release of a package, recreate and reupload the package archive (and @tech{checksum}). Your changes will automatically be discovered by those who used your package source when they use -@exec{raco pkg update}. +@command-ref{update}. -@margin-note{By default, @exec{raco pkg create} generates a +@margin-note{By default, @command-ref{create} generates a @filepath{.zip} archive. For more options, refer to the @command-ref{create} documentation. If you want to generate an archive through some other means, simply archive what you made in the first @@ -453,7 +457,7 @@ If you use this server, and if you use a public Git repository for deployment, then you will never need to open a web browser to update your package for end users. You just need to push to your Git repository, then within 24 hours, the PLT @tech{package catalog} will -notice, and @exec{raco pkg update} will work on your user's machines. +notice, and @command-ref{update} will work on your user's machines. @; - - - - - - - - - - - - - - - - - - - - - - - - @@ -484,8 +488,8 @@ present interfaces to external, versioned things, such as @item{A @tech{version} declaration for a package is used only by other package implementors to effectively declare dependencies on provided -features. Such declarations allow @exec{raco pkg install} and -@exec{raco pkg update} to help check dependencies. Declaring and +features. Such declarations allow @command-ref{install} and +@command-ref{update} to help check dependencies. Declaring and changing a version is optional, and the @tech{package catalog} ignores version declarations; in particular, a package is a candidate for updating when its @tech{checksum} changes, independent of whether diff --git a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/git-workflow.scrbl b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/git-workflow.scrbl new file mode 100644 index 0000000000..1806f49b57 --- /dev/null +++ b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/git-workflow.scrbl @@ -0,0 +1,148 @@ +#lang scribble/manual +@(require "common.rkt" + scribble/bnf) + +@title[#:tag "git-workflow"]{Developing Packages with Git} + +When a Git repository is specified as a package source, then a copy of +the repository content is installed as the package +implementation. That installation mode is designed for package +consumers, who normally use a package without modifying it. The +installed copy of the package is unsuitable for development by the +package author, however, since the installation is not a full clone of +the Git repository. The Racket package manager provides different +installation modes to support package authors who work with Git +repository clones. + + +@section{Linking a Git Checkout as a Directory} + +Since a Git repository checkout is a directory, it can be linked as a +package as described in @secref["working-new-pkgs"]. In that case, any +modifications made locally take effect immediately for the package +installation, including any updates from a @exec{git pull}. The +developer must explicitly pull any remote updates to the repository, +however, including when the updates are needed to satisfy the +requirements of dependent packages. + +In the following section, we describe an alternative that makes +@command-ref{update} aware of the checkout directory's status as a +repository clone. Furthermore, a directory-linked package can be +promoted to a clone-linked package with @command-ref{update}. + + +@section{Linking a Git Checkout as a Clone} + +When a package is installed with + +@commandline{@command{install} --clone @nonterm{dir} @nonterm{git-pkg-source}} + +then instead of installing the package as a mere copy of the +repository source, the package is installed by creating a Git clone of +@nonterm{git-pkg-source} as @nonterm{dir}. The clone's checkout is +linked in the same way as a directory, but unlike a plain directory +link, the Racket package manager keeps track of the repository +connection. + +When the repository at @nonterm{git-pkg-source} is changed so that the +source has a new checksum, then @command-ref{update} for the package pulls +commits from the repository to the local clone. In other words, +@command-ref{update} works as an alternative to @exec{git pull --ff-only} +to pull updates for the package. Furthermore, @command-ref{update} can +pull updates to local package repositories when checking dependencies. +For example, @exec{@command{update} --all} pulls updates for all +linked package repositories. + +Suppose that a developer works with a large number of packages and +develops only a few of them. The intended workflow is as follows: + +@itemlist[ + + @item{Install all the relevant packages with @command-ref{install}.} + + @item{For each package to be developed out of a particular Git + repository named by @nonterm{git-pkg-source}, update the installation with + + @commandline{@command{update} --clone @nonterm{dir} @nonterm{git-pkg-source}} + + which discards the original installation of the package and replaces + it with a local clone as @nonterm{dir}.} + + @item{Manage changes to each of the developed packages in the usual + way with @exec{git} tools, but @command-ref{update} is also available + for updates, including mass updates.} + +] + +A @tech{package source} provided with @DFlag{clone} can include a +branch and/or path into the repository. The branch specification +affects the branch used for the initial checkout, while a non-empty +path causes a subdirectory of the checkout to be linked for the +package. + +The package developer will work with both @exec{git} tools and +@exec{raco pkg} tools, and the tools interact in specific ways: + +@itemlist[ + + @item{With the link-establishing + + @commandline{@command{install} --clone @nonterm{dir} @nonterm{git-pkg-source}} + + or the same for @command-ref{update}, if a local repository exists + already as @nonterm{dir}, then it is left in place and any new + commits are fetched from @nonterm{git-pkg-source}. The package + manager does not attempt to check whether a pre-existing + repository is consistent with @nonterm{git-pkg-source}; it + simply starts fetching new commits to the repository, and a + later @exec{git pull --ff-only} will detect any mismatch. + + Multiple @nonterm{git-pkg-source}s can be provided to + @command-ref{install}, which makes sense when multiple packages are + sourced from the same repository and can therefore share + @nonterm{dir}. Whether through a single @exec{raco pkg} use or + multiple uses with the same @exec{--clone @nonterm{dir}}, + packages from the same repository should be linked from the + same local clone, assuming that they are in the same repository + because they should be modified together. The package system, + however, makes no requirement of clone sharing among the + packages.} + + @item{When pulling changes to repositories that have local copies, + @command-ref{update} pulls changes with the equivalent of @exec{git + pull --ff-only}.} + + @item{When @command-ref{update} is given a specific commit as the target + of the update, it uses the equivalent of @exec{git merge --ff-only + @nonterm{checksum}}. This approach is intended to preserve any + changes to the package made locally, but it implies that the + package cannot be ``downgraded'' to a older commit simply by + specifying the commit for @command-ref{update}; any newer commits + that are already in the local repository will be preserved.} + + @item{The installed-package database records the most recent commit + pulled from the source repository after each installation or + update. The current commit in the repository checkout is + consulted only for the purposes of merging onto pulled + commits. Thus, after pushing repository changes with @exec{git + push}, a @command-ref{update} makes sense to synchronize the + package-installation database with the remote repository state + (which is then the same as the local repository state).} + + @item{When checking a @command-ref{install} or @command-ref{update} + request for collisions, commits are first fetched with + @exec{git fetch}, and an additional local clone is created in a + temporary directory. If the overall installation or update is + deemed to be successful with respect to remote commits (not + necessarily the current commit in each local repository) in + that copy, then an update to the linked repository checkout + proceeds. Finally, after all checkouts succeed, other package + installations and updates are completed and recorded. If a + checkout fails (e.g., due to a conflict or uncommitted change), + then the repository checkout is left in a failed state, but all + package actions are otherwise canceled.} + + @item{Removing a package with @command-ref{remove} leaves the + repository checkout intact while removing the package link.} + +] diff --git a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/lib.scrbl b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/lib.scrbl index b0765a888e..1325976088 100644 --- a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/lib.scrbl +++ b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/lib.scrbl @@ -125,18 +125,27 @@ scope}.} @deftogether[( @defproc[(pkg-desc? [v any/c]) boolean?] @defproc[(pkg-desc [source string?] - [type (or/c #f 'file 'dir 'link 'static-link - 'file-url 'dir-url 'git 'github 'name)] + [type (or/c #f 'name 'file 'dir 'link 'static-link + 'file-url 'dir-url 'git 'github 'clone)] [name (or/c string? #f)] [checksum (or/c string? #f)] - [auto? boolean?]) + [auto? boolean?] + [#:path path (or/c #f path-string?) #f]) pkg-desc?] )]{ A @racket[pkg-desc] value describes a package source plus details of its intended interpretation, where the @racket[auto?] field indicates that the package is should be treated as installed automatically for a -dependency.} +dependency. + +The optional @racket[path] argument is intended for use when +@racket[type] is @racket['clone], in which case it specifies< a +directory containing the repository clone (where the repository itself +is a directory within @racket[path]). + +@history[#:changed "6.1.1.1" @elem{Added @racket['git] as a @racket[type].} + #:changed "6.1.1.5" @elem{Added @racket['clone] as a @racket[type].}]} @defproc[(pkg-stage [desc pkg-desc?] @@ -271,8 +280,12 @@ Implements @racket[pkg-update-command]. The result is the same as for @racket[pkg-install]. A string in @racket[names] refers to an installed package that should -be checked for updates. A @racket[pkg-desc] in @racket[names] indicates -a package source that should replace the current installation. +be checked for updates. A @racket[pkg-desc] in @racket[names] +indicates a package source that should replace the current +installation, except that a @racket[package-desc] can have the type +@racket['clone] and a source with the syntax of a package name, in +which case it refers to an existing package installation that should +be converted to a Git repository clone. If @racket[from-command-line?] is true, error messages may suggest specific command-line flags for @command-ref{update}. diff --git a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/name.scrbl b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/name.scrbl index 4fa675e71d..03b8e9c32d 100644 --- a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/name.scrbl +++ b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/name.scrbl @@ -14,15 +14,18 @@ extracting a package name.} @defproc[(package-source-format? [v any/c]) boolean?]{ Returns @racket[#t] if @racket[v] is @racket['name] , @racket['file], -@racket['dir], @racket['git], @racket['github], @racket['file-url], +@racket['dir], @racket['git], @racket['github], @racket['clone], @racket['file-url], @racket['dir-url], @racket['link], or @racket['static-link], and returns @racket[#f] otherwise. The @racket['link] and @racket['static-link] formats are the same as @racket['dir] in terms of parsing, but they are treated differently -for tasks such as package installation. +for tasks such as package installation. The @racket['clone] format +is similarly the same as @racket['github] or @racket['git] in terms of +parsing. -@history[#:changed "6.1.1.1" @elem{Added @racket['git].}]} +@history[#:changed "6.1.1.1" @elem{Added @racket['git].} + #:changed "6.1.1.5" @elem{Added @racket['clone].}]} @defproc[(package-source->name [source string?] diff --git a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/path.scrbl b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/path.scrbl index 321704d364..847f159d6e 100644 --- a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/path.scrbl +++ b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/path.scrbl @@ -18,7 +18,8 @@ databases.} @defstruct*[pkg-info ([orig-pkg (or/c (list/c 'catalog string?) (list/c 'url string?) (list/c 'link string?) - (list/c 'static-link string?))] + (list/c 'static-link string?) + (list/c 'clone string? string?))] [checksum (or/c #f string?)] [auto? boolean?]) #:prefab]{ diff --git a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/pkg.scrbl b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/pkg.scrbl index faf1dbaba5..b18cdd0a9f 100644 --- a/pkgs/racket-pkgs/racket-doc/pkg/scribblings/pkg.scrbl +++ b/pkgs/racket-pkgs/racket-doc/pkg/scribblings/pkg.scrbl @@ -378,7 +378,7 @@ directory @tech{package scopes}. The @exec{raco pkg} command provides package-management tools via sub-commands. -@command/toc{install} @nonterm{option} ... @nonterm{pkg-source} ... +@subcommand{@command/toc{install} @nonterm{option} ... @nonterm{pkg-source} ... --- Installs the given @tech{package sources} (eliminating exact-duplicate @nonterm{pkg-source}s). If a given @nonterm{pkg-source} is ``auto-installed'' (to satisfy some other package's dependency), then it is promoted to explicitly installed. @@ -432,7 +432,7 @@ sub-commands. @item{@DFlag{skip-implies} --- Disables special treatment of dependencies that are listed in @racketidfont{implies} (see @secref["metadata"]) for an installed or updated package.} - @item{@DFlag{link} --- Implies @exec{--type dir} (and overrides any specified type), + @item{@DFlag{link} --- Implies @exec{--type dir} and links the existing directory as an installed package, instead of copying the directory's content to install. Directory @tech{package sources} are treated as links by default, unless @DFlag{copy} is specified. @@ -447,12 +447,19 @@ sub-commands. of the given directory will not change for each given directory that implements a @tech{multi-collection package}.} - @item{@DFlag{pkgs} --- Disables default installation of the current directory when no @nonterm{pkg-source}s - are supplied.} - @item{@DFlag{copy} --- Disables default handling of directory @tech{package sources} as links, and instead treats them like other sources: package content is copied to install.} + @item{@DFlag{clone} @nonterm{dir} --- A Git or GitHub @tech{package + source} is cloned as @nonterm{dir} and locally linked as the + package implementation. Multiple @nonterm{pkg-source} + arguments make sense only if they all specify the same Git + repository (with different paths in the repository). The + @DFlag{clone} flag implies @DFlag{type} in the sense that each + @nonterm{pkg-source} must be either a Git or GitHub + @tech{package source}. See @secref["git-workflow"] for more + information.} + @item{@DFlag{binary} --- Strips source elements of a package before installing, and implies @DFlag{copy}.} @item{@DFlag{source} --- Strips built elements of a package before installing, and implies @DFlag{copy}.} @@ -477,6 +484,9 @@ sub-commands. whose name corresponds to an already-installed package, except for promoting auto-installed packages to explicitly installed.} + @item{@DFlag{pkgs} --- Disables default installation of the current directory when no @nonterm{pkg-source}s + are supplied.} + @item{@DFlag{all-platforms} --- Considers package dependencies independent of the current platform (instead of filtering dependencies to platforms other than the current one).} @@ -501,6 +511,7 @@ sub-commands. @item{@DFlag{fail-fast} --- Breaks @exec{raco setup} as soon as any error is encountered.} ] +@history[#:changed "6.1.1.5" @elem{Added the @DFlag{clone} flag.}]} @subcommand{@command/toc{update} @nonterm{option} ... @nonterm{pkg-source} ... @@ -513,13 +524,17 @@ any of the @nonterm{pkg-source}s (or their dependencies). If a @tech{package scope} is not specified, the scope is inferred from the given @nonterm{pkg-source}s. +If no @racket{pkg-source}, @DFlag{all} or @Flag{a} flag, or +@DFlag{clone} flag is specified, and if the current directory is +within a package, then the enclosing package is updated. + The @exec{update} sub-command accepts the following @nonterm{option}s: @itemlist[ @item{@DFlag{all} or @Flag{a} --- Update all packages, if no packages are given in the argument list.} - @item{@DFlag{lookup} --- Checks Causes a @tech{package name} as a @nonterm{pkg-source} to be used + @item{@DFlag{lookup} --- Causes a @tech{package name} as a @nonterm{pkg-source} to be used as a replacement, instead of the name of a installed package that may have updates. (If the named package was installed through a package name, then there's effectively no difference.)} @@ -534,6 +549,12 @@ the given @nonterm{pkg-source}s. @item{@DFlag{skip-implies} --- Same as for @command-ref{install}.} @item{@DFlag{link} --- Same as for @command-ref{install}.} @item{@DFlag{static-link} --- Same as for @command-ref{install}.} + @item{@DFlag{clone} @nonterm{dir} --- Same as for + @command-ref{install}, except that a @nonterm{pkg-source} can be + the name of an installed package. In that case, the package must + be currently installed from a Git or GitHub source, and that + source is used for the clone (which replaces the existing package + installation).} @item{@DFlag{binary} --- Same as for @command-ref{install}.} @item{@DFlag{copy} --- Same as for @command-ref{install}.} @item{@DFlag{source} --- Same as for @command-ref{install}.} @@ -550,6 +571,11 @@ the given @nonterm{pkg-source}s. @item{@DFlag{no-setup} --- Same as for @command-ref{install}.} @item{@DFlag{jobs} @nonterm{n} or @Flag{j} @nonterm{n} --- Same as for @command-ref{install}.} ] + +@history[#:changed "6.1.1.5" @elem{Added the @DFlag{clone} flag, and added + update of enclosing package when no + arguments are provided.}] + } @subcommand{@command/toc{remove} @nonterm{option} ... @nonterm{pkg} ... @@ -581,12 +607,15 @@ the given @nonterm{pkg}s. ] } -@subcommand{@command/toc{new} @nonterm{package} --- -Populates a directory with the stubs for a new racket package, where -@nonterm{package} is the name of the new package. -If @nonterm{package} already exists as a folder in the current directory, no new + +@subcommand{@command/toc{new} @nonterm{pkg} --- +Populates a directory with the stubs for a new package, where +@nonterm{pkg} is the name of the new package. +If @nonterm{pkg} already exists as a directory in the current directory, no new package is created. -} + +@history[#:added "6.1.1.5"]} + @subcommand{@command/toc{show} @nonterm{option} ... --- Print information about currently installed packages. By default, packages are shown for all @tech{package scopes}, but only for packages @@ -612,8 +641,7 @@ package is created. @item{@DFlag{scope-dir} @nonterm{dir} --- Shows only packages installed in @nonterm{dir}.} @item{@DFlag{version} @nonterm{vers} or @Flag{v} @nonterm{vers} --- Show only user-specific packages for the installation name/version @nonterm{vers}.} - ] -} + ]} @subcommand{@command/toc{migrate} @nonterm{option} ... @nonterm{from-version} --- Installs packages that were previously installed in @exec{user} @@ -980,6 +1008,10 @@ The following @filepath{info.rkt} fields are used by the package manager: @; ---------------------------------------- +@include-section["git-workflow.scrbl"] + +@; ---------------------------------------- + @include-section["apis.scrbl"] @include-section["catalog-protocol.scrbl"] diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/test-catalogs-api.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/test-catalogs-api.rkt index 866f7702ee..521063f96b 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/test-catalogs-api.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/test-catalogs-api.rkt @@ -18,10 +18,10 @@ (check-equal? (hash-ref (hash-ref details "pkg-test1") 'source) - "http://localhost:9999/pkg-test1.zip") + "http://localhost:9997/pkg-test1.zip") (check-equal? (hash-ref (hash-ref details "pkg-test2") 'source) - "http://localhost:9999/pkg-test2.zip") + "http://localhost:9997/pkg-test2.zip") (define test1-details (get-pkg-details-from-catalogs "pkg-test1")) (check-equal? test1-details @@ -30,7 +30,7 @@ (define-values (cksum mods deps) (get-pkg-content (pkg-desc "pkg-test1" #f #f #f #f))) (define-values (cksum1 mods1 deps1) - (get-pkg-content (pkg-desc "http://localhost:9999/pkg-test1.zip" #f #f #f #f))) + (get-pkg-content (pkg-desc "http://localhost:9997/pkg-test1.zip" #f #f #f #f))) (check-equal? cksum cksum1) (check-equal? (sort mods string #:key cadr) diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-catalogs.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-catalogs.rkt index ad51e70edc..9de6dba7f9 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-catalogs.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-catalogs.rkt @@ -29,13 +29,13 @@ $ (~a "raco pkg config --set catalogs file://" (path->string db)) $ "raco pkg catalog-show pkg-test1" - =stdout> #rx"Source: http://localhost:9999/pkg-test1.zip" + =stdout> #rx"Source: http://localhost:9997/pkg-test1.zip" (parameterize ([db:current-pkg-catalog-file db]) (db:set-pkgs! "local" (append (db:get-pkgs) (list - (db:pkg "fish" "local" "nemo@sub" "http://localhost:9999/fish.zip" "123" + (db:pkg "fish" "local" "nemo@sub" "http://localhost:9997/fish.zip" "123" "Not a whale")))) (db:set-pkg-modules! "fish" "local" "123" '((lib "fish/main.rkt") (lib "fish/food.rkt"))) (db:set-pkg-dependencies! "fish" "local" "123" @@ -78,7 +78,7 @@ (lambda (o) (write (hash 'name "whale" 'checksum cksum - 'source "http://localhost:9999/whale.plt" + 'source "http://localhost:9997/whale.plt" 'versions (hash "5.3.6" (hash 'checksum 123))) diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-checksums.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-checksums.rkt index bee0dca8a7..448c7d04b2 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-checksums.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-checksums.rkt @@ -43,7 +43,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-test1-bad-checksum.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-test1-bad-checksum.zip")) + "http://localhost:9997/pkg-test1-bad-checksum.zip")) $ "raco pkg config --set catalogs http://localhost:9990 http://localhost:9991" $ "racket -e '(require pkg-test1)'" =exit> 1 $ "raco pkg install pkg-test1" =exit> 1 @@ -53,20 +53,20 @@ (shelly-case "checksums are checked (remote)" $ "racket -e '(require pkg-test1)'" =exit> 1 - $ "raco pkg install http://localhost:9999/pkg-test1-bad-checksum.zip" =exit> 1 + $ "raco pkg install http://localhost:9997/pkg-test1-bad-checksum.zip" =exit> 1 $ "racket -e '(require pkg-test1)'" =exit> 1)) (with-fake-root (shelly-case "checksums are required by default remotely (remote)" $ "racket -e '(require pkg-test1)'" =exit> 1 - $ "raco pkg install http://localhost:9999/pkg-test1-no-checksum.zip" =exit> 1 + $ "raco pkg install http://localhost:9997/pkg-test1-no-checksum.zip" =exit> 1 $ "racket -e '(require pkg-test1)'" =exit> 1)) (shelly-install* "but, bad checksums can be ignored (local)" "--ignore-checksums test-pkgs/pkg-test1-bad-checksum.zip" "pkg-test1-bad-checksum") (shelly-install* "but, bad checksums can be ignored (remote)" - "--ignore-checksums http://localhost:9999/pkg-test1-bad-checksum.zip" + "--ignore-checksums http://localhost:9997/pkg-test1-bad-checksum.zip" "pkg-test1-bad-checksum") (shelly-install* "but, checksums can be missing if ignored (remote)" - "--ignore-checksums http://localhost:9999/pkg-test1-no-checksum.zip" + "--ignore-checksums http://localhost:9997/pkg-test1-no-checksum.zip" "pkg-test1-no-checksum")))) diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-clone.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-clone.rkt new file mode 100644 index 0000000000..924ef42caf --- /dev/null +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-clone.rkt @@ -0,0 +1,163 @@ +#lang racket/base +(require rackunit + racket/file + racket/format + web-server/servlet-env + "util.rkt" + "shelly.rkt") + +(this-test-is-run-by-the-main-test) + +(define (set-file path content) + (call-with-output-file* + path + #:exists 'truncate/replace + (lambda (o) (displayln content o)))) + +(pkg-tests + (define git-exe (find-executable-path + (if (eq? 'windows (system-type)) "git.exe" "git"))) + + (when git-exe + (define tmp-dir (path->directory-path (make-temporary-file "pkg~a" 'directory))) + (define http-custodian (make-custodian)) + + (parameterize ([current-custodian http-custodian]) + (thread + (lambda () + (serve/servlet + void + #:command-line? #t + #:extra-files-paths + (list tmp-dir) + #:servlet-regexp #rx"$." ; no servlets + #:port 9998)))) + + (shelly-wind + (sync (system-idle-evt)) ; let web server get going + + (define clone-dir (build-path tmp-dir "clones")) + (make-directory clone-dir) + + (define a-dir (build-path tmp-dir "a")) + + ;; ---------------------------------------- + ;; Single-package repository + + (make-directory a-dir) + $ (~a "cd " a-dir "; git init") + (set-file (build-path a-dir "main.rkt") "#lang racket/base 1") + (define (commit-changes-cmd [a-dir a-dir]) + (~a "cd " a-dir "; git add .; git commit -m change; git update-server-info")) + $ (commit-changes-cmd) + + (shelly-case + "basic --clone installation" + $ (~a "raco pkg install --clone " (build-path clone-dir "a") " --name a http://localhost:9998/a/.git") + $ "racket -l a" =stdout> "1\n") + + (shelly-case + "update of --clone installation" + (set-file (build-path a-dir "main.rkt") "#lang racket/base 2") + $ (commit-changes-cmd) + $ (~a "raco pkg update a") + $ "racket -l a" =stdout> "2\n") + + (shelly-case + "update of --clone installation doesn't overwrite local changes" + (set-file (build-path a-dir "main.rkt") "#lang racket/base 3") + $ (commit-changes-cmd) + (set-file (build-path clone-dir "a" "alt.rkt") "#lang racket/base 'one") + $ (~a "cd " (build-path clone-dir "a") "; git add .; git commit -m local") + $ "racket -l a" =stdout> "2\n" + $ "racket -l a/alt" =stdout> "'one\n" + $ (~a "raco pkg update a") =exit> 1 =stderr> #rx"fast-forward" + $ (~a "cd " (build-path clone-dir "a") "; git pull --rebase") + $ (~a "raco pkg update a") + $ "racket -l a" =stdout> "3\n" + $ "racket -l a/alt" =stdout> "'one\n") + + (shelly-case + "update of --clone installation doesn't proceed past conflicts" + (set-file (build-path a-dir "main.rkt") "#lang racket/base 4") + $ (commit-changes-cmd) + (set-file (build-path clone-dir "a" "main.rkt") "#lang racket/base 3.5") + $ (~a "raco pkg update a") =exit> 1 + $ "racket -l a" =stdout> "3.5\n") + + (shelly-case + "removal of --clone installation leaves local clone intact" + $ "raco pkg remove a" + $ "racket -l a" =exit> 1 + $ (~a "ls " (build-path clone-dir "a"))) + + (delete-directory/files (build-path clone-dir "a")) + (delete-directory/files a-dir) + + ;; ---------------------------------------- + ;; Multi-package repository + + (make-directory a-dir) + $ (~a "cd " a-dir "; git init") + (make-directory* (build-path a-dir "one")) + (set-file (build-path a-dir "one" "main.rkt") "#lang racket/base 1") + (make-directory* (build-path a-dir "two")) + (set-file (build-path a-dir "two" "main.rkt") "#lang racket/base 2") + $ (commit-changes-cmd) + + (shelly-case + "--clone installation with path into repository" + $ (~a "raco pkg install --clone " (build-path clone-dir "a") " --name one http://localhost:9998/a/.git?path=one") + $ "racket -l one" =stdout> "1\n" + $ (~a "ls " (build-path clone-dir "a"))) + + (shelly-case + "update of --clone installation" + (set-file (build-path a-dir "one" "main.rkt") "#lang racket/base 1.0") + $ (commit-changes-cmd) + $ (~a "raco pkg update one") + $ "racket -l one" =stdout> "1.0\n") + + (shelly-case + "--clone second installation with path into same repository" + (set-file (build-path a-dir "one" "main.rkt") "#lang racket/base 'one") + $ (commit-changes-cmd) + $ (~a "raco pkg install --clone " (build-path clone-dir "a") " http://localhost:9998/a/.git?path=two") + $ "racket -l one" =stdout> "'one\n" + $ "racket -l two" =stdout> "2\n") + + (shelly-case + "no changes => still an update, since previous update was implicit via shared repo" + $ "raco pkg update one" =stdout> #rx"Re-installing one\n") + + (shelly-case + "no further changes => no update" + $ "raco pkg update one two" =stdout> #rx"No updates available\n") + + $ "raco pkg remove one two" + + (shelly-case + "conflicting repositories with the same name" + (define another-a-dir (build-path tmp-dir "another" "a")) + (make-directory* another-a-dir) + $ (~a "cd " another-a-dir "; git init") + (make-directory* (build-path another-a-dir "two")) + (set-file (build-path another-a-dir "two" "main.rkt") "#lang racket/base 'two") + $ (commit-changes-cmd another-a-dir) + + ;; A wacky merge of repsitories will happen here, but the checkout should not + ;; get mangled. The package manager should bail out at the point that it would + ;; try to rebase the single "a" clone on different commits. + $ (~a "raco pkg install --clone " (build-path clone-dir "a") + " http://localhost:9998/a/.git?path=one" + " http://localhost:9998/another/a/.git?path=two") + =exit> 1 + =stderr> #rx"different target commits" + ;; Check that the old repo checkout is not mangled: + $ (~a "racket " (build-path clone-dir "a" "two" "main.rkt")) =stdout> "2\n") + + ;; ---------------------------------------- + + (finally + (custodian-shutdown-all http-custodian) + (delete-directory/files tmp-dir))))) diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-deps.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-deps.rkt index 4fbbb88e81..1493759a4e 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-deps.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-deps.rkt @@ -108,7 +108,7 @@ $ "racket -e '(require pkg-test2)'" =exit> 1 $ "raco pkg install --deps search-auto test-pkgs/pkg-test2.zip" =exit> 0 - =stdout> "Resolving \"pkg-test1\" via http://localhost:9990\nDownloading http://localhost:9999/pkg-test1.zip\nThe following uninstalled packages were listed as dependencies\nand they were automatically installed:\n dependencies of pkg-test2:\n pkg-test1\n" + =stdout> "Resolving \"pkg-test1\" via http://localhost:9990\nDownloading http://localhost:9997/pkg-test1.zip\nThe following uninstalled packages were listed as dependencies\nand they were automatically installed:\n dependencies of pkg-test2:\n pkg-test1\n" =stderr> "" $ "racket -e '(require pkg-test2)'" =exit> 0 $ "racket -e '(require pkg-test2/contains-dep)'" =exit> 0 diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-implies.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-implies.rkt index 65b8328748..4c3cd0292c 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-implies.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-implies.rkt @@ -20,13 +20,13 @@ (hasheq 'checksum (file->string (format "test-pkgs/pkg-implied-~a.zip.CHECKSUM" s)) 'source - (format "http://localhost:9999/pkg-implied-~a.zip" s)))) + (format "http://localhost:9997/pkg-implied-~a.zip" s)))) (implied-version! "one") (hash-set! *index-ht-1* "pkg-implies" (hasheq 'checksum (file->string "test-pkgs/pkg-implies.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-implies.zip")) + "http://localhost:9997/pkg-implies.zip")) (with-fake-root (shelly-begin diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-install.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-install.rkt index e388eae1a9..6840bef428 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-install.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-install.rkt @@ -59,9 +59,9 @@ $ "raco pkg install test-pkgs/pkg-test1.zip.CHECKSUM" =exit> 1) (shelly-install "remote/URL/http package (file, tgz)" - "http://localhost:9999/pkg-test1.tgz") + "http://localhost:9997/pkg-test1.tgz") (shelly-install "remote/URL/http package (directory)" - "http://localhost:9999/pkg-test1/") + "http://localhost:9997/pkg-test1/") (with-fake-root (shelly-begin @@ -96,19 +96,19 @@ (shelly-case "remote/URL/http directory, non-existant file" - $ "raco pkg install http://localhost:9999/pkg-test1.rar" =exit> 1) + $ "raco pkg install http://localhost:9997/pkg-test1.rar" =exit> 1) (shelly-case "remote/URL/http directory, no manifest fail" - $ "raco pkg install http://localhost:9999/pkg-test1/pkg-test1/" + $ "raco pkg install http://localhost:9997/pkg-test1/pkg-test1/" =exit> 1 =stderr> #rx"could not find MANIFEST") (shelly-case "remote/URL/http directory, bad manifest" ;; XXX why does this error now? - $ "raco pkg install http://localhost:9999/pkg-test1-manifest-error/" =exit> 1) + $ "raco pkg install http://localhost:9997/pkg-test1-manifest-error/" =exit> 1) (shelly-case "remote/URL/file, bad checksum" - $ "raco pkg install --checksum zzz http://localhost:9999/pkg-test1.tgz" + $ "raco pkg install --checksum zzz http://localhost:9997/pkg-test1.tgz" =exit> 1 =stderr> #rx"mismatched checksum") diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-migrate.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-migrate.rkt index a4eacc5f99..3c14f356d4 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-migrate.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-migrate.rkt @@ -15,12 +15,12 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-b-second.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-b-second.plt")) + "http://localhost:9997/pkg-b-second.plt")) (hash-set! *index-ht-1* "pkg-a" (hasheq 'checksum (file->string "test-pkgs/pkg-a-first.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-a-first.plt")) + "http://localhost:9997/pkg-a-first.plt")) $ "raco pkg install -u --deps search-auto pkg-b" =exit> 0 $ "raco pkg show -u -a" =stdout> #rx"Package\\[\\*=auto\\] +Checksum +Source\npkg-a\\* +[a-f0-9]+ \\(catalog pkg-a\\)\npkg-b +[a-f0-9]+ +\\(catalog pkg-b\\)\n" $ (~a "racket" diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-name.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-name.rkt index dd6afa22b8..c82de07ec4 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-name.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-name.rkt @@ -96,6 +96,8 @@ (check-equal-values? (parse "github://github.com/racket/fish.more/release" 'github) (values #f 'github #t)) (check-equal-values? (parse "github://github.com/racket/./release" #f #rx"indicator") (values #f 'github #f)) (check-equal-values? (parse "github://github.com/../fish/release" #f #rx"indicator") (values #f 'github #f)) + (check-equal-values? (parse "github://github.com/racket/fish/master" 'clone) (values "fish" 'clone #t)) + (check-equal-values? (parse "github://github.com/fish/master" 'clone #rx"three") (values #f 'clone #f)) (check-equal-values? (parse "git://github.com/racket/fish" #f) (values "fish" 'github #t)) (check-equal-values? (parse "git://github.com/racket/fish/" #f) (values "fish" 'github #t)) @@ -111,6 +113,8 @@ (check-equal-values? (parse "git://github.com/racket/fish.more" 'github) (values #f 'github #t)) (check-equal-values? (parse "git://github.com/racket/." #f #rx"indicator") (values #f 'github #f)) (check-equal-values? (parse "git://github.com/../fish" #f #rx"indicator") (values #f 'github #f)) + (check-equal-values? (parse "git://github.com/racket/fish" 'clone) (values "fish" 'clone #t)) + (check-equal-values? (parse "racket/fish" 'github) (values "fish" 'github #t)) (check-equal-values? (parse "git://not-github.com/racket/fish" #f #f) (values "fish" 'git #t)) (check-equal-values? (parse "git://not-github.com/fish" #f #f) (values "fish" 'git #t)) @@ -123,6 +127,8 @@ (check-equal-values? (parse "git://not-github.com/fish/?path=catfish/bill" #f) (values "bill" 'git #t)) (check-equal-values? (parse "git://not-github.com/../fish.git/" #f) (values "fish" 'git #t)) (check-equal-values? (parse "git://not-github.com/.././" #f #rx"indicator") (values #f 'git #f)) + (check-equal-values? (parse "git://not-github.com/racket/fish" 'clone #f) (values "fish" 'clone #t)) + (check-equal-values? (parse "git://not-github.com/.././" 'clone #rx"indicator") (values #f 'clone #f)) (check-equal-values? (parse "http://racket-lang.org/racket/fish" 'git #f) (values "fish" 'git #t)) (check-equal-values? (parse "https://racket-lang.org/racket/fish" 'git #f) (values "fish" 'git #t)) @@ -155,7 +161,7 @@ (check-equal-values? (parse "" 'file-url) (values #f 'file-url #f)) (check-equal-values? (parse "" 'dir-url) (values #f 'dir-url #f)) (check-equal-values? (parse "" 'git) (values #f 'git #f)) - (check-equal-values? (parse "" 'github #rx"empty") (values #f 'github #f)) + (check-equal-values? (parse "" 'github #rx"two path elements") (values #f 'github #f)) (void)) diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-raco.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-raco.rkt index f733d1308e..cac26ba656 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-raco.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-raco.rkt @@ -48,7 +48,7 @@ $ "cp -f test-pkgs/pkg-test1.zip test-pkgs/update-test/pkg-test1.zip" $ "cp -f test-pkgs/pkg-test1.zip.CHECKSUM test-pkgs/update-test/pkg-test1.zip.CHECKSUM" (shelly-install* "remote packages can be updated" - "http://localhost:9999/update-test/pkg-test1.zip" + "http://localhost:9997/update-test/pkg-test1.zip" "pkg-test1 pkg-test3" $ "raco pkg install --copy test-pkgs/pkg-test3" $ "racket -l pkg-test3/number" =exit> 1 diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update-auto.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update-auto.rkt index 86cc10b446..598113f72b 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update-auto.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update-auto.rkt @@ -11,7 +11,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-b-first.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-b-first.plt")) + "http://localhost:9997/pkg-b-first.plt")) $ "raco pkg config --set catalogs http://localhost:9990" $ "raco pkg install pkg-b" $ "racket -e '(require pkg-b)'" =exit> 42 @@ -19,12 +19,12 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-b-second.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-b-second.plt")) + "http://localhost:9997/pkg-b-second.plt")) (hash-set! *index-ht-1* "pkg-a" (hasheq 'checksum (file->string "test-pkgs/pkg-a-first.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-a-first.plt")))) + "http://localhost:9997/pkg-a-first.plt")))) (pkg-tests (shelly-case @@ -41,12 +41,12 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-b-second.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-b-second.plt")) + "http://localhost:9997/pkg-b-second.plt")) (hash-set! *index-ht-1* "pkg-a" (hasheq 'checksum (file->string "test-pkgs/pkg-a-first.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-a-first.plt")) + "http://localhost:9997/pkg-a-first.plt")) $ "raco pkg install --deps search-auto pkg-b" =exit> 0 #rx"Package\\[\\*=auto\\] +Checksum +Source\npkg-a\\* +[a-f0-9]+ \\(catalog pkg-a\\)\npkg-b +[a-f0-9]+ +\\(catalog pkg-b\\)\n" $ "racket -e '(require pkg-b)'" =exit> 43 @@ -61,7 +61,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-a-second.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-a-second.plt")) + "http://localhost:9997/pkg-a-second.plt")) $ "raco pkg update -a" =exit> 0 $ "racket -e '(require pkg-a)'" =exit> 43 $ "raco pkg remove pkg-b" diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update-deps.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update-deps.rkt index 7eb2290b66..5e8757de00 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update-deps.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update-deps.rkt @@ -11,7 +11,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-b-first.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-b-first.plt")) + "http://localhost:9997/pkg-b-first.plt")) $ "raco pkg config --set catalogs http://localhost:9990" $ "raco pkg install pkg-b" $ "racket -e '(require pkg-b)'" =exit> 42 @@ -19,12 +19,12 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-b-second.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-b-second.plt")) + "http://localhost:9997/pkg-b-second.plt")) (hash-set! *index-ht-1* "pkg-a" (hasheq 'checksum (file->string "test-pkgs/pkg-a-first.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-a-first.plt")))) + "http://localhost:9997/pkg-a-first.plt")))) (pkg-tests (shelly-case @@ -86,7 +86,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-a-second.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-a-second.plt")) + "http://localhost:9997/pkg-a-second.plt")) $ "racket -e '(require pkg-a)'" =exit> 0 $ "raco pkg update pkg-a" =exit> 0 $ "racket -e '(require pkg-a)'" =exit> 43 @@ -104,7 +104,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-a-third.plt.CHECKSUM") 'source - "http://localhost:9999/pkg-a-third.plt")) + "http://localhost:9997/pkg-a-third.plt")) $ "racket -e '(require pkg-a)'" =exit> 0 $ "raco pkg update pkg-a" =exit> 1 $ "racket -e '(require pkg-a)'" =exit> 0 diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update.rkt index 32cc4c0b3f..d206036a17 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-update.rkt @@ -78,7 +78,7 @@ $ "cp -f test-pkgs/pkg-test1.zip test-pkgs/update-test/pkg-test1.zip" $ "cp -f test-pkgs/pkg-test1.zip.CHECKSUM test-pkgs/update-test/pkg-test1.zip.CHECKSUM" (shelly-install* "remote packages can be updated" - "http://localhost:9999/update-test/pkg-test1.zip" + "http://localhost:9997/update-test/pkg-test1.zip" "pkg-test1" $ "raco pkg update pkg-test1" =exit> 0 =stdout> "Downloading checksum for pkg-test1\nNo updates available\n" $ "racket -e '(require pkg-test1/update)'" =exit> 42 @@ -95,7 +95,7 @@ $ "cp -f test-pkgs/pkg-test3.zip test-pkgs/update-test/pkg-test3.zip" $ "cp -f test-pkgs/pkg-test3.zip.CHECKSUM test-pkgs/update-test/pkg-test3.zip.CHECKSUM" (shelly-install* "remote packages can be updated, single-collection to multi-collection" - "test-pkgs/pkg-test1.zip http://localhost:9999/update-test/pkg-test3.zip" + "test-pkgs/pkg-test1.zip http://localhost:9997/update-test/pkg-test3.zip" "pkg-test1 pkg-test3" $ "raco pkg update pkg-test3" =exit> 0 =stdout> "Downloading checksum for pkg-test3\nNo updates available\n" $ "cp -f test-pkgs/pkg-test3-v2.zip test-pkgs/update-test/pkg-test3.zip" @@ -111,7 +111,7 @@ $ "cp -f test-pkgs/pkg-test3-v2.zip test-pkgs/update-test/pkg-test3.zip" $ "cp -f test-pkgs/pkg-test3-v2.zip.CHECKSUM test-pkgs/update-test/pkg-test3.zip.CHECKSUM" (shelly-install* "remote packages can be updated, multi-colelction to single-collection" - "test-pkgs/pkg-test1.zip http://localhost:9999/update-test/pkg-test3.zip" + "test-pkgs/pkg-test1.zip http://localhost:9997/update-test/pkg-test3.zip" "pkg-test1 pkg-test3" $ "raco pkg update pkg-test3" =exit> 0 =stdout> "Downloading checksum for pkg-test3\nNo updates available\n" $ "cp -f test-pkgs/pkg-test3.zip test-pkgs/update-test/pkg-test3.zip" @@ -129,9 +129,9 @@ $ "cp -f test-pkgs/pkg-test2.zip test-pkgs/update-test/pkg-test2.zip" $ "cp -f test-pkgs/pkg-test2.zip.CHECKSUM test-pkgs/update-test/pkg-test2.zip.CHECKSUM" (shelly-install* "update deps" - "http://localhost:9999/update-test/pkg-test1.zip" + "http://localhost:9997/update-test/pkg-test1.zip" "pkg-test1" - $ "raco pkg install http://localhost:9999/update-test/pkg-test2.zip" + $ "raco pkg install http://localhost:9997/update-test/pkg-test2.zip" $ "raco pkg update --update-deps pkg-test2" =exit> 0 =stdout> "Downloading checksum for pkg-test2\nDownloading checksum for pkg-test1\nNo updates available\n" $ "racket -e '(require pkg-test1/update)'" =exit> 42 @@ -151,9 +151,9 @@ $ "cp -f test-pkgs/pkg-test3.zip test-pkgs/update-test/pkg-test3.zip" $ "cp -f test-pkgs/pkg-test3.zip.CHECKSUM test-pkgs/update-test/pkg-test3.zip.CHECKSUM" (shelly-install* "update original and deps" - "http://localhost:9999/update-test/pkg-test1.zip" + "http://localhost:9997/update-test/pkg-test1.zip" "pkg-test1" - $ "raco pkg install http://localhost:9999/update-test/pkg-test3.zip" + $ "raco pkg install http://localhost:9997/update-test/pkg-test3.zip" $ "raco pkg update --update-deps pkg-test3" =exit> 0 =stdout> "Downloading checksum for pkg-test3\nDownloading checksum for pkg-test1\nNo updates available\n" $ "racket -e '(require pkg-test1/update)'" =exit> 42 @@ -176,9 +176,9 @@ $ "cp -f test-pkgs/pkg-test3.zip test-pkgs/update-test/pkg-test3.zip" $ "cp -f test-pkgs/pkg-test3.zip.CHECKSUM test-pkgs/update-test/pkg-test3.zip.CHECKSUM" (shelly-install* "update original, where update has no deps" - "http://localhost:9999/update-test/pkg-test1.zip" + "http://localhost:9997/update-test/pkg-test1.zip" "pkg-test1" - $ "raco pkg install http://localhost:9999/update-test/pkg-test3.zip" + $ "raco pkg install http://localhost:9997/update-test/pkg-test3.zip" $ "raco pkg update --update-deps pkg-test3" =exit> 0 =stdout> "Downloading checksum for pkg-test3\nDownloading checksum for pkg-test1\nNo updates available\n" $ "racket -e '(require pkg-test1/update)'" =exit> 42 @@ -201,9 +201,9 @@ $ "cp -f test-pkgs/pkg-test3-v3.zip test-pkgs/update-test/pkg-test3.zip" $ "cp -f test-pkgs/pkg-test3-v3.zip.CHECKSUM test-pkgs/update-test/pkg-test3.zip.CHECKSUM" (shelly-install* "update and get updates for newly introduced deps" - "http://localhost:9999/update-test/pkg-test1.zip" + "http://localhost:9997/update-test/pkg-test1.zip" "pkg-test1" - $ "raco pkg install http://localhost:9999/update-test/pkg-test3.zip" + $ "raco pkg install http://localhost:9997/update-test/pkg-test3.zip" $ "racket -e '(require pkg-test3)'" =stdout> #rx"version 3 loaded" $ "raco pkg update --update-deps pkg-test3" =exit> 0 =stdout> "Downloading checksum for pkg-test3\nNo updates available\n" @@ -225,7 +225,7 @@ $ "cp -f test-pkgs/pkg-test1.zip test-pkgs/update-test/pkg-test1.zip" $ "cp -f test-pkgs/pkg-test1.zip.CHECKSUM test-pkgs/update-test/pkg-test1.zip.CHECKSUM" (shelly-install* "update all" - "http://localhost:9999/update-test/pkg-test1.zip" + "http://localhost:9997/update-test/pkg-test1.zip" "pkg-test1" $ "raco pkg install test-pkgs/pkg-test2.zip" $ "raco pkg update -a" =exit> 0 =stdout> "Downloading checksum for pkg-test1\nNo updates available\n" diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-versions.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-versions.rkt index f3e38b16c6..b901618b83 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/tests-versions.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/tests-versions.rkt @@ -30,13 +30,13 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-v-one.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-v-one.zip")) + "http://localhost:9997/pkg-v-one.zip")) (hash-set! *index-ht-1* "pkg-w" (hasheq 'checksum (file->string "test-pkgs/pkg-w-one.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-w-one.zip")) + "http://localhost:9997/pkg-w-one.zip")) $ "raco pkg config --set catalogs http://localhost:9990" @@ -57,7 +57,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-v-two.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-v-two.zip")) + "http://localhost:9997/pkg-v-two.zip")) (shelly-case "update" @@ -68,12 +68,12 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-v-three.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-v-three.zip")) + "http://localhost:9997/pkg-v-three.zip")) (hash-set! *index-ht-1* "pkg-w" (hasheq 'checksum (file->string "test-pkgs/pkg-w-two.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-w-two.zip")) + "http://localhost:9997/pkg-w-two.zip")) (shelly-case "update again" @@ -85,7 +85,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-w-three.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-w-three.zip")) + "http://localhost:9997/pkg-w-three.zip")) (shelly-case "update again" diff --git a/pkgs/racket-pkgs/racket-test/tests/pkg/util.rkt b/pkgs/racket-pkgs/racket-test/tests/pkg/util.rkt index 3220ecb1fe..29eec9802a 100644 --- a/pkgs/racket-pkgs/racket-test/tests/pkg/util.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/pkg/util.rkt @@ -108,7 +108,7 @@ (define (start-file-server) (serve/servlet (λ (req) (response/xexpr "None")) #:command-line? #t - #:port 9999 + #:port 9997 #:extra-files-paths (list (build-path test-directory "test-pkgs")))) (require "basic-index.rkt") @@ -192,7 +192,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-test1.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-test1.zip" + "http://localhost:9997/pkg-test1.zip" 'tags '("first"))) @@ -200,7 +200,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-test2.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-test2.zip" + "http://localhost:9997/pkg-test2.zip" 'dependencies '("pkg-test1"))) @@ -208,7 +208,7 @@ (hasheq 'checksum (file->string "test-pkgs/pkg-test2.zip.CHECKSUM") 'source - "http://localhost:9999/pkg-test2.zip" + "http://localhost:9997/pkg-test2.zip" 'dependencies '("pkg-test1")))) diff --git a/racket/collects/pkg/lib.rkt b/racket/collects/pkg/lib.rkt index 5b3ef7a2fa..e37c3fa5a7 100644 --- a/racket/collects/pkg/lib.rkt +++ b/racket/collects/pkg/lib.rkt @@ -34,6 +34,12 @@ (or/c 'installation 'user (and/c path? complete-path?))) +(define pkg-desc/opt + (let ([pkg-desc (lambda (source type name checksum auto? + #:path [path #f]) + (pkg-desc source type name checksum auto? path))]) + pkg-desc)) + (provide (all-from-out "path.rkt") with-pkg-lock @@ -58,13 +64,15 @@ (parameter/c (or/c #f real?))] [pkg-directory (-> string? (or/c path-string? #f))] - [pkg-desc - (-> string? - (or/c #f 'file 'dir 'link 'static-link 'file-url 'dir-url 'git 'github 'name) - (or/c string? #f) - (or/c string? #f) - boolean? - pkg-desc?)] + [rename + pkg-desc/opt pkg-desc + (->* (string? + (or/c #f 'file 'dir 'link 'static-link 'file-url 'dir-url 'git 'github 'clone 'name) + (or/c string? #f) + (or/c string? #f) + boolean?) + (#:path (or/c #f path-string?)) + pkg-desc?)] [pkg-config (->* (boolean? (listof string?)) (#:from-command-line? boolean?) diff --git a/racket/collects/pkg/main.rkt b/racket/collects/pkg/main.rkt index a5a68c2980..10e51a4819 100644 --- a/racket/collects/pkg/main.rkt +++ b/racket/collects/pkg/main.rkt @@ -114,7 +114,8 @@ #:install-force-flags (install-force-flags ...) #:update-deps-flags (update-deps-flags ...) #:install-copy-flags (install-copy-flags ...) - #:install-copy-defns (install-copy-defns ...)) + #:install-copy-defns (install-copy-defns ...) + #:install-copy-checks (install-copy-checks ...)) (with-syntax ([([scope-flags ...] [job-flags ...] [catalog-flags ...] @@ -123,7 +124,8 @@ [install-force-flags ...] [update-deps-flags ...] [install-copy-flags ...] - [install-copy-defns ...]) + [install-copy-defns ...] + [install-copy-checks ...]) (syntax-local-introduce #'([scope-flags ...] [job-flags ...] [catalog-flags ...] @@ -132,7 +134,8 @@ [install-force-flags ...] [update-deps-flags ...] [install-copy-flags ...] - [install-copy-defns ...]))]) + [install-copy-defns ...] + [install-copy-checks ...]))]) #`(commands "This tool is used for managing installed packages." "pkg-~a-command" @@ -167,6 +170,7 @@ 'install scope scope-dir installation user #f a-type (lambda () + install-copy-checks ... (when (and name (> (length pkg-source) 1)) ((current-pkg-error) (format "the --name flag only makes sense with a single package source"))) (unless (or (not name) (package-source->name name)) @@ -199,7 +203,9 @@ #:force-strip? force #:link-dirs? link-dirs? (for/list ([p (in-list sources)]) - (pkg-desc p a-type* name checksum #f)))))) + (pkg-desc p a-type* name checksum #f + #:path (and (eq? a-type* 'clone) + (path->complete-path clone)))))))) (setup "installed" no-setup fail-fast setup-collects jobs)))] ;; ---------------------------------------- [update @@ -226,40 +232,53 @@ job-flags ... #:args pkg-source install-copy-defns ... - (call-with-package-scope - 'update - scope scope-dir installation user pkg-source #f - (lambda () - (define setup-collects - (with-pkg-lock - (parameterize ([current-pkg-catalogs (and catalog - (list (catalog->url catalog)))]) - (pkg-update (for/list ([pkg-source (in-list pkg-source)]) - (cond - [lookup - (pkg-desc pkg-source a-type name checksum #f)] - [else - (define-values (pkg-name pkg-type) - (package-source->name+type pkg-source a-type)) - (if (eq? pkg-type 'name) - pkg-name - (pkg-desc pkg-source a-type name checksum #f))])) - #:from-command-line? #t - #:all? all - #:dep-behavior (if auto 'search-auto deps) - #:all-platforms? all-platforms - #:force? force - #:ignore-checksums? ignore-checksums - #:strict-doc-conflicts? strict-doc-conflicts - #:use-cache? (not no-cache) - #:update-deps? (or update-deps auto) - #:update-implies? (not ignore-implies) - #:strip (or (and source 'source) - (and binary 'binary) - (and binary-lib 'binary-lib)) - #:force-strip? force - #:link-dirs? link-dirs?)))) - (setup "updated" no-setup #f setup-collects jobs)))] + (let ([pkg-source (cond + [(and (null? pkg-source) + (not all) + (not clone)) + ;; In a package directory? + (define pkg (path->pkg (current-directory))) + (if pkg + (list pkg) + null)] + [else pkg-source])]) + (call-with-package-scope + 'update + scope scope-dir installation user pkg-source #f + (lambda () + install-copy-checks ... + (define setup-collects + (with-pkg-lock + (parameterize ([current-pkg-catalogs (and catalog + (list (catalog->url catalog)))]) + (pkg-update (for/list ([pkg-source (in-list pkg-source)]) + (cond + [lookup + (pkg-desc pkg-source a-type name checksum #f)] + [else + (define-values (pkg-name pkg-type) + (package-source->name+type pkg-source a-type)) + (if (eq? pkg-type 'name) + pkg-name + (pkg-desc pkg-source a-type name checksum #f + #:path (and (eq? a-type 'clone) + (path->complete-path clone))))])) + #:from-command-line? #t + #:all? all + #:dep-behavior (if auto 'search-auto deps) + #:all-platforms? all-platforms + #:force? force + #:ignore-checksums? ignore-checksums + #:strict-doc-conflicts? strict-doc-conflicts + #:use-cache? (not no-cache) + #:update-deps? (or update-deps auto) + #:update-implies? (not ignore-implies) + #:strip (or (and source 'source) + (and binary 'binary) + (and binary-lib 'binary-lib)) + #:force-strip? force + #:link-dirs? link-dirs?)))) + (setup "updated" no-setup #f setup-collects jobs))))] ;; ---------------------------------------- [remove "Remove packages" @@ -559,12 +578,29 @@ ([#:bool link () ("Link a directory package source in place (default for a directory)")] [#:bool static-link () ("Link in place, promising collections do not change")] [#:bool copy () ("Treat directory sources the same as other sources")] + [(#:str dir #f) clone () ("Clone Git and GitHub package sources to