diff --git a/.github/workflows/site.yaml b/.github/workflows/site.yaml
new file mode 100644
index 00000000..ca519739
--- /dev/null
+++ b/.github/workflows/site.yaml
@@ -0,0 +1,67 @@
+name: Deploy site
+on:
+ push:
+ branches:
+ - scratch/deploy-site
+ tags:
+ - 'v[0-9]+.[0-9]+.[0-9]+'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - name: Install Hugo
+ shell: bash
+ run: |
+ tdir=$(mktemp -d)
+ tgz=$tdir/hugo.tar.gz
+ bin=$HOME/bin
+ mkdir -p "$bin"
+
+ url=https://github.com/gohugoio/hugo/releases/download
+ curl -fSsL --retry 3 \
+ "$url/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz" \
+ >"$tgz"
+ printf '%s %s\n' "$HUGO_SHA" "$tgz" | sha256sum --check >/dev/null
+
+ tar --to-stdout --extract -zf "$tgz" hugo >"$bin"/hugo
+ chmod +x "$bin/hugo"
+ "$bin"/hugo version
+ echo "$bin" >>"$GITHUB_PATH"
+ env:
+ HUGO_VERSION: '0.133.0'
+ HUGO_SHA: '372530e2de9ae74087a987ca841429390a055123b8a4dec665cc601f10dc8e6e'
+ - uses: actions/configure-pages@v5
+ id: pages
+ - name: Check URL match
+ shell: bash
+ run: |
+ url=$(grep '^baseURL:' docs/site/hugo.yaml)
+ test "${{ steps.pages.outputs.base_url }}/" = "${url#baseURL: }"
+ - name: Build site
+ shell: bash
+ run: make -C docs/site build
+ env:
+ HUGO_ENVIRONMENT: production
+ HUGO_CACHEDIR: ${{ runner.temp }}/hugo_cache
+ TZ: America/New_York
+ - name: Upload site
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ./docs/site/public
+ deploy:
+ needs: build
+ runs-on: ubuntu-latest
+ permissions:
+ pages: write
+ id-token: write
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/README.md b/README.md
index 945b3b2c..1bcc616c 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
# pkgr
-For additional details of how to use pkgr, please see the [user manual](https://github.com/metrumresearchgroup/pkgr/wiki/user_manual)
+Documentation for `pkgr` is available at
+.
-# What is pkgr?
+## What is pkgr?
`pkgr` is a rethinking of the way packages are managed in R. Namely, it embraces
the declarative philosophy of defining _ideal state_ of the entire system, and working
@@ -10,7 +11,7 @@ towards achieving that objective. Furthermore, `pkgr` is built with a focus on r
and auditability of what is going on, a vital component for the pharmaceutical sciences + enterprises.
-# Why pkgr?
+## Why pkgr?
`install.packages` and friends such as `remotes::install_github` have a subtle weakness --
they are not good at controlling desired global state. There are some knobs that
@@ -31,14 +32,14 @@ the same set of responsibilities (dealing with dataframes + dealing with other l
As such, it is becoming increasingly difficult to manage the _set_ of packages in a transparent and robust
way.
-### how does it compare with pak can be read about [here](https://github.com/metrumresearchgroup/pkgr/issues/222#issuecomment-576340217)
-
+> [!NOTE]
+> How pkgr compares with pak can be read about [here](https://github.com/metrumresearchgroup/pkgr/issues/222#issuecomment-576340217).
## pkgr in action
[![asciicast](https://asciinema.org/a/wgcPBvCMtEwhpdW793MBjgSi2.svg)](https://asciinema.org/a/wgcPBvCMtEwhpdW793MBjgSi2)
-# Getting Started
+## Getting Started
### OSX and Linux installation
@@ -56,13 +57,17 @@ Pkgr for Windows is supported, but we have not yet published on a Windows-compat
- The destination folder should be on your Windows PATH. You may need to [modify your Windows PATH environment variable](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) to make this happen.
- If you do not already have a preferred way of accomplishing the above, we suggest creating a folder called "apps" in your home directory, then adding the "apps" directory to your PATH. From there, simply make sure that the `pkgr.exe` file from the tarball ends up in your "apps/" directory.
-# How it works
+## How it works
+
+> [!NOTE]
+> For additional details of how to use pkgr, please see the
+> [user manual](https://github.com/metrumresearchgroup/pkgr/wiki/user_manual).
`pkgr` is a command line utility with several top level commands. The two primary commands are:
```bash
pkgr plan # show what would happen if install is run
-pkgr install # install the packages specified in pkgr.config
+pkgr install # install the packages specified in pkgr.yml
```
The actions are controlled by a configuration file that specifies the desired global state, namely,
by defining the top level packages a user cares about, as well as specific configuration customizations.
@@ -184,7 +189,7 @@ Logging:
overwrite: true
```
-# pkgr and [packrat](https://rstudio.github.io/packrat/) and renv
+## pkgr and [packrat](https://rstudio.github.io/packrat/) and renv
**Pkgr is not a replacement for Packrat/renv -- Pkgr is complementary to packrat/renv**.
@@ -207,3 +212,23 @@ Pkgr solves these issues by:
- Providing timely error messages and halting the installation process immediately when something goes wrong during the
installation process (such as a package not being available, a repository being unreachable, etc.)
+## Development
+
+To run the test suite, you can invoke [scripts/run-unit-tests][ru] and
+[scripts/run-integration-tests][ri] directly or via `make vt-test`.
+
+After updating a subcommand, regenerate the Markdown documentation at
+[docs/commands][dc] by running `make vt-gen-docs`. See `make vt-help` and
+[internal/valtools/README.md][vr] for more details on the validation tooling.
+
+The setup for building the documentation site is described in
+[docs/site/README.md][dr].
+
+
+
+
+[dc]: https://github.com/metrumresearchgroup/pkgr/blob/main/docs/commands
+[dr]: https://github.com/metrumresearchgroup/pkgr/blob/main/docs/site/README.md
+[ri]: https://github.com/metrumresearchgroup/pkgr/blob/main/scripts/run-integration-tests
+[ru]: https://github.com/metrumresearchgroup/pkgr/blob/main/scripts/run-unit-tests
+[vr]: https://github.com/metrumresearchgroup/pkgr/blob/main/internal/valtools/README.md
diff --git a/cmd/add.go b/cmd/add.go
index 445e3418..bf968574 100644
--- a/cmd/add.go
+++ b/cmd/add.go
@@ -26,18 +26,22 @@ import (
// installCmd represents the R CMD install command
var addCmd = &cobra.Command{
- Use: "add [package name1] [package name2] [package name3] ...",
- Short: "add one or more packages",
- Long: `
- add package/s to the configuration file and optionally install
-`,
+ Use: "add [flags] [...]",
+ Short: "Add packages to the configuration file",
+ Long: `Add the specified packages to the 'Packages' section of the
+configuration file.`,
+ Example: ` # Add mrgsolve and bbr to list of packages
+ pkgr add mrgsolve bbr
+ # Add rlang and then do installation
+ # (same result as following up with 'pkgr install' call)
+ pkgr add --install rlang`,
RunE: rAdd,
}
var install bool
func init() {
- addCmd.Flags().BoolVar(&install, "install", false, "install package/s after adding")
+ addCmd.Flags().BoolVar(&install, "install", false, "run install after updating config")
RootCmd.AddCommand(addCmd)
}
diff --git a/cmd/clean.go b/cmd/clean.go
index bb3cf86d..9ac98ff1 100644
--- a/cmd/clean.go
+++ b/cmd/clean.go
@@ -26,10 +26,22 @@ var cleanAll bool
// CleanCmd represents the clean command
var CleanCmd = &cobra.Command{
- Use: "clean",
- Short: "clean up cached information",
- Long: "clean up cached source files and binaries, as well as the saved package database.",
- RunE: clean,
+ Use: `clean [flags]`,
+ Short: "Clean cached information",
+ Long: `This subcommand is an entry point for cleaning two categories of cached
+data:
+
+ * source and binary tarballs
+
+ Use the 'cache' subcommand to remove these.
+
+ * package databases with information about the packages available from
+ repositories
+
+ Use the 'pkgdbs' subcommand to remove these.
+
+To remove cached data for both categories, pass the --all flag.`,
+ RunE: clean,
}
func init() {
diff --git a/cmd/cleanCache.go b/cmd/cleanCache.go
index 627a3a2b..923c19c3 100644
--- a/cmd/cleanCache.go
+++ b/cmd/cleanCache.go
@@ -35,22 +35,27 @@ var reposToClear string
// cacheCmd represents the cache command
var cleanCacheCmd = &cobra.Command{
Use: "cache",
- Short: "Subcommand to clean cached source and binary files.",
- Long: `This command is a subcommand of the "clean" command.
-
- Using this command deletes cached source and binary files. Use the
- --src and --binary options to specify which repos to clean each
- file type from.
-
- `,
+ Short: "Clean cached package tarballs",
+ Long: `Delete cached tarballs for source and binary packages. Both source and
+binary files are deleted if neither the --src-only or --binaries-only flags
+is specified.
+
+By default, files for all repositories are deleted unless specific
+repositories are specified via the --repos option. Note that the value must
+match the directory name in the cache, including the unique ID that is
+appended to the repository name.`,
+ Example: ` # Clean binary files for all repos
+ pkgr clean cache --binaries-only
+ # Clean binaries files for MPN-889df4238bae repo
+ pkgr clean cache --repos=MPN-889df4238bae --binaries-only`,
RunE: cache,
}
func init() {
//cleanCacheCmd.Flags().BoolVar(&cleanAllFromCache, "all", true, "Clean both src and binary files from the cache.")
- cleanCacheCmd.Flags().BoolVar(&srcOnly, "src-only", false, "Clean only src files from the cache")
- cleanCacheCmd.Flags().BoolVar(&binariesOnly, "binaries-only", false, "Clean only binary files from the cache")
- cleanCacheCmd.Flags().StringVar(&reposToClear, "repos", "ALL", "Comma separated list of repositories to be cleaned. Defaults to all.")
+ cleanCacheCmd.Flags().BoolVar(&srcOnly, "src-only", false, "clean only source files from the cache")
+ cleanCacheCmd.Flags().BoolVar(&binariesOnly, "binaries-only", false, "clean only binary files from the cache")
+ cleanCacheCmd.Flags().StringVar(&reposToClear, "repos", "ALL", "comma-separated list of repositories to be cleaned. Defaults to all.")
CleanCmd.AddCommand(cleanCacheCmd)
}
diff --git a/cmd/cleanPkgdb.go b/cmd/cleanPkgdb.go
index 288e3968..09a51246 100644
--- a/cmd/cleanPkgdb.go
+++ b/cmd/cleanPkgdb.go
@@ -29,17 +29,19 @@ var pkgdbsToClearArgument string
// pkgdbCmd represents the pkgdb command
var pkgdbsCmd = &cobra.Command{
Use: "pkgdbs",
- Short: "Subcommand to clean cached pkgdbs",
- Long: `This command parses the currently-cached pkgdbs and removes all
- of them by default, or specific ones if desired. Identify specific repos using the "repos" argument, i.e.
- pkgr clean pkgdbs --repos="CRAN,r_validated"
- Repo names should match names in the pkgr.yml file.`,
+ Short: "Clean cached package databases",
+ Long: `Delete cached package databases. By default, remove cached databases for
+every repository listed in the active configuration file. If the --repos option
+is passed, remove only the cached databases for those repositories. Repo names
+should match the names in the configuration file.`,
+ Example: ` # Clean package databases for CRAN and MPN
+ pkgr clean pkgdbs --repos=CRAN,MPN`,
RunE: executeCommand,
}
func init() {
- pkgdbsCmd.Flags().StringVar(&pkgdbsToClearArgument, "repos", "ALL", "Set the repos you wish to clear the pkgdbs for.")
+ pkgdbsCmd.Flags().StringVar(&pkgdbsToClearArgument, "repos", "ALL", "clear databases for these repos")
CleanCmd.AddCommand(pkgdbsCmd)
}
diff --git a/cmd/inspect.go b/cmd/inspect.go
index cd7ed567..f74da871 100644
--- a/cmd/inspect.go
+++ b/cmd/inspect.go
@@ -29,11 +29,30 @@ import (
// inspectCmd shows the install inspect
var inspectCmd = &cobra.Command{
- Use: "inspect",
- Short: "inspect a full installation",
- Long: `
- see the inspect for an install
- `,
+ Use: "inspect --deps [flags] [...]",
+ Short: "Inspect package dependencies",
+ Long: `The inspect subcommand provides an entry point for displaying
+information that can be gathered by examining the configuration file, the
+associated package database, and the library. The current focus is on
+inspecting package dependencies (triggered by passing --deps).
+
+Note: If the configuration file has 'Suggests: true', that does not affect
+the set of dependencies listed for any particular package. Instead the set
+of suggested packages is included in the top-level package set.`,
+ Example: ` # Show all dependencies as a tree
+ pkgr --loglevel=fatal inspect --deps --tree
+ # Show dependency tree, restricting roots to the named packages
+ pkgr --loglevel=fatal inspect --deps --tree processx here
+
+ # Output a JSON record where each item maps a package to its direct
+ # and indirect dependencies
+ pkgr --loglevel=fatal inspect --deps
+ # Do the same, but filter to records for the named packages
+ pkgr --loglevel=fatal inspect --deps processx here
+
+ # Output a JSON record where each item maps a package to
+ # the packages that have it as a dependency
+ pkgr --loglevel=fatal inspect --deps --reverse`,
RunE: inspect,
}
@@ -115,8 +134,14 @@ func init() {
inspectCmd.Flags().BoolVar(&showDeps, "deps", false, "show dependency tree")
inspectCmd.Flags().BoolVar(&reverse, "reverse", false, "show reverse dependencies")
inspectCmd.Flags().BoolVar(&tree, "tree", false, "show full recursive dependency tree")
- inspectCmd.Flags().BoolVar(&toJson, "json", false, "output as clean json")
+ inspectCmd.Flags().BoolVar(&toJson, "json", false,
+ // Point the user to --loglevel because it also suppresses logging
+ // upstream of the inspect() call.
+ "suppress non-fatal logging (note: prefer --loglevel=fatal to this flag)")
inspectCmd.Flags().BoolVar(&installedFrom, "installed-from", false, "show package installation source")
+ // Don't advertise this until work is done to improve it.
+ inspectCmd.Flags().MarkHidden("installed-from")
+
RootCmd.AddCommand(inspectCmd)
}
diff --git a/cmd/install.go b/cmd/install.go
index f40cf9a1..b8ad05ab 100644
--- a/cmd/install.go
+++ b/cmd/install.go
@@ -35,10 +35,16 @@ import (
// installCmd represents the R CMD install command
var installCmd = &cobra.Command{
Use: "install",
- Short: "install a package",
- Long: `
- install a package
-`,
+ Short: "Install packages",
+ Long: `Create the library defined by the configuration file.
+
+See for details on
+the configuration file.`,
+ Example: ` # Create or update library defined by pkgr.yml
+ pkgr install
+ # Install new packages and dependencies but don't update packages that already
+ # exist in the library.
+ pkgr install --no-update`,
RunE: rInstall,
}
diff --git a/cmd/load.go b/cmd/load.go
index 83b58d14..d57d5e76 100644
--- a/cmd/load.go
+++ b/cmd/load.go
@@ -21,9 +21,20 @@ import (
// loadCmd represents the load command
var loadCmd = &cobra.Command{
Use: "load",
- Short: "Checks that installed packages can be loaded",
- Long: `Attempts to load user packages specified in pkgr.yml to validate that each package has been installed
-successfully and can be used. Use the --all flag to load all packages in the user-library dependency tree instead of just user-level packages.`,
+ Short: "Check that installed packages can be loaded",
+ Long: `Load packages specified in the configuration file to validate that
+each package has been installed successfully and can be used.
+
+**Execution environment**. This subcommand runs R with the same settings
+that R would use if you invoked 'R' from the current working directory. It
+relies on that environment being configured to find packages in the library
+path specified in the configuration file (via 'Library' or 'Lockfile:
+Type'). Pass the --json argument to confirm that the package is being
+loaded from the expected library.`,
+ Example: ` # Load packages listed in config file
+ pkgr load --json
+ # Load the above packages and all their dependencies
+ pkgr load --json --all`,
Run: func(cmd *cobra.Command, args []string) {
all := viper.GetBool("all")
json := viper.GetBool("json")
@@ -52,9 +63,9 @@ successfully and can be used. Use the --all flag to load all packages in the use
func init() {
RootCmd.AddCommand(loadCmd)
- loadCmd.Flags().Bool("all", false, "load user packages as well as their dependencies")
+ loadCmd.Flags().Bool("all", false, "load all packages in dependency tree")
viper.BindPFlag("all", loadCmd.LocalFlags().Lookup("all")) //There doesn't seem to be a way to bind local flags.
- loadCmd.Flags().Bool("json", false, "output a JSON object of package info at the end")
+ loadCmd.Flags().Bool("json", false, "output results as a JSON object")
viper.BindPFlag("json", loadCmd.LocalFlags().Lookup("json")) //There doesn't seem to be a way to bind local flags.
// loadCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
diff --git a/cmd/plan.go b/cmd/plan.go
index 45b7fd66..83490c77 100644
--- a/cmd/plan.go
+++ b/cmd/plan.go
@@ -47,10 +47,14 @@ import (
// planCmd shows the install plan
var planCmd = &cobra.Command{
Use: "plan",
- Short: "plan a full installation",
- Long: `
- see the plan for an install
- `,
+ Short: "Display plan for installation",
+ Long: `Preview an installation with the current configuration. This subcommand
+is commonly invoked before running 'pkgr install' to confirm that the
+configuration is behaving as intended.
+
+The output includes details about which repositories particular packages would
+be retrieved from, the library that packages would be installed into, and which
+packages would be installed or updated.`,
RunE: plan,
}
diff --git a/cmd/remove.go b/cmd/remove.go
index ed57088a..c8c25c86 100644
--- a/cmd/remove.go
+++ b/cmd/remove.go
@@ -26,11 +26,10 @@ import (
// installCmd represents the R CMD install command
var removeCmd = &cobra.Command{
- Use: "remove [package name1] [package name2] [package name3] ...",
- Short: "remove one or more packages",
- Long: `
- remove package/s from the configuration file
-`,
+ Use: "remove [flags] [...]",
+ Short: "Remove packages from the configuration file",
+ Long: `Remove the specified packages from the 'Packages' section of the
+configuration file.`,
RunE: rRemove,
}
diff --git a/cmd/root.go b/cmd/root.go
index dbbe387d..d28905df 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -38,7 +38,7 @@ var update bool
// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "pkgr",
- Short: "package manager",
+ Short: "A package manager for R",
Version: VERSION,
}
@@ -67,6 +67,7 @@ func rootInit() {
// this is added to maintain legacy compatibility in case people use this flag
RootCmd.PersistentFlags().BoolVar(&update, "update", false, "whether to update installed packages")
+ RootCmd.PersistentFlags().MarkHidden("update")
// this replaces the update
RootCmd.PersistentFlags().Bool("no-update", false, "don't update installed packages")
@@ -86,6 +87,7 @@ func rootInit() {
RootCmd.PersistentFlags().Bool("preview", false, "preview action, but don't actually run command")
_ = viper.BindPFlag("preview", RootCmd.PersistentFlags().Lookup("preview"))
+ RootCmd.PersistentFlags().MarkHidden("preview")
RootCmd.PersistentFlags().Bool("debug", false, "use debug mode")
_ = viper.BindPFlag("debug", RootCmd.PersistentFlags().Lookup("debug"))
@@ -96,13 +98,13 @@ func rootInit() {
RootCmd.PersistentFlags().String("library", "", "library to install packages")
_ = viper.BindPFlag("library", RootCmd.PersistentFlags().Lookup("library"))
- RootCmd.PersistentFlags().Bool("no-rollback", cfg.NoRollback, "Disable rollback")
+ RootCmd.PersistentFlags().Bool("no-rollback", cfg.NoRollback, "disable rollback")
_ = viper.BindPFlag("norollback", RootCmd.PersistentFlags().Lookup("no-rollback"))
RootCmd.PersistentFlags().Bool("no-secure", cfg.NoSecure, "disable TLS certificate verification")
_ = viper.BindPFlag("nosecure", RootCmd.PersistentFlags().Lookup("no-secure"))
- RootCmd.PersistentFlags().Bool("strict", cfg.Strict, "Enable strict mode")
+ RootCmd.PersistentFlags().Bool("strict", cfg.Strict, "enable strict mode")
_ = viper.BindPFlag("strict", RootCmd.PersistentFlags().Lookup("strict"))
}
diff --git a/cmd/run.go b/cmd/run.go
index 3e1f3db0..af34d99b 100644
--- a/cmd/run.go
+++ b/cmd/run.go
@@ -25,11 +25,29 @@ var pkg string
// checkCmd represents the R CMD check command
var runCmd = &cobra.Command{
- Use: "run R",
- Short: "Run R with the configuration settings used with other R commands",
- Long: `
- allows for interactive use and debugging based on the configuration specified by pkgr
- `,
+ Use: "run",
+ Short: "Launch R session with config settings",
+ Long: `Start an interactive R session based on the settings defined in the
+configuration file.
+
+ * Use the R executable defined by the 'RPath' value, if any.
+
+ * Set the library paths so that packages come from only the
+ configuration's library and the library bundled with the R
+ installation.
+
+ * If the --pkg option is passed, set the environment variables defined in
+ the package's 'Customizations' entry.`,
+ Example: ` # Launch an R session, setting values based on pkgr.yml
+ pkgr run
+ # Also setting environment variables specified for dplyr:
+ #
+ # Customizations:
+ # Packages:
+ # - dplyr:
+ # Env:
+ # [...]
+ pkgr run --pkg=dplyr`,
RunE: rRun,
}
diff --git a/docs/commands/pkgr.md b/docs/commands/pkgr.md
index d82f1d3e..8afbe658 100644
--- a/docs/commands/pkgr.md
+++ b/docs/commands/pkgr.md
@@ -1,6 +1,6 @@
## pkgr
-package manager
+A package manager for R
### Options
@@ -11,24 +11,22 @@ package manager
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
-v, --version print the version
```
### SEE ALSO
-* [pkgr add](pkgr_add.md) - add one or more packages
-* [pkgr clean](pkgr_clean.md) - clean up cached information
-* [pkgr inspect](pkgr_inspect.md) - inspect a full installation
-* [pkgr install](pkgr_install.md) - install a package
-* [pkgr load](pkgr_load.md) - Checks that installed packages can be loaded
-* [pkgr plan](pkgr_plan.md) - plan a full installation
-* [pkgr remove](pkgr_remove.md) - remove one or more packages
-* [pkgr run](pkgr_run.md) - Run R with the configuration settings used with other R commands
+* [pkgr add](pkgr_add.md) - Add packages to the configuration file
+* [pkgr clean](pkgr_clean.md) - Clean cached information
+* [pkgr inspect](pkgr_inspect.md) - Inspect package dependencies
+* [pkgr install](pkgr_install.md) - Install packages
+* [pkgr load](pkgr_load.md) - Check that installed packages can be loaded
+* [pkgr plan](pkgr_plan.md) - Display plan for installation
+* [pkgr remove](pkgr_remove.md) - Remove packages from the configuration file
+* [pkgr run](pkgr_run.md) - Launch R session with config settings
diff --git a/docs/commands/pkgr_add.md b/docs/commands/pkgr_add.md
index 83b1905b..3ccba0f0 100644
--- a/docs/commands/pkgr_add.md
+++ b/docs/commands/pkgr_add.md
@@ -1,22 +1,31 @@
## pkgr add
-add one or more packages
+Add packages to the configuration file
### Synopsis
+Add the specified packages to the 'Packages' section of the
+configuration file.
- add package/s to the configuration file and optionally install
+```
+pkgr add [flags] [...]
+```
+### Examples
```
-pkgr add [package name1] [package name2] [package name3] ... [flags]
+ # Add mrgsolve and bbr to list of packages
+ pkgr add mrgsolve bbr
+ # Add rlang and then do installation
+ # (same result as following up with 'pkgr install' call)
+ pkgr add --install rlang
```
### Options
```
-h, --help help for add
- --install install package/s after adding
+ --install run install after updating config
```
### Options inherited from parent commands
@@ -27,16 +36,14 @@ pkgr add [package name1] [package name2] [package name3] ... [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr](pkgr.md) - package manager
+* [pkgr](pkgr.md) - A package manager for R
diff --git a/docs/commands/pkgr_clean.md b/docs/commands/pkgr_clean.md
index 6726caac..a2871780 100644
--- a/docs/commands/pkgr_clean.md
+++ b/docs/commands/pkgr_clean.md
@@ -1,10 +1,22 @@
## pkgr clean
-clean up cached information
+Clean cached information
### Synopsis
-clean up cached source files and binaries, as well as the saved package database.
+This subcommand is an entry point for cleaning two categories of cached
+data:
+
+ * source and binary tarballs
+
+ Use the 'cache' subcommand to remove these.
+
+ * package databases with information about the packages available from
+ repositories
+
+ Use the 'pkgdbs' subcommand to remove these.
+
+To remove cached data for both categories, pass the --all flag.
```
pkgr clean [flags]
@@ -25,18 +37,16 @@ pkgr clean [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr](pkgr.md) - package manager
-* [pkgr clean cache](pkgr_clean_cache.md) - Subcommand to clean cached source and binary files.
-* [pkgr clean pkgdbs](pkgr_clean_pkgdbs.md) - Subcommand to clean cached pkgdbs
+* [pkgr](pkgr.md) - A package manager for R
+* [pkgr clean cache](pkgr_clean_cache.md) - Clean cached package tarballs
+* [pkgr clean pkgdbs](pkgr_clean_pkgdbs.md) - Clean cached package databases
diff --git a/docs/commands/pkgr_clean_cache.md b/docs/commands/pkgr_clean_cache.md
index 4e22dbef..e751d051 100644
--- a/docs/commands/pkgr_clean_cache.md
+++ b/docs/commands/pkgr_clean_cache.md
@@ -1,28 +1,38 @@
## pkgr clean cache
-Subcommand to clean cached source and binary files.
+Clean cached package tarballs
### Synopsis
-This command is a subcommand of the "clean" command.
+Delete cached tarballs for source and binary packages. Both source and
+binary files are deleted if neither the --src-only or --binaries-only flags
+is specified.
- Using this command deletes cached source and binary files. Use the
- --src and --binary options to specify which repos to clean each
- file type from.
-
-
+By default, files for all repositories are deleted unless specific
+repositories are specified via the --repos option. Note that the value must
+match the directory name in the cache, including the unique ID that is
+appended to the repository name.
```
pkgr clean cache [flags]
```
+### Examples
+
+```
+ # Clean binary files for all repos
+ pkgr clean cache --binaries-only
+ # Clean binaries files for MPN-889df4238bae repo
+ pkgr clean cache --repos=MPN-889df4238bae --binaries-only
+```
+
### Options
```
- --binaries-only Clean only binary files from the cache
+ --binaries-only clean only binary files from the cache
-h, --help help for cache
- --repos string Comma separated list of repositories to be cleaned. Defaults to all. (default "ALL")
- --src-only Clean only src files from the cache
+ --repos string comma-separated list of repositories to be cleaned. Defaults to all. (default "ALL")
+ --src-only clean only source files from the cache
```
### Options inherited from parent commands
@@ -33,16 +43,14 @@ pkgr clean cache [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr clean](pkgr_clean.md) - clean up cached information
+* [pkgr clean](pkgr_clean.md) - Clean cached information
diff --git a/docs/commands/pkgr_clean_pkgdbs.md b/docs/commands/pkgr_clean_pkgdbs.md
index 98fb80c5..5114c4f1 100644
--- a/docs/commands/pkgr_clean_pkgdbs.md
+++ b/docs/commands/pkgr_clean_pkgdbs.md
@@ -1,23 +1,30 @@
## pkgr clean pkgdbs
-Subcommand to clean cached pkgdbs
+Clean cached package databases
### Synopsis
-This command parses the currently-cached pkgdbs and removes all
- of them by default, or specific ones if desired. Identify specific repos using the "repos" argument, i.e.
- pkgr clean pkgdbs --repos="CRAN,r_validated"
- Repo names should match names in the pkgr.yml file.
+Delete cached package databases. By default, remove cached databases for
+every repository listed in the active configuration file. If the --repos option
+is passed, remove only the cached databases for those repositories. Repo names
+should match the names in the configuration file.
```
pkgr clean pkgdbs [flags]
```
+### Examples
+
+```
+ # Clean package databases for CRAN and MPN
+ pkgr clean pkgdbs --repos=CRAN,MPN
+```
+
### Options
```
-h, --help help for pkgdbs
- --repos string Set the repos you wish to clear the pkgdbs for. (default "ALL")
+ --repos string clear databases for these repos (default "ALL")
```
### Options inherited from parent commands
@@ -28,16 +35,14 @@ pkgr clean pkgdbs [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr clean](pkgr_clean.md) - clean up cached information
+* [pkgr clean](pkgr_clean.md) - Clean cached information
diff --git a/docs/commands/pkgr_inspect.md b/docs/commands/pkgr_inspect.md
index 4e67db54..8935d07f 100644
--- a/docs/commands/pkgr_inspect.md
+++ b/docs/commands/pkgr_inspect.md
@@ -1,26 +1,49 @@
## pkgr inspect
-inspect a full installation
+Inspect package dependencies
### Synopsis
+The inspect subcommand provides an entry point for displaying
+information that can be gathered by examining the configuration file, the
+associated package database, and the library. The current focus is on
+inspecting package dependencies (triggered by passing --deps).
- see the inspect for an install
-
+Note: If the configuration file has 'Suggests: true', that does not affect
+the set of dependencies listed for any particular package. Instead the set
+of suggested packages is included in the top-level package set.
```
-pkgr inspect [flags]
+pkgr inspect --deps [flags] [...]
+```
+
+### Examples
+
+```
+ # Show all dependencies as a tree
+ pkgr --loglevel=fatal inspect --deps --tree
+ # Show dependency tree, restricting roots to the named packages
+ pkgr --loglevel=fatal inspect --deps --tree processx here
+
+ # Output a JSON record where each item maps a package to its direct
+ # and indirect dependencies
+ pkgr --loglevel=fatal inspect --deps
+ # Do the same, but filter to records for the named packages
+ pkgr --loglevel=fatal inspect --deps processx here
+
+ # Output a JSON record where each item maps a package to
+ # the packages that have it as a dependency
+ pkgr --loglevel=fatal inspect --deps --reverse
```
### Options
```
- --deps show dependency tree
- -h, --help help for inspect
- --installed-from show package installation source
- --json output as clean json
- --reverse show reverse dependencies
- --tree show full recursive dependency tree
+ --deps show dependency tree
+ -h, --help help for inspect
+ --json suppress non-fatal logging (note: prefer --loglevel=fatal to this flag)
+ --reverse show reverse dependencies
+ --tree show full recursive dependency tree
```
### Options inherited from parent commands
@@ -31,16 +54,14 @@ pkgr inspect [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr](pkgr.md) - package manager
+* [pkgr](pkgr.md) - A package manager for R
diff --git a/docs/commands/pkgr_install.md b/docs/commands/pkgr_install.md
index 6ea3e110..4680dcf6 100644
--- a/docs/commands/pkgr_install.md
+++ b/docs/commands/pkgr_install.md
@@ -1,17 +1,28 @@
## pkgr install
-install a package
+Install packages
### Synopsis
+Create the library defined by the configuration file.
- install a package
-
+See for details on
+the configuration file.
```
pkgr install [flags]
```
+### Examples
+
+```
+ # Create or update library defined by pkgr.yml
+ pkgr install
+ # Install new packages and dependencies but don't update packages that already
+ # exist in the library.
+ pkgr install --no-update
+```
+
### Options
```
@@ -26,16 +37,14 @@ pkgr install [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr](pkgr.md) - package manager
+* [pkgr](pkgr.md) - A package manager for R
diff --git a/docs/commands/pkgr_load.md b/docs/commands/pkgr_load.md
index ff9cc160..7a618d44 100644
--- a/docs/commands/pkgr_load.md
+++ b/docs/commands/pkgr_load.md
@@ -1,22 +1,38 @@
## pkgr load
-Checks that installed packages can be loaded
+Check that installed packages can be loaded
### Synopsis
-Attempts to load user packages specified in pkgr.yml to validate that each package has been installed
-successfully and can be used. Use the --all flag to load all packages in the user-library dependency tree instead of just user-level packages.
+Load packages specified in the configuration file to validate that
+each package has been installed successfully and can be used.
+
+**Execution environment**. This subcommand runs R with the same settings
+that R would use if you invoked 'R' from the current working directory. It
+relies on that environment being configured to find packages in the library
+path specified in the configuration file (via 'Library' or 'Lockfile:
+Type'). Pass the --json argument to confirm that the package is being
+loaded from the expected library.
```
pkgr load [flags]
```
+### Examples
+
+```
+ # Load packages listed in config file
+ pkgr load --json
+ # Load the above packages and all their dependencies
+ pkgr load --json --all
+```
+
### Options
```
- --all load user packages as well as their dependencies
+ --all load all packages in dependency tree
-h, --help help for load
- --json output a JSON object of package info at the end
+ --json output results as a JSON object
```
### Options inherited from parent commands
@@ -27,16 +43,14 @@ pkgr load [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr](pkgr.md) - package manager
+* [pkgr](pkgr.md) - A package manager for R
diff --git a/docs/commands/pkgr_plan.md b/docs/commands/pkgr_plan.md
index 7ee71e11..b825355e 100644
--- a/docs/commands/pkgr_plan.md
+++ b/docs/commands/pkgr_plan.md
@@ -1,12 +1,16 @@
## pkgr plan
-plan a full installation
+Display plan for installation
### Synopsis
+Preview an installation with the current configuration. This subcommand
+is commonly invoked before running 'pkgr install' to confirm that the
+configuration is behaving as intended.
- see the plan for an install
-
+The output includes details about which repositories particular packages would
+be retrieved from, the library that packages would be installed into, and which
+packages would be installed or updated.
```
pkgr plan [flags]
@@ -27,16 +31,14 @@ pkgr plan [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr](pkgr.md) - package manager
+* [pkgr](pkgr.md) - A package manager for R
diff --git a/docs/commands/pkgr_remove.md b/docs/commands/pkgr_remove.md
index 591ec73a..063685a8 100644
--- a/docs/commands/pkgr_remove.md
+++ b/docs/commands/pkgr_remove.md
@@ -1,15 +1,14 @@
## pkgr remove
-remove one or more packages
+Remove packages from the configuration file
### Synopsis
-
- remove package/s from the configuration file
-
+Remove the specified packages from the 'Packages' section of the
+configuration file.
```
-pkgr remove [package name1] [package name2] [package name3] ... [flags]
+pkgr remove [flags] [...]
```
### Options
@@ -26,16 +25,14 @@ pkgr remove [package name1] [package name2] [package name3] ... [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr](pkgr.md) - package manager
+* [pkgr](pkgr.md) - A package manager for R
diff --git a/docs/commands/pkgr_run.md b/docs/commands/pkgr_run.md
index cdd87a4b..ded0b05d 100644
--- a/docs/commands/pkgr_run.md
+++ b/docs/commands/pkgr_run.md
@@ -1,15 +1,38 @@
## pkgr run
-Run R with the configuration settings used with other R commands
+Launch R session with config settings
### Synopsis
+Start an interactive R session based on the settings defined in the
+configuration file.
- allows for interactive use and debugging based on the configuration specified by pkgr
-
+ * Use the R executable defined by the 'RPath' value, if any.
+
+ * Set the library paths so that packages come from only the
+ configuration's library and the library bundled with the R
+ installation.
+
+ * If the --pkg option is passed, set the environment variables defined in
+ the package's 'Customizations' entry.
+
+```
+pkgr run [flags]
+```
+
+### Examples
```
-pkgr run R [flags]
+ # Launch an R session, setting values based on pkgr.yml
+ pkgr run
+ # Also setting environment variables specified for dplyr:
+ #
+ # Customizations:
+ # Packages:
+ # - dplyr:
+ # Env:
+ # [...]
+ pkgr run --pkg=dplyr
```
### Options
@@ -27,16 +50,14 @@ pkgr run R [flags]
--library string library to install packages
--logjson log as json
--loglevel string level for logging
- --no-rollback Disable rollback
+ --no-rollback disable rollback
--no-secure disable TLS certificate verification
--no-update don't update installed packages
- --preview preview action, but don't actually run command
- --strict Enable strict mode
+ --strict enable strict mode
--threads int number of threads to execute with
- --update whether to update installed packages
```
### SEE ALSO
-* [pkgr](pkgr.md) - package manager
+* [pkgr](pkgr.md) - A package manager for R
diff --git a/docs/config.md b/docs/config.md
new file mode 100644
index 00000000..78f16378
--- /dev/null
+++ b/docs/config.md
@@ -0,0 +1,399 @@
+
+## Overview
+
+The package library to be created is defined by a configuration file.
+`pkgr` reads the configuration from `pkgr.yml` in the current working
+directory unless another location is specified via its `--config`
+option.
+
+Here's an example of a minimal configuration:
+
+```yaml {filename="pkgr.yml"}
+Version: 1
+Packages:
+ - here
+Repos:
+ - MPN: https://mpn.metworx.com/snapshots/stable/2024-06-12
+Library: lib
+```
+
+That instructs `pkgr` to install `here` and its dependencies, where to
+popuplate the library (`lib/` under the current working directory),
+and where to get the package and its dependencies from (MPN's
+2024-06-12 snapshot).
+
+Running `pkgr install` from the directory that contains that
+`pkgr.yml` file creates the library with `here` and its dependency
+`rprojroot`:
+
+```
+lib/
+|-- here/
+`-- rprojroot/
+```
+
+### Path handling
+
+Several values in the configuration may be paths (e.g., `Library` and
+`Descriptions`).
+
+ * A `~` in the path is expanded to the home directory.
+
+ * If the path is a relative path, it is interpreted as relative to
+ the *configuration file*. This is typically the same location from
+ which `pkgr` was invoked but may differ if an alternative
+ configuration file was specified with `--config`.
+
+### Expansion of environment variables
+
+If a dollar sign precedes a word (with optional brackets around the
+word), the sequence is replaced by the value of the environment
+variable with that name. If that variable is undefined, it is
+replaced by an empty string.
+
+This is most commonly used to set `Rpath` based on an environment
+variable (e.g., `${R_EXE_4_3}`).
+
+> [!CAUTION]
+> Dollar signs should be avoided in configuration unless they
+> reference an environment variable, as there is no support for
+> escaping the dollar sign to disable the expansion.
+
+## Primary sections
+
+The sections below are the most commonly used.
+
+### Customizations
+
+Specify package-specific or repo-specific customizations.
+
+#### Package customizations
+
+Package-level customization is specified as a list of items under
+`Customizations: Packages`.
+
+ * **Env**: a set of environment variables to set when installing the
+ package. This is most commonly used to set `R_MAKEVARS_USER`.
+
+ ```yaml {filename="Example"}
+ Customizations:
+ Packages:
+ - RCurl:
+ Env:
+ R_MAKEVARS_USER: ~/.R/Makevars-RCurl
+ ```
+
+ * **Repo**: install the package from this repository (must match a
+ key under top-level `Repos` section)
+
+ ```yaml {filename="Example"}
+ Customizations:
+ Packages:
+ - here:
+ Repo: PPM
+ ```
+
+ * **Suggests**: whether to install the suggested dependencies for a
+ package
+
+ ```yaml {filename="Example"}
+ Customizations:
+ Packages:
+ - here:
+ Suggests: true
+ ```
+
+ * **Type**: type of package, "source" or "binary", to install for a
+ package
+
+ Installing a binary package is faster, but the CRAN-like repository
+ must have a binary available for the package, which is often not
+ the case.
+
+ ```yaml {filename="Example"}
+ Customizations:
+ Packages:
+ - here:
+ Type: binary
+ ```
+
+#### Repo customizations
+
+ * **Type**: type of packages, "source" or "binary", to install from
+ the specified repository
+
+ The default type is "source" on Linux and "binary" on macOS and
+ Windows.
+
+ > [!NOTE]
+ > It is common for a repository to be missing binaries available
+ > for your setup (platform, architecture, and version of R). If
+ > binaries are unavailable and you're running macOS or Windows, you
+ > must customize the repository to have type "source" and ensure
+ > your machine has the necessary system requirements to build the
+ > package from source.
+
+ ```yaml {filename="Example"}
+ Customizations:
+ Repos:
+ - MPN:
+ Type: source
+ ```
+
+
+
+### Descriptions
+
+Install the dependencies listed in the specified R package
+[DESCRIPTION][desc] files.
+
+[desc]: https://r-pkgs.org/description.html
+
+This main use case for this is R package development, as it avoids
+duplicating the list of dependencies under the `Packages` section of
+the `pkgr` configuration.
+
+```yaml {filename="Example"}
+Descriptions:
+ - DESCRIPTION
+```
+
+### Library
+
+Directory in which to install packages.
+
+A directory specified via the `--library` command-line option
+overrides the value specified in the configuration.
+
+Either this section or `Lockfile` must be present. `Library` takes
+precedence over `Lockfile` if both are specified.
+
+```yaml {filename="Example"}
+Library: lib
+```
+
+### Lockfile
+
+Use the same library location as
+[renv](https://rstudio.github.io/renv) or
+[packrat](https://github.com/rstudio/packrat).
+
+> [!WARNING]
+> Packrat was superseded by renv. It is in maintenance-only mode.
+
+`pkgr` invokes `renv` to find the library, as its location depends on
+a number of settings. If `renv` has not yet been initialized for a
+project, `pkgr` tries to query the `renv`, if any, available in the
+default library paths. However, the recommended approach is to
+initialize `renv` *before* calling `pkgr install` (e.g., by invoking
+`renv::init(bare = TRUE)`).
+
+Either this section or `Library` must be present. `Library` takes
+precedence over `Lockfile` if both are specified.
+
+```yaml {filename="Example"}
+Lockfile:
+ Type: renv
+```
+
+### Packages
+
+Packages to install. They must be available from at least one of the
+CRAN-like repositories listed under the `Repos` section.
+
+Any of their dependencies are installed automatically. By default,
+suggested dependencies are not included (but see `Suggests` section).
+
+```yaml {filename="Example"}
+Packages:
+ - here
+ - rlang
+```
+
+### Repos
+
+CRAN-like repositories from which to retrieve the packages listed in
+`Packages`.
+
+> [!CAUTION]
+> The order is important. Unless customized in the `Customizations`
+> section, a package is downloaded from the first repository that
+> contains it.
+
+> [!TIP]
+> To create a library with a reproducible set of packages, use
+> CRAN-like repositories that snapshot packages at a particular date,
+> such as [Metrum Package Network][mpn] and
+> [Posit Package Manager][ppm].
+
+[mpn]: https://mpn.metworx.com
+[ppm]: https://packagemanager.posit.co
+
+```yaml {filename="Example"}
+Repos:
+ - MPN: https://mpn.metworx.com/snapshots/stable/2024-06-12
+ - PPM: https://packagemanager.posit.co/cran/2024-06-12
+```
+
+### RPath
+
+Which R executable to use. Defaults to the highest priority R
+executable in `PATH` (i.e. the same R that would launch if you invoked
+`R` from the current shell).
+
+```yaml {filename="Example"}
+Rpath: /opt/R/4.2.3/bin/R
+```
+
+### Suggests
+
+Install the suggested dependencies for all packages listed in
+`Packages`.
+
+To do so only for some packages, use a package-specific customizations
+entry (see `Customizations` section).
+
+```yaml {filename="Example"}
+Suggests: true
+```
+
+### Version
+
+The configuration format version. This should always be `1`.
+
+```yaml {filename="Example"}
+Version: 1
+```
+
+## Other sections
+
+These sections are not as commonly used as the ones above.
+
+### Cache
+
+Store downloaded packages and built binaries in this directory rather
+than the default platform-specific directory (e.g.,
+`$HOME/.cache/pkgr/` on Linux).
+
+```yaml {filename="Example"}
+Cache: cache
+```
+
+### IgnorePackages
+
+Do not install the specified packages even if they are a required
+dependency.
+
+```yaml {filename="Example"}
+IgnorePackages:
+- foo
+```
+
+
+
+
+### Logging
+
+Configure logging behavior.
+
+ * **all**: path for all commands to write log records to
+
+ * **install**: path for `pkgr install` to write log records to
+ instead of the one specified by **all**.
+
+ * **overwrite**: overwrite the above files instead of the default
+ behavior of appending to them
+
+
+
+
+```yaml {filename="Example"}
+Logging:
+ all: pkgr-all.log
+ install: pkgr-install.log
+ overwrite: true
+```
+
+### NoRecommended
+
+By default `pkgr intall` considers [recommended packages][rp] when
+installing and updating a library. If `NoRecommended` is set to
+`true`, recommended packages are ignored unless they are explicitly
+listed under the `Packages` section.
+
+[rp]: https://rstudio.github.io/r-manuals/r-admin/Obtaining-R.html#using-subversion-and-rsync
+
+```yaml {filename="Example"}
+NoRecommended: true
+```
+
+### NoRollback
+
+By default `pkgr install` restores the library to its original state
+if the installation fails. Set `NoRollback` to `true` to disable that
+behavior.
+
+```yaml {filename="Example"}
+NoRollback: true
+```
+
+### NoSecure
+
+Disable the default TLS certificate verification by setting
+`NoSecure: true`.
+
+> [!CAUTION]
+> Disable TLS certificate verification is not recommended. If you
+> need this in a particular case, consider passing the `--no-secure`
+> command-line flag instead.
+
+```yaml {filename="Example"}
+NoSecure: true
+```
+
+### NoUpdate
+
+Disable the default behavior of updating packages that are already
+present in the library.
+
+This can be set for a single call by passing the `--no-update`
+command-line flag instead.
+
+```yaml {filename="Example"}
+NoUpdate: true
+```
+
+### Strict
+
+`pkgr install` creates the library directory if needed. Set `Strict`
+to `true` to make it abort if the library directory does not exist.
+
+This can be set for a single call by passing the `--strict`
+command-line flag instead.
+
+```yaml {filename="Example"}
+Strict: true
+```
+
+### Tarballs
+
+Install packages from the specified source tarball.
+
+```yaml {filename="Example"}
+Tarballs:
+ - packages/R6_2.5.1.tar.gz
+ - packages/glue_1.7.0.tar.gz
+```
+
+### Threads
+
+Number of workers to use for installing packages. The default is to
+use up to eight workers, considering the number of workers on the
+machine and any configured Linux CPU quotas.
+
+A value specified via the `--threads` command-line option overrides
+the value specified in the configuration.
+
+```yaml {filename="Example"}
+Threads: 2
+```
diff --git a/docs/site/.gitignore b/docs/site/.gitignore
new file mode 100644
index 00000000..d6a86d88
--- /dev/null
+++ b/docs/site/.gitignore
@@ -0,0 +1,7 @@
+/.hugo_build.lock
+/content/**/*.md
+!/content/docs/_index.md
+/local.mk
+/public/
+/resources/
+/static/windows.png
diff --git a/docs/site/Makefile b/docs/site/Makefile
new file mode 100644
index 00000000..4faf6155
--- /dev/null
+++ b/docs/site/Makefile
@@ -0,0 +1,60 @@
+-include local.mk
+
+HTTP_PORT ?= 1313
+
+version := $(shell git describe --tags --always HEAD)
+export HUGO_PARAMS_PKGRVERSION ?= $(version)
+
+.PHONY: help
+help:
+ $(info Primary targets:)
+ $(info * build: build site under public/)
+ $(info * serve: build and serve the site locally with 'hugo server')
+ @:
+
+.PHONY: build
+build: prep
+ hugo --gc --minify
+
+.PHONY: serve
+serve: prep
+ hugo server -p '$(HTTP_PORT)'
+
+copied_files = content/_index.md
+copied_files += content/docs/config.md
+copied_files += content/news.md
+copied_files += static/windows.png
+
+.PHONY: prep
+prep: commands
+prep: $(copied_files)
+ rm -rf public resources
+
+command_dir = content/docs/commands
+
+.PHONY: commands
+commands:
+ rm -rf '$(command_dir)'
+ ./scripts/ingest-command-docs '$(command_dir)'
+
+content/_index.md: ../../README.md
+ sed 's|docs/images/windows_tarball_picture\.png|windows.png|' '$<' >'$@'
+
+content/docs/config.md: ../config.md
+ printf -- '---\ntitle: "Configuration"\nweight: 10\n---\n\n' >'$@'
+ cat '$<' >>'$@'
+
+content/news.md: ./scripts/add-gh-links
+content/news.md: ../../NEWS.md
+ printf -- '---\ntitle: "News"\n---\n\n' >'$@'
+ sed 's/^# pkgr/##/' '$<' | \
+ ./scripts/add-gh-links https://github.com/metrumresearchgroup/pkgr \
+ >>'$@'
+
+static/windows.png: ../images/windows_tarball_picture.png
+ cp '$<' '$@'
+
+.PHONY: clean
+clean:
+ rm -rf public resources $(command_dir)
+ rm -f $(copied_files)
diff --git a/docs/site/README.md b/docs/site/README.md
new file mode 100644
index 00000000..a7a210ec
--- /dev/null
+++ b/docs/site/README.md
@@ -0,0 +1,57 @@
+This directory contains files for building the GitHub Pages site with
+[Hugo][h] and the [Hextra][x] theme. The site is published on release
+via GitHub Actions ([workflow](/.github/workflows/site.yaml)).
+
+[h]: https://gohugo.io/
+[x]: https://imfing.github.io/hextra/
+
+## Previewing the site
+
+ * Install Hugo ()
+
+ * Run `make serve` to prepare the necessary files and launch
+ [Hugo's web server](https://gohugo.io/commands/hugo_server/)
+
+## Components
+
+ * [hugo.yaml](./hugo.yaml): site configuration
+
+ * [Hugo docs](https://gohugo.io/getting-started/configuration/)
+
+ * [Hextra docs](https://imfing.github.io/hextra/docs/guide/configuration/)
+
+ * [go.mod](./go.mod): defines Hextra as a Hugo module
+
+ * [Hugo docs](https://gohugo.io/hugo-modules/)
+
+ * [Hextra docs](https://imfing.github.io/hextra/docs/getting-started/#setup-hextra-as-hugo-module)
+
+ * [content/][c]: Markdown content of the site
+
+ Most of the content is pulled from other spots in the repository by
+ the [Makefile][m], including [NEWS.md](/NEWS.md) and the
+ command-line Markdown documentation at
+ [docs/commands/](/docs/commands).
+
+ * [Hugo docs](https://gohugo.io/content-management/)
+
+ * [layouts/](./layouts): templates for rendering the site pages
+
+ Most of the layouts are defined by the Hextra theme. The files
+ here override particular templates. They are derived from the
+ corresponding Hextra template. The header of each template
+ documents what was changed.
+
+ * [Hugo docs](https://gohugo.io/templates/)
+
+ * [scripts/](./scripts): custom scripts used by the [Makefile][m] to
+ process the Markdown content before writing it to [content/][c]
+
+ This is responsible for things like adding PR links in the NEWS
+ page rendered on the site.
+
+ * [static/](./static): this directory contains the logos and any
+ other images used on the site
+
+[c]: ./content
+[m]: ./Makefile
diff --git a/docs/site/content/docs/_index.md b/docs/site/content/docs/_index.md
new file mode 100644
index 00000000..5d180eec
--- /dev/null
+++ b/docs/site/content/docs/_index.md
@@ -0,0 +1,25 @@
+---
+title: Documentation
+toc: false
+---
+
+`pkgr` is a command-line interface for managing R packages. This
+documentation describes that [interface][commands] and the
+[configuration file][config] that controls its operation.
+
+{{< cards >}}
+ {{< card link="config" title="Configuration" icon="document-text"
+ subtitle="Define the package library to create" >}}
+{{< /cards >}}
+
+{{< cards >}}
+ {{< card link="commands/plan" title="Key subcommand: plan" icon="terminal"
+ subtitle="Preview what would be installed or updated" >}}
+ {{< card link="commands/install" title="Key subcommand: install" icon="terminal"
+ subtitle="Create or update the library" >}}
+{{< /cards >}}
+
+[commands]: {{< relref "/docs/commands" >}}
+[config]: {{< relref "/docs/config" >}}
+[install]: {{< relref "/docs/commands/install" >}}
+[plan]: {{< relref "/docs/commands/plan" >}}
diff --git a/docs/site/go.mod b/docs/site/go.mod
new file mode 100644
index 00000000..40fd050f
--- /dev/null
+++ b/docs/site/go.mod
@@ -0,0 +1,5 @@
+module github.com/metrumresearchgroup/pkgr/docs/site
+
+go 1.21.4
+
+require github.com/imfing/hextra v0.8.2 // indirect
diff --git a/docs/site/go.sum b/docs/site/go.sum
new file mode 100644
index 00000000..ed34ce09
--- /dev/null
+++ b/docs/site/go.sum
@@ -0,0 +1,4 @@
+github.com/imfing/hextra v0.8.1 h1:HPeuyBTxaG7o2PHT9XRgFTVbCVGhJbZ0t7PjApA32F8=
+github.com/imfing/hextra v0.8.1/go.mod h1:cEfel3lU/bSx7lTE/+uuR4GJaphyOyiwNR3PTqFTXpI=
+github.com/imfing/hextra v0.8.2 h1:/IykSIAywgKfhKUBgAW+dCCjrJWJNny4jr9qvdXfch0=
+github.com/imfing/hextra v0.8.2/go.mod h1:cEfel3lU/bSx7lTE/+uuR4GJaphyOyiwNR3PTqFTXpI=
diff --git a/docs/site/hugo.yaml b/docs/site/hugo.yaml
new file mode 100644
index 00000000..a042ee4a
--- /dev/null
+++ b/docs/site/hugo.yaml
@@ -0,0 +1,67 @@
+title: pkgr
+baseURL: https://metrumresearchgroup.github.io/pkgr/
+languageCode: en-us
+markup:
+ highlight:
+ noClasses: false
+ goldmark:
+ extensions:
+ typographer:
+ # Prevent --option in command pages from being rendered with an en-dash.
+ disable: true
+ parser:
+ attribute:
+ block: true
+menu:
+ main:
+ - name: Docs
+ pageRef: /docs
+ weight: 10
+ - name: News
+ pageRef: /news
+ weight: 20
+ - name: Search
+ weight: 30
+ params:
+ type: search
+ - name: GitHub
+ weight: 40
+ url: https://github.com/metrumresearchgroup/pkgr
+ params:
+ icon: github
+ sidebar:
+ - identifier: wikimanual
+ name: "User manual (pkgr wiki) ↗"
+ url: "https://github.com/metrumresearchgroup/pkgr/wiki/user_manual"
+ weight: 100
+ - identifier: repos
+ name: Snapshot repos
+ params:
+ type: separator
+ weight: 110
+ - identifier: mpn
+ name: "Metrum Package Network ↗"
+ url: "https://mpn.metworx.com"
+ weight: 120
+ - identifier: ppm
+ name: "Posit Package Manager ↗"
+ url: "https://packagemanager.posit.co"
+ weight: 130
+
+disableKinds:
+ - taxonomy
+ - term
+
+module:
+ imports:
+ - path: github.com/imfing/hextra
+params:
+ navbar:
+ displayTitle: false
+ displayLogo: true
+ logo:
+ path: logo.png
+ width: 45
+ theme:
+ default: system
+ displayToggle: false
diff --git a/docs/site/layouts/_default/_markup/render-blockquote.html b/docs/site/layouts/_default/_markup/render-blockquote.html
new file mode 100644
index 00000000..5204b6a9
--- /dev/null
+++ b/docs/site/layouts/_default/_markup/render-blockquote.html
@@ -0,0 +1,47 @@
+{{/*
+ This is combines the types from the example at
+ with the
+ classes from Hextra's layouts/shortcodes/callout.html
+ (blob: 6b56bcb2fff52b58af2a34da0bd8e5784108bd2b).
+*/}}
+{{ if eq .Type "alert" }}
+ {{ $emojis := dict
+ "caution" ":exclamation:"
+ "important" ":information_source:"
+ "note" ":information_source:"
+ "tip" ":bulb:"
+ "warning" ":information_source:"
+ }}
+
+ {{ $orange := "hx-border-orange-100 hx-bg-orange-50 hx-text-orange-800 dark:hx-border-orange-400/30 dark:hx-bg-orange-400/20 dark:hx-text-orange-300" }}
+ {{ $blue := "hx-border-blue-200 hx-bg-blue-100 hx-text-blue-900 dark:hx-border-blue-200/30 dark:hx-bg-blue-900/30 dark:hx-text-blue-200" }}
+ {{ $yellow := "hx-border-yellow-100 hx-bg-yellow-50 hx-text-yellow-900 dark:hx-border-yellow-200/30 dark:hx-bg-yellow-700/30 dark:hx-text-yellow-200" }}
+ {{ $red := "hx-border-red-200 hx-bg-red-100 hx-text-red-900 dark:hx-border-red-200/30 dark:hx-bg-red-900/30 dark:hx-text-red-200" }}
+
+ {{ $classes := dict
+ "caution" $red
+ "important" $orange
+ "note" $blue
+ "tip" $blue
+ "warning" $yellow
+ }}
+
+ {{ $class := (index $classes .AlertType) }}
+
+{{ end }}
diff --git a/docs/site/layouts/partials/favicons.html b/docs/site/layouts/partials/favicons.html
new file mode 100644
index 00000000..2d659c3b
--- /dev/null
+++ b/docs/site/layouts/partials/favicons.html
@@ -0,0 +1,13 @@
+{{/*
+ This is modified from Hextra's layouts/partials/favicons.html
+ (blob: 66a80188e72c094884b37ff9720d669a6e03824f)
+
+ Changes:
+
+ * remove links to favicon.svg and favicon-dark.svg
+*/}}
+
+
+
+
+
diff --git a/docs/site/layouts/partials/footer.html b/docs/site/layouts/partials/footer.html
new file mode 100644
index 00000000..787c46fe
--- /dev/null
+++ b/docs/site/layouts/partials/footer.html
@@ -0,0 +1,35 @@
+{{/*
+ This is modified from Hextra's layouts/partials/footer.html
+ (blob: 61cbb1133d633b0389f9d6ce70cd99b8568a7bad)
+
+ Changes:
+
+ * remove support for toggling (handled in navbar instead)
+
+ * decrease height of footer
+
+ * use custom credit line that 1) credits Hugo in addition to
+ Hextra and 2) is right aligned
+*/}}
+
+{{- $footerWidth := "hx-max-w-screen-xl" -}}
+{{- with .Site.Params.footer.width -}}
+ {{ if eq . "wide" -}}
+ {{ $footerWidth = "hx-max-w-[90rem]" -}}
+ {{ else if eq . "full" -}}
+ {{ $footerWidth = "max-w-full" -}}
+ {{ end -}}
+{{- end -}}
+
+
diff --git a/docs/site/layouts/partials/navbar.html b/docs/site/layouts/partials/navbar.html
new file mode 100644
index 00000000..ed4574da
--- /dev/null
+++ b/docs/site/layouts/partials/navbar.html
@@ -0,0 +1,89 @@
+{{/*
+ This is modified from Hextra's layouts/partials/navbar.html
+ (blob: 04adb27e4f170601cc82f9d8ecf30baf50ffbe5a)
+
+ Changes:
+
+ * add pkgr version
+
+ * don't blur
+
+ * add dark/light theme toggle (but don't guard it with
+ site.Params.theme.displayToggle so that Hexta's sidebar can be
+ used without any changes)
+*/}}
+
+{{- $logoPath := .Site.Params.navbar.logo.path | default "images/logo.svg" -}}
+{{- $logoLink := .Site.Params.navbar.logo.link | default .Site.Home.RelPermalink -}}
+{{- $logoWidth := .Site.Params.navbar.logo.width | default "20" -}}
+{{- $logoHeight := .Site.Params.navbar.logo.height | default "20" -}}
+{{- $logoDarkPath := .Site.Params.navbar.logo.dark | default $logoPath -}}
+
+{{- $pkgrVersion := .Site.Params.pkgrversion | default "" -}}
+
+{{- $navWidth := "hx-max-w-[90rem]" -}}
+{{- with .Site.Params.navbar.width -}}
+ {{ if eq . "normal" -}}
+ {{ $navWidth = "hx-max-w-screen-xl" -}}
+ {{ else if eq . "full" -}}
+ {{ $navWidth = "max-w-full" -}}
+ {{ end -}}
+{{- end -}}
+
+
+
+
+
+
diff --git a/docs/site/layouts/partials/theme-toggle.html b/docs/site/layouts/partials/theme-toggle.html
new file mode 100644
index 00000000..2da946d4
--- /dev/null
+++ b/docs/site/layouts/partials/theme-toggle.html
@@ -0,0 +1,29 @@
+{{/*
+ This is modified from Hextra's layouts/partials/favicons.html
+ (blob: 6a939b56760c8f2b7ca442463ee41b47a65b6091)
+
+ Changes:
+
+ * increase size of icons
+*/}}
+{{- $hideLabel := .hideLabel | default false -}}
+
+{{- $changeTheme := (T "changeTheme") | default "Change theme" -}}
+{{- $light := (T "light") | default "Light" -}}
+{{- $dark := (T "dark") | default "Dark" -}}
+
+
+
diff --git a/docs/site/scripts/add-gh-links b/docs/site/scripts/add-gh-links
new file mode 100755
index 00000000..e4420dd0
--- /dev/null
+++ b/docs/site/scripts/add-gh-links
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+# Copyright 2024 Metrum Research Group
+# SPDX-License-Identifier: MIT
+"""usage: {}
+
+Read markdown content from stdin and write it to stdout replacing
+
+ * #NNN with [#NNN](/issue/NNN)
+
+ * commit IDs with links to [](/commit/)
+
+ If something looks like a commit but isn't a known commit in the
+ current repository, it's left as is.
+
+This script must be executed from a Git repository.
+"""
+
+import fileinput
+import re
+import subprocess as sp
+import sys
+
+link_re = re.compile(r"\B#([1-9][0-9]*)\b")
+
+
+def link_issues(url, string):
+ return link_re.sub(rf"[#\1]({url}/issues/\1)", string)
+
+
+commit_re = re.compile(r"\b([0-9a-f]{7,})\b")
+
+
+# Note: This runs a git process per commit candidate. If this were to
+# be used in a case where there is a large amount of input and
+# performance matters, consider rewriting to use cat-file and a single
+# process.
+def replace_commit(matchobj):
+ fullmatch = matchobj.group(0)
+ commit = matchobj.group(1)
+
+ try:
+ p = sp.run(
+ ["git", "rev-parse", "--verify", "--quiet", commit + "^{commit}"],
+ check=True,
+ capture_output=True,
+ encoding="utf-8",
+ )
+ except sp.CalledProcessError as err:
+ if err.returncode == 1:
+ # This doesn't resolve to a known commit.
+ return fullmatch
+ raise
+
+ resolved = p.stdout.rstrip("\n")
+ return fullmatch.replace(commit, f"[{commit}]({url}/commit/{resolved})")
+
+
+def link_commits(url, string):
+ return commit_re.sub(replace_commit, string)
+
+
+if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ sys.stderr.write(__doc__.format(sys.argv[0]))
+ sys.exit(1)
+
+ url = sys.argv[1]
+ if url.endswith("/"):
+ url = url[:-1]
+
+ for line in fileinput.input("-"):
+ line = link_issues(url, line)
+ line = link_commits(url, line)
+ sys.stdout.write(line)
diff --git a/docs/site/scripts/format-command-flags b/docs/site/scripts/format-command-flags
new file mode 100755
index 00000000..e9c2a413
--- /dev/null
+++ b/docs/site/scripts/format-command-flags
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+"""
+Read Cobra command markdown on stdin and replace option code blocks
+with a list of options.
+
+For example, convert
+
+ ```
+ --json json tree of output, if possible
+ -v, --verbose verbose output
+ ```
+
+to
+
+ * `--json`: json tree of output, if possible
+
+ * `-v, --verbose`: verbose output
+
+"""
+
+import fileinput
+import sys
+
+
+def format_option(line):
+ line = line.strip()
+ if not line:
+ return ""
+ if line == "```":
+ return "\n"
+
+ try:
+ # Note: This relies on the "-o, --option value" part 1) _not_
+ # containing two spaces and 2) being separated from the
+ # description by at least two spaces.
+ opts, desc = line.split(" ", maxsplit=1)
+ except ValueError:
+ raise ValueError(f"option line in unexpected format: {line}") from None
+
+ return f" * `{opts}`: {desc}\n\n"
+
+
+if __name__ == "__main__":
+ in_options = False
+ for line in fileinput.input("-"):
+ if line.startswith("#"):
+ in_options = line.startswith("### Options")
+ sys.stdout.write(line)
+ continue
+
+ if in_options:
+ line = format_option(line)
+ sys.stdout.write(line)
diff --git a/docs/site/scripts/ingest-command-docs b/docs/site/scripts/ingest-command-docs
new file mode 100755
index 00000000..0881ad2f
--- /dev/null
+++ b/docs/site/scripts/ingest-command-docs
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+# Copy generated command docs from contents/commands/ with the
+# following modifications:
+#
+# * set title metadata to name of subcommand
+#
+# * promote each heading (e.g., H2 becomes H1)
+#
+# * adjust the link to the other markdown files to work in the Hugo
+# context
+#
+# * tweak the headings of top-level command page to make it a more
+# suitable landing page for /commands
+#
+# * replace "option" with "flag" in title.
+#
+# Although "option" is arguably the better term in general, 1)
+# cobra puts these under "flags" in its command-line help output
+# and 2) cobra adds a "[flag]" value to the usage, so staying with
+# "flag" is better for consistency.
+#
+# * put inherited flags as subhead of under flags heading
+#
+# * extract option lines from code block and reformat as bullets
+
+set -eu
+
+test -x scripts/format-command-flags || {
+ printf >&2 'script must be executed from docs/site/ directory\n'
+ exit 1
+}
+
+outdir=content/docs/commands
+mkdir -p "$outdir"
+for f in ../commands/*.md
+do
+ if test "$f" = ../commands/pkgr.md
+ then
+ dest=$outdir/_index.md
+ title=Commands
+ seename=Subcommands
+ else
+ base=$(basename "$f")
+ cmd=${base%.md}
+ title=$(printf '%s\n' "$cmd" | sed 's/pkgr_//' | sed 's/_/ /g')
+ dest=$outdir/${base#pkgr_}
+ seename='See also'
+ fi
+ printf -- '---\ntitle: "%s"\ntype: "command"\n---\n\n' "$title" >"$dest"
+ ./scripts/format-command-flags <"$f" | \
+ sed 's/^##/#/' | \
+ sed -E 's|\[pkgr\]\(pkgr\.md\).*|[pkgr]({{< relref "/docs/commands/" >}}) - top-level entry point |' | \
+ sed 's|(pkgr_\(.*\)\.md)|({{< relref "/docs/commands/\1" >}})|' | \
+ sed 's/# Options inherited from parent commands/## Inherited/' | \
+ sed 's/# Options/# Flags/' | \
+ sed "s/# SEE ALSO/# $seename/" >>"$dest"
+done
diff --git a/docs/site/static/apple-touch-icon-120x120.png b/docs/site/static/apple-touch-icon-120x120.png
new file mode 100644
index 00000000..1e9fe20c
Binary files /dev/null and b/docs/site/static/apple-touch-icon-120x120.png differ
diff --git a/docs/site/static/apple-touch-icon-152x152.png b/docs/site/static/apple-touch-icon-152x152.png
new file mode 100644
index 00000000..c4d2527d
Binary files /dev/null and b/docs/site/static/apple-touch-icon-152x152.png differ
diff --git a/docs/site/static/apple-touch-icon-180x180.png b/docs/site/static/apple-touch-icon-180x180.png
new file mode 100644
index 00000000..1063ce61
Binary files /dev/null and b/docs/site/static/apple-touch-icon-180x180.png differ
diff --git a/docs/site/static/apple-touch-icon-60x60.png b/docs/site/static/apple-touch-icon-60x60.png
new file mode 100644
index 00000000..2b577822
Binary files /dev/null and b/docs/site/static/apple-touch-icon-60x60.png differ
diff --git a/docs/site/static/apple-touch-icon-76x76.png b/docs/site/static/apple-touch-icon-76x76.png
new file mode 100644
index 00000000..3f55d615
Binary files /dev/null and b/docs/site/static/apple-touch-icon-76x76.png differ
diff --git a/docs/site/static/apple-touch-icon.png b/docs/site/static/apple-touch-icon.png
new file mode 100644
index 00000000..1063ce61
Binary files /dev/null and b/docs/site/static/apple-touch-icon.png differ
diff --git a/docs/site/static/favicon-16x16.png b/docs/site/static/favicon-16x16.png
new file mode 100644
index 00000000..038940a5
Binary files /dev/null and b/docs/site/static/favicon-16x16.png differ
diff --git a/docs/site/static/favicon-32x32.png b/docs/site/static/favicon-32x32.png
new file mode 100644
index 00000000..5e64c7c4
Binary files /dev/null and b/docs/site/static/favicon-32x32.png differ
diff --git a/docs/site/static/favicon.ico b/docs/site/static/favicon.ico
new file mode 100644
index 00000000..bac9784b
Binary files /dev/null and b/docs/site/static/favicon.ico differ
diff --git a/docs/site/static/logo.png b/docs/site/static/logo.png
new file mode 100644
index 00000000..eb7e3b72
Binary files /dev/null and b/docs/site/static/logo.png differ