Skip to content

[Feature]: GDAL Configuration #8

Description

@jimbrig

GDAL Configuration System (gdal_config)

Incorporate a global, stateful GDAL configuration system into the existing options (gdal_opts) and internal package environment systems.

Motivation

The package's value layer (gdal_config_opts(), gdal_vsi_opts(), driver-typed builders) can describe configuration but nothing applies it: workflows still end in raw gdalraster::set_config_option() walls (see dev/work/pipelines/), with no memory of prior state, no restore, and no way to ask "what is in effect right now and who set it."

Design

A three-tier model, keeping GDAL itself as the single source of truth (nothing is ever mirrored):

Tier Object Role
Value gdal_config An inert, composable bundle: one gdal_config_opts payload (global channel) + zero or more path-bound gdal_vsi_opts (VSI channel). Full S3 conventions: new_gdal_config(), gdal_config(...) constructor, as_gdal_config() coercions, c() merge (later wins - the composition primitive future presets build on), cli format()/print(), render methods.
State active gdal_config in .pkg_env What this session has applied, retrievable via gdal_config_active() for reuse/rendering anywhere (CLI args, optfile, child processes). Restore metadata (prior value, whether it came from an envvar, scrubbed envvars) is internal bookkeeping, not part of the value.
View gdal_config_sitrep() Live provenance report of effective configuration (see #12).

Verbs

  • gdal_config_set(...) - applies to GDAL (set_config_option() / vsi_set_path_option()), records priors on first touch, merges into the active config. Accepts KEY = value pairs, gdal_config values, gdal_config_opts/gdal_vsi_opts objects, named lists, "KEY=VALUE" strings. Rejects open/creation opts (wrong channel) with a classed error.
  • gdal_config_get(keys) - effective values, read live from GDAL, never from package state.
  • gdal_config_unset(keys, mode) - explicit semantics for the envvar fallback (see below).
  • gdal_config_reset(keys) - restores touched keys to their true pre-package state (including re-setting scrubbed envvars).
  • local_gdal_config() / with_gdal_config() - scoped application with exact restoration (GDAL values and package state) even on error; the recommended pattern around pipeline executions.

The precedence model (why unset needs modes)

GDAL resolves a key: thread-local -> global in-memory (CPLSetConfigOption; includes config-file values loaded at init) -> environment variable (live getenv()) -> built-in default. Consequences:

  • Set is authoritative - a set value beats an envvar while set.
  • Unset is not - clearing the in-memory entry reveals the envvar underneath; the built-in default cannot be forced while an envvar exists.

Hence gdal_config_unset(mode = ):

  • "reveal" (default): clear; warn (classed) when an envvar re-surfaces.
  • "mask": pin the documented default from driver/runtime metadata - "GDAL default behavior" despite an envvar.
  • "scrub": also Sys.unsetenv() (recorded, so reset restores it) - the only true removal; explicit opt-in.

Known options (no unbacked hardcoded lists)

Advisory (never blocking) typo checking draws on, in decreasing authority:

  1. Runtime: VSI/network/credential options enumerated from the running GDAL build (vsi_get_fs_prefixes() x vsi_get_fs_options()), lazily cached.
  2. Curated driver metadata: the existing per-driver config option table.
  3. Curated core: a small GDAL_CORE_CONFIG_OPTS list (aaa.R) for core CPL/GDAL/OGR names only, which GDAL does not expose at runtime (gdalraster does not bind CPLGetKnownConfigOptions(), GDAL >= 3.11 - upstream request candidate).
  4. Envvars present at load (app-defined options are known to the user's setup by definition).

Keys GDAL already resolves to a value are never flagged.

VSI: one key namespace, two binding tiers

gdal_vsi_opts are config opts; the vsi_path attribute binds them at the path-specific tier (VSIGetPathSpecificOption: longest-prefix match, then fall through to the normal chain). Unbound VSI opts are plain config opts. Consequence for rendering: path-bound options cannot be expressed as CLI --config flags - as_gdal_args() omits them with a message by default, with an explicit flatten_vsi = TRUE escape hatch (warns when multiple paths carry conflicting values). The gdalrc [credentials] section is the only lossless out-of-process serialization (see #13).

Load-time behavior

gdal_config_init() (in rlang::on_load()): empty active config + restore store, snapshot of GDAL-relevant envvars, config-file discovery, an at_load baseline sitrep - then a tiny, curated, fill-only default set (currently just GDAL_HTTP_USERAGENT from pkg_user_agent()), applied through gdal_config_set() (ledgered, visible, reversible) only when the key resolves to nothing, opt-out via options(gdalvector.config_defaults = FALSE).

Related

Activity

  1. self-assigned this
    on Jul 2, 2026
  2. changed the title [-]GDAL Configuration[/-] [+][Feature]: GDAL Configuration[/+] on Jul 2, 2026
  3. linked a pull request that will close this issueGDAL Configuration System (#8) #15on Jul 2, 2026
  4. added 2 commits that reference this issue on Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationenhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions