Refreshes the layers of a project's background_layers.gpkg from their
sources, reconciled against the project's manifest (see
rfp_manifest_read()) when one exists, else the template registry.
Replace-only: refresh = manifest-intersect-gpkg per source type; manifest-not-gpkg
layers are ADDED (the manifest edit was the deliberate act); frozen
layers are untouched; gpkg-not-manifest layers are flagged but never
removed. The legacy unprefixed AOI layer (#71) is removed when present.
Usage
rfp_project_update(
path,
watershed_groups,
manifest = NULL,
template = NULL,
add = NULL,
dry_run = TRUE,
path_hold = NULL,
dir_layers = NULL,
file_gpkg = NULL,
layout = NULL,
s3_base = NULL,
lookups = NULL
)Arguments
- path
Character. Path to the project directory containing
background_layers.gpkg.- watershed_groups
Character vector of 4-letter uppercase BC watershed group codes (e.g.,
c("BULK", "KLUM")). Interpolated into source SQL, so the format is enforced strictly.- manifest
NULL(default), a path to a manifest CSV, or a manifest data frame.NULLauto-discoversrfp_manifest.csvat the project root and falls back to registry mode when absent. The mode in use is always printed - no silent switch.- template
Character. Template for registry mode, and the style source for layers the project
.qgsdoes not reference.NULL(default) uses the template recorded in the project'srfp_project.json, falling back to"bcfishpass_mobile"for a project created before that was written. An explicit value always wins.- add
Character vector of registry layers to add (registry mode only - in manifest mode, edit the manifest instead). Default
NULL.- dry_run
Logical. Default
TRUE- print the plan and exit.- path_hold
Character. Root directory for pre-refresh backups. Default
NULLuses ahold/directory NEXT TO the project (never inside it - backups inside a Mergin project would sync to the server on the next push).- dir_layers
Character. Directory holding one GeoPackage per layer.
NULL(default) resolvesgetOption("rfp.dir_layers").- file_gpkg
Character. Single-GeoPackage file name for projects that have not been split.
NULL(default) resolvesgetOption("rfp.file_gpkg").- layout
Character.
"split","monolith", orNULL(default) to detect from the project directory.- s3_base
Character. Object-storage base for the
awspass, orNULL(default) to take the project's own recorded base and fall back to the shipped host. Re-resolved after a Mergin pull, because the record syncs (#268).- lookups
Named list of override CSVs for the
osm,urlandstactiers, merged row-wise over the shipped lookups. Passed straight torfp_source(); see there andrfp_source_lookup(). NOT recorded in the project's identity record the ways3_baseis - the file lives in the caller's repo, so a path written into a Mergin-synced project would be machine-specific and would sync to field devices (rfp#285).
Value
Invisibly, a list with plan (per-source-type refresh/add
lists), and on execute runs audit (the post-refresh
rfp_project_audit() result), path_hold (the backup directory), and
hashes (per-table content fingerprints via .gpkg_hash_tables()).
Details
DRY-RUN by default: prints the plan and exits - nothing touches the
project or Mergin until dry_run = FALSE. For a Mergin project
(.mergin/ present) an execute run pulls first, recomputes the plan
against post-pull state, and backs up the gpkg + .qgs +
habitat_lateral.tif to path_hold before any write. Never pushes
verify in QGIS desktop, then
rfp_mergin_push().
Refreshed layers that carry a shipped natural key (see
inst/lookups/rfp_natural_keys.csv, e.g. bcfishpass.streams_vw ->
segmented_stream_id) are REIDENTIFIED on execute: each surviving key
keeps the feature id it had before the refresh, so a re-download that
reassigns ids no longer churns every row and the Mergin push is a
true-delta changeset instead of the whole file (#12). The reidentify is
fail-closed - a layer whose key is dropped by a column keep-list, or is
not unique in the fresh data, silently falls back to naive ids (a full
push for that layer) - so any keep-list applied to a keyed layer must
retain its natural key.
Styling
On execute, the background GeoPackages are re-styled from the project's own
.qgs, so a layer added since the last run carries its symbology into
layer_styles — the table QGIS reads on Add Layer.
A layer the .qgs does not reference — one added since creation — is styled
from the project's recorded template instead, so it arrives styled on its
first Add Layer rather than needing to be styled by hand.
That second source is scoped to tables the project's own .qgs did not
cover, and the scoping is what makes it safe. Two overlapping sources would
replace a symbology restyled in QGIS Desktop on every run, and leave a
renamed layer trading useAsDefault between them forever. With no overlap
neither can happen, and re-styling an unchanged layer leaves its file
byte-identical, so it does not dirty a project for the next Mergin push.
A project with no recorded template (created before rfp 0.15.0) skips the second pass entirely and behaves as before.
Examples
if (FALSE) { # \dontrun{
# Dry run - review the plan
rfp_project_update("~/Projects/gis/test_kotl_20260505", "KOTL")
# Execute, then verify in QGIS desktop before pushing
rfp_project_update("~/Projects/gis/test_kotl_20260505", "KOTL",
dry_run = FALSE)
rfp_mergin_push("~/Projects/gis/test_kotl_20260505")
} # }
