spacehakr 0.4.0
-
[spk_source_url()] silently failed on any URL containing
&, which is every service endpoint.system2()pastes its arguments into a command string and runs it throughsh, quoting only the command itself — measured:system2("echo", args = "a&b")printsaand reportssh: b: command not found. A query-string URL was therefore split at each&, and the trailingcount=1was read byshas a successful variable assignment, soogr2ogrreported status 0 having written nothing. Arguments are now shell-quoted at the point of invocation.The same gap was a command-injection vector, not only a correctness bug: a
;, backtick or$()reachingshinside a caller-suppliedurlsorqueryvalue would have executed. That matters wherever these values come from a config file or a layer catalog rather than from a literal in the calling script.This also restores
query. The 0.3.0 note below saysshQuote()was removed becausesystem2()“does not go through a shell”; that is not correct, and a-whereclause containing quotes and spaces has been dying with a shell syntax error (loudly, at least) ever since. A caller who worked around it by pre-quoting their query should remove that quoting. [spk_source_url()] gains
vsi, choosing the GDAL virtual filesystem each URL is read through./vsicurl/— still the default, so nothing changes for existing callers — probes a source with aHEADrequest and reads it with HTTP range requests, which a service endpoint addressed by a query string typically supports neither of. Measured against a BC Geographic Warehouse WFS on GDAL 3.13.0:HEADreturns 404 and aRangerequest is answered with a full-body 200, so the open fails before any driver is tried, and forcing the driver does not help.vsi = "curl_streaming"reads with a single sequentialGETand works. Until now the only way to avoid/vsicurl/was to supply anencoding, which is a statement about a source’s character set rather than its transport — so a WFS endpoint could not be expressed at all.Behaviour change: [spk_source_url()] now requires
layerwhen a URL carries a query string. The derived name wastools::file_path_sans_ext(basename(url)), which for a WFSGetFeaturerequest is the entire query string. A caller who relied on the derived name for a query-string URL — a presigned object URL, say — must now passlayerexplicitly.[spk_source_url()] no longer leaks temp files when given several URLs with an
encoding.on.exit()was registered inside the loop, so all registrations resolved to the last value of the source path: the final temp file was unlinked once per URL and every earlier one survived for the life of the session. Measured at 2 of 3 leaked.[spk_source_url()] refuses
encodingcombined with a non-defaultvsi. An encoded source is downloaded and re-encoded before conversion, so it never reaches a virtual filesystem, and honouring one argument while silently dropping the other is what madeencodingusable as a transport switch in the first place.
spacehakr 0.3.0
[spk_source_url()] now fails loudly. The
ogr2ogrexit status was never checked, so a bad URL, a 404 or an unreadable source returned exactly what success returned, and a layer that was never written looked identical to one that was.stderrnow goes to a file rather than being merged into a discarded value, and a non-zero status aborts naming the URL and the tail of the diagnostic.[spk_source_url()] gains
open_options,a_srs,t_srs,layerandencoding. A non-spatial CSV carrying coordinate columns can now become a point layer (-oo X_POSSIBLE_NAMES=,-a_srs), a source that is not UTF-8 is fetched and re-encoded before conversion (GDAL’s CSV driver has no encoding open option), and the layer name no longer has to be whatever the URL’s file name happens to be.[spk_source_url()] creates the output GeoPackage when it does not exist, rather than requiring one to append to.
Behaviour change: [spk_source_url()]’s
queryis no longer passed throughshQuote().system2()with an argument vector does not go through a shell, so the quotes were reaching-whereliterally and the filter is unlikely to have worked. A caller who compensated by pre-quoting their query should remove that quoting.
spacehakr 0.2.0
-
Add [spk_source_url()] and [spk_source_bcdata()], which fetch layers into a GeoPackage from an arbitrary URL and from the BC Data Catalogue respectively. Sourcing data from public endpoints is what a reader needs to regenerate a report’s inputs, so these belong in a public package.
[spk_source_url()] reads through GDAL’s
/vsicurl/virtual filesystem and takes an optional SQLqueryapplied as-where. It subsumes a separate CSV-only fetcher that was byte-equivalent to it with the filter omitted, so there is one entry point rather than two.bcdatajoinsImportsfor [spk_source_bcdata()]. Adopt the two STAC articles from
ngr. Both demonstratespk_stac_calc(), so they follow the function here rather than documenting a deprecated shim on ngr’s site. They live invignettes/articles/— pkgdown builds them,R CMD buildignores them. As true vignettes they would have to build on all five check runners against the live Planetary Computer API.Exclude
.gitfrom the build. In agit worktreecheckout.gitis a file holding an absolute developer path, andR CMD buildships it (it is only excluded when it is a directory).
spacehakr 0.1.0
First tagged release. Twelve spatial functions extracted from ngr’s ngr_spk_* family — GDAL and OpenDroneMap command building, GeoServer WFS download, STAC raster math, spatial joins and raster utilities. See the reference index.
This release exists so ngr has a pinnable version to depend on while it deprecates its own copies of these functions (ngr#7).
- Declare
rlanginImports. It was imported byspk_join()via@importFrom rlang .databut never declared, soR CMD checkfailed withNamespace dependency missing from DESCRIPTION Imports/Depends entries. This went unnoticed because the package had noR-CMD-checkworkflow. - Add an
R-CMD-checkworkflow, so the twelve test files run on every push rather than never. - Guard the
gdalwarprun intest-spk_gdalwarp.R. It shelled out to the GDAL CLI at file top level with no guard, which errors the whole file on any machine without it — including every GitHub runner. Now scoped to atest_that()block that skips whengdalwarpis not onPATH.
