Compact Package Representations

1 Introduction

pkglite offers a solution for converting R package source code to a compact, text-based representation and restore the source package structure from the representation. There are three specific aims:

  1. To provide a tool for packing and restoring R packages as plain text assets that are easy to store, transfer, and review.
  2. To provide a grammar for specifying the file packing scope that is functional, precise, and extendable.
  3. To provide a standard for exchanging the packed asset that is unambiguous, human-friendly, and machine-readable.

To achieve these goals, we developed a pipe-friendly workflow, the concept of file specifications and file collections, and a format specification for the output file pkglite.txt. These designs allow us to leave a clear and skimmable trace in the code when generating such compact representations, thus improves reproducibility.

2 Example workflow

To demonstrate the basic usage of pkglite, we will show how to pack and unpack one or multiple R packages.

library("pkglite")

2.1 Pack one package

First, locate the input package directory and the output file:

pkg <- system.file("examples/pkg1", package = "pkglite")
txt <- tempfile(fileext = ".txt")

Use the following chain of calls to pack a default set of files in the R package under directory pkg into the file txt:

pkg %>%
  collate(file_default()) %>%
  pack(output = txt, quiet = TRUE)

The collate() function evaluates one or more file specifications to generate a file collection. They fully determine the scope of the files to pack here. For details, check vignette("filespec", package = "pkglite").

Check the first lines of the output file:

txt %>%
  readLines() %>%
  head(11) %>%
  cat(sep = "\n")
# Generated by pkglite: do not edit by hand
# Use pkglite::unpack() to restore the packages

Package: pkg1
File: DESCRIPTION
Format: text
Content:
  Package: pkg1
  Type: Package
  Title: Example Package One
  Version: 0.1.0

Check the number of lines the output file:

txt %>%
  readLines() %>%
  length()
[1] 1081

2.2 Unpack one package

To unpack (restore) the file structures from the text file, use unpack():

out <- file.path(tempdir(), "onepkg")
txt %>% unpack(output = out, quiet = TRUE)

This will create a directory named after the R package under the output directory:

out %>%
  file.path("pkg1") %>%
  list.files()
[1] "DESCRIPTION" "NAMESPACE"   "NEWS.md"     "R"           "README.md"  
[6] "data"        "man"         "vignettes"  

To install the packages after unpacking them, use unpack(..., install = TRUE).

2.3 Pack multiple packages

pack() accepts one or more input directories. Therefore, one can pack multiple R packages (file collections) into one file at once:

pkg1 <- system.file("examples/pkg1", package = "pkglite")
pkg2 <- system.file("examples/pkg2", package = "pkglite")

fc1 <- pkg1 %>% collate(file_default())
fc2 <- pkg2 %>% collate(file_default())

pack(fc1, fc2, output = txt, quiet = TRUE)

Since the two example packages have almost identical content, the number of lines in the text file is doubled here (three header lines excluded):

txt %>%
  readLines() %>%
  length()
[1] 2159

2.4 Unpack multiple packages

Use the same call to unpack (and install) multiple R packages from the text file:

out <- file.path(tempdir(), "twopkgs")
txt %>% unpack(output = out, quiet = TRUE)
out %>%
  file.path("pkg1") %>%
  list.files()
[1] "DESCRIPTION" "NAMESPACE"   "NEWS.md"     "R"           "README.md"  
[6] "data"        "man"         "vignettes"  
out %>%
  file.path("pkg2") %>%
  list.files()
[1] "DESCRIPTION" "NAMESPACE"   "NEWS.md"     "R"           "README.md"  
[6] "data"        "man"         "vignettes"  

The file format specification for pkglite.txt is described in vignette("format", package = "pkglite").

3 Helper functions

Verify if the text file contains only ASCII characters:

txt %>% verify_ascii()
[1] TRUE

Remove lines of file content from the text file:

txt %>% remove_content(c("## New Features", "## Improvements"), quiet = TRUE)
txt %>%
  readLines() %>%
  length()
[1] 2157