Skip to contents

Reads a legacy source job and copies its deterministic choices into a supported template. Writes the migrated job and an evidence report beside it. Review the remaining EDIT: markers before rendering the job.

Usage

migrate_job(
  source,
  subject,
  type,
  prefix = NULL,
  qualifier = NULL,
  lst = NULL,
  log = NULL,
  reference = NULL,
  dir = NULL
)

Arguments

source

Path to one legacy source job, relative to the working directory or absolute.

subject

Grouping topic for the new job's filename. It is a statistical endpoint only when the job analyses one; an endpoint-free job may use a topic such as "cohort".

type

Analysis-type field for the new job's filename.

prefix

Template prefix, such as "dc", or a template's full name, such as "dc-tables", which carries its qualifier and leaves qualifier NULL. Read from the SAS filename when NULL. When given without qualifier, the qualifier is still read from the filename's second field if that field names one of this prefix's templates.

qualifier

Template qualifier, such as "tables". Read from the SAS filename when NULL. When given without prefix, the prefix is read from the filename and this qualifier is used. Filename fields must match [A-Za-z0-9_]+.

lst

Optional path to a SAS listing, relative to the working directory or absolute. Defaults to the same-named file beside source when present.

log

Optional path to a SAS log, relative to the working directory or absolute. Defaults to the same-named file beside source when present.

reference

Optional vector of paths to output references, such as RTF or DOCX files, relative to the working directory or absolute. They record comparison targets, not analysis choices.

dir

Any directory in the study, used only to locate the study root. Defaults to the directory of source.

Value

The migrated job path, invisibly. The report is written beside it.

Details

A converter is available for dc-tables, dc-gfup, dc-trends, and dc-eda, each interpreting its own source choices; choices the interpreter does not recognize remain for review. Legacy EDA reports migrate into dc-eda with SECTIONS <- c("continuous", "percent", "count"), the pages they drew. Naming a deprecated template warns and writes the job from its replacement. Naming a template by its name before a rename, such as dp-trends, warns and writes the job from the renamed template, dc-trends; a legacy source whose own file name carries the old name, such as dp.trends.sas, migrates into the renamed template without a warning, since that name is not the caller's to change. A template with no converter yet still migrates: it is scaffolded with every EDIT: marker kept, the evidence travels with it, and the report says the migration adapter is not yet available.

Relative source, lst, log and reference paths resolve against the working directory, as in any R function; dir only locates the study root. Each file must exist, be readable and lie beneath that root, and symbolic links are checked after resolution. The evidence files are never modified. The report records whether the listing and log were supplied, found beside the source, or not found.

The job uses the filename and study folder selected by add_job. Its report replaces the .qmd extension with -migration.md and records study-relative evidence paths, SHA-256 checksums, the package version, translated choices, unresolved choices, and ignored material. Source text quoted in the report is masked, whichever converter ran: string literal contents (R raw strings included), SAS and R comment bodies, %let values (whole, even when a macro-quoting function such as %str() holds a semicolon), %put text, unquoted title and footnote text, and digit runs of five or more are replaced by placeholders such as "[string]" or [text], and Quarto or R Markdown prose and YAML are withheld. Statement keywords, variable names and operators remain. Absolute paths in any remaining text are redacted. The job is not masked. SAS log errors leave a blocking EDIT: marker in the generated job. Listings, RTF files and log messages may contain patient observations. Their text is withheld; locations remain available for local review. Logs retain severity, error codes and recognized aggregate counts only.

Both outputs are prepared as temporary files beside their targets before placement. Migration refuses to overwrite an existing target, checked for each output immediately before it is placed. Outputs are placed by hard link, which cannot replace an existing file; where the filesystem refuses hard links, the prepared file is renamed into place after a fresh check, so a concurrent writer landing between that check and the rename can still be replaced. If placement fails, only the outputs this call placed are removed, along with its temporary files.

Examples

# \donttest{
root <- file.path(tempdir(), "migrate-job-example")
invisible(hvtiRutilities::study_setup(root, "Example", 1L, renv = FALSE))
# A legacy follow-up job; the template is read from its name, dc.gfup.
sas <- file.path(hvtiRutilities::study_dir("descriptive", root), "dc.gfup.sas")
writeLines(c("data followup;", "  set built;", "run;",
             "proc means data=followup; var iv_dead; by dead; run;"), sas)
job <- migrate_job(sas, subject = "cohort", type = "eda")
basename(job)
#> [1] "dc.gfup.cohort.eda.qmd"

# The choices it translated into the new job ...
grep("^(EVENT|FOLLOWUP) <- ", readLines(job), value = TRUE)
#> [1] "EVENT <- \"dead\""          "FOLLOWUP <- c(\"iv_dead\")"

# ... and the report beside it, saying what was translated and what is left
# to review.
report <- readLines(sub("[.]qmd$", "-migration.md", job))
headings <- grep("^## ", report)
first <- which(report[headings] == "## Translated")
# The Translated section and the one after it, Unresolved.
report[headings[first]:(headings[first + 2L] - 1L)]
#> [1] "## Translated"                                                                                                  
#> [2] ""                                                                                                               
#> [3] "- line=4; text=var iv_dead;; reason=Declared follow-up fields; no interval derivation reproduced."              
#> [4] "- line=4; text=by dead;; reason=Leading BY field supplies event evidence; other sort fields do not filter data."
#> [5] ""                                                                                                               
#> [6] "## Unresolved"                                                                                                  
#> [7] ""                                                                                                               
#> [8] "- line=2; text=set built;; reason=study_config(): [absolute path]) after the default study dataset exists."     
#> [9] ""                                                                                                               
unlink(root, recursive = TRUE)
# }