---
title: "Getting started with bigbang"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting started with bigbang}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(bigbang)
```

## A complete disposable example

This guide creates a component archive and a metapackage source tree entirely
under `tempdir()`. It does not write to the working directory, install anything,
or contact a repository.

```{r create-component}
root <- tempfile("bigbang-vignette-")
source_root <- file.path(root, "sources")
archive_root <- file.path(root, "archives")
destination <- file.path(root, "generated")
dir.create(file.path(source_root, "toycomponent", "R"), recursive = TRUE)
dir.create(archive_root)
dir.create(destination)

writeLines(c(
  "Package: toycomponent",
  "Type: Package",
  "Title: Toy Component",
  "Version: 0.1.0",
  "Authors@R: person('Test', 'Author', email='test@example.org', role=c('aut','cre'))",
  "Description: A disposable component used by the bigbang vignette.",
  "License: MIT"
), file.path(source_root, "toycomponent", "DESCRIPTION"), useBytes = TRUE)
writeLines(
  "export(toy_value)",
  file.path(source_root, "toycomponent", "NAMESPACE"),
  useBytes = TRUE
)
writeLines(
  "toy_value <- function() 'hello from the component'",
  file.path(source_root, "toycomponent", "R", "toy.R"),
  useBytes = TRUE
)

withr::with_dir(source_root, utils::tar(
  file.path(archive_root, "toycomponent_0.1.0.tar.gz"),
  files = "toycomponent", compression = "gzip"
))
```

The archive stem includes the version; `ext` is supplied separately.

```{r generate-metapackage}
result <- create_metapackage(
  name = "toyverse",
  packages = "toycomponent_0.1.0",
  pkg_dir = archive_root,
  dest_dir = destination,
  document = FALSE,
  verbose = FALSE,
  import_deps = character(),
  force_deps = character()
)
result
list.files(result$path)
```

The generated tree can be scanned without loading it:

```{r scan-metapackage}
scan <- scan_bigbang_artifact(result$path)
scan
stopifnot(!scan$vulnerable)
```

## Build, install, and use

In a real project, build and install the generated package using the standard R
workflow. Loading the metapackage never installs components:

```{r, eval = FALSE}
system2(file.path(R.home("bin"), "R"), c("CMD", "build", shQuote(result$path)))
install.packages("toyverse_0.1.0.tar.gz", repos = NULL, type = "source")
library(toyverse)
toyverse_install()
```

Those four lines are also the whole procedure for someone else. The component
archives were copied into the generated package, so `toyverse_0.1.0.tar.gz` is
the only file that has to travel: whoever receives it installs it and calls
`toyverse_install()`, with no archive directory beside it and no path agreed on
in advance. The default `pkg_dir` is
`system.file("archives", package = "toyverse")`, which is resolved when the
installer runs and therefore points at the library it was installed into.

## Re-export collisions

When multiple components export the same symbol, pass
`reexport_prefer = c(symbol = "component")` to choose its provider or
`reexport_exclude = "symbol"` to omit it. Every collision requires one of those
choices because static analysis cannot prove that two exported objects are the
same at runtime. The diagnostic labels collisions as `probable_same_object`,
`distinct_definitions`, or `undetermined`; a preferred probable collision is
checked against installed owners by `<meta>_install()` and `<meta>_conflicts()`.

Generate with `include_archives = FALSE` when the archives should stay in a
location every recipient can already reach; then `toyverse_install()` requires
an explicit `pkg_dir`.

`cran_deps = "skip"` is the offline default. Choose `"error"` for strict
offline validation or `"install"` only when an explicit repository is available.
Use `upgrade = "always"` or `force = TRUE` for an explicit reinstall. Generated
metapackages provide `<meta>_conflicts()` and honor
`options(<meta>.quiet = TRUE)` for startup output. Their optional `cli` display
falls back to a dependency-free ASCII banner.
`<meta>_conflicts()` retains masking conflicts. In a metapackage generated with
`reexport = TRUE`, inspect its installation check with
`<meta>_reexport_verification(<meta>_conflicts())`.

Before installing on a recipient machine, inspect the read-only plan:

```{r, eval = FALSE}
toyverse_deps(plan = TRUE, upgrade = "newer", cran_deps = "skip")
```

This reads the archive `DESCRIPTION` files and installed package metadata only.
It reports the archive version, installed version and library, planned action,
and missing or unsatisfied external constraints. It performs no loading,
installation, network access, or disk write. The installer and this plan share
the same version and upgrade policy evaluation.

## Interrupted updates and recovery

An interrupted `update = TRUE` leaves a durable journal beside the project.
The next update inspects it before writing, and `dry_run = TRUE` previews the
pending action. After confirming that no other update is running, use
`recover = TRUE` to preserve unknown user bytes and complete recovery.

## Beyond the simple case

The example above uses the simplest input: stems resolved in one directory. That
is not a requirement. Any element of `packages` that is an existing file is used
as a path, so components can come from several directories in one call, mix
`.tar.gz`, `.tar` and `.zip`, and carry no version in the filename — identity and
version are read from each archive's `DESCRIPTION`. A component can also be a
source directory, built for you with the optional `pkgbuild` package, or the whole
list can live in a manifest file under version control.

Two options are worth knowing before you generate anything for real:

```r
plan <- create_metapackage(..., dry_run = TRUE)
plan$order      # the installation order that would be used
plan$findings   # every validation finding, without writing anything
```

`dry_run = TRUE` does not create the destination at all. And `update = TRUE`
regenerates an existing project in place, rewriting only the files bigbang itself
wrote — it refuses if any of them was modified by hand, and never touches files it
did not write.

See `?create_metapackage` for the full set, including `on_component_error` for
generating from a partly broken set, `tolerate` for relaxing tidiness checks
individually, and `install_upgrade` for fixing the upgrade policy of the
installer that gets emitted.

```{r cleanup, include = FALSE}
unlink(root, recursive = TRUE)
```
