Skip to contents

Checks a repository's files for the three ways authors commonly pin the environment their analysis depended on, so a later reproduction attempt knows which R and package versions were actually used rather than whatever happens to be current: an renv.lock file (parsed for the R version and every locked package + its version/source), a sessionInfo() / sessioninfo::session_info() text dump (matched by filename, since authors deposit these as a dedicated file rather than burying them in unrelated text — see @details), or a groundhog::groundhog.library() / checkpoint::checkpoint() call in the R code, which pin by date instead of a lockfile. Static analysis only: this reports what was DECLARED, not whether the declared versions still install today (that risk is what repro_install_deps()'s CRAN Archive fallback exists for).

Usage

.code_version_pin_check(
  all_files,
  code_text_list = list(),
  max_file_size = 100,
  max_download_size = 500,
  cache = FALSE,
  skip_on_api_limit = FALSE,
  max_files_per_repo = Inf
)

Arguments

all_files

the full repo file listing (repo_check's table: needs file_name, file_url, repo_url, file_location where available)

code_text_list

a named list of already-read R file text (names are file_names) — reused for the groundhog/checkpoint scan and for records pasted into scripts, so no file is downloaded or read twice

max_file_size

passed to download_repo_files() for any candidate file not yet local

max_download_size

passed to download_repo_files()

cache

passed to download_repo_files()

skip_on_api_limit

passed to download_repo_files()

Value

a list: pinned (logical, TRUE if any mechanism was found), mechanisms (character vector, any of renv.lock, sessionInfo, groundhog, checkpoint), r_versions (character vector of R version strings found, one per source), renv_files (character vector of renv.lock file_names found), renv_packages (data frame file_name, package, version, source, remote ("user/repo@ref" for a package from GitHub, else NA) — one row per locked package, across all renv.lock files found), sessioninfo_files (character vector of matched file_names), session_packages (data frame with the same columns — one row per package version the sessionInfo()/session_info() records list), pin_dates (data frame mechanism (groundhog or checkpoint), date — one row per distinct date), python_files (character vector of the file_names of Python package lists: requirements*.txt, environment.yml, Pipfile(.lock), poetry.lock, uv.lock, pyproject.toml), python_pinned (logical, TRUE if any Python package list was found; pinned stays about R only), file_location (named character vector, file_name -> resolved local path, for every candidate file this call downloaded — a caller re-checking a SUBSET of all_files per paper can splice these back into its own copy of all_files first, so the same file is never downloaded twice across repeat calls)

Details

The sessionInfo() scan is filename-gated, not a blanket content scan of every text file in the repository: it looks at files whose name suggests they ARE such a dump (sessioninfo/session_info/session-info, case-insensitive, any extension — the two forms actually seen in a real corpus are sessionInfo.txt and session_info.txt) plus any readme* file, since authors sometimes paste the dump into a README instead of a dedicated file. A blanket scan of every .txt/.md/.log file was considered and rejected: it would also match a paper's own methods prose mentioning an R version in a sentence, which is not a pinned-environment record.

renv.lock is matched by its fixed, case-sensitive filename (that is the one name renv itself ever writes) and searched for anywhere in the repository tree, not just the top level — a paper can deposit more than one (e.g. one per study folder), and all are reported.

groundhog/checkpoint are detected by the PINNING CALL itself (groundhog.library(pkg, "YYYY-MM-DD"), checkpoint("YYYY-MM-DD")), not merely library(groundhog)/library(checkpoint): loading the package is not evidence it was used to pin anything, so a bare library() call does not count. The date may be held in a variable the same script assigns it to; a call in a comment does not count.

The packages a sessionInfo() or session_info() record lists are read by .code_session_packages(). A file that only mentions an R version still counts as a sessionInfo record, but has no rows in session_packages. A record pasted into an R script, usually as comments, also counts, but only when it lists packages: a comment such as "needs R version 4.2.0" does not.