| Title: | Version Management Tools on the File System |
|---|---|
| Description: | Data version management on the file system for smaller projects. Manage data pipeline outputs with symbolic folder links, structured logging and reports, using 'R6' classes for encapsulation and 'data.table' for speed. Directory-specific logs used as source of truth to allow portability of versioned data folders. |
| Authors: | Sam Byrne [aut, cre, cph] (ORCID: <https://orcid.org/0009-0008-1067-307X>) |
| Maintainer: | Sam Byrne <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 2.0.0 |
| Built: | 2026-11-13 13:49:45 UTC |
| Source: | https://github.com/epi-sam/vmtools |
Wrapper utility for sanitizing file.path(...) output
clean_path(..., normalize = TRUE, mustWork = FALSE)clean_path(..., normalize = TRUE, mustWork = FALSE)
... |
(chr) paths passed to file.path() |
normalize |
(lgl) pass path to normalizePath()? |
mustWork |
(lgl) passed to normalizePath() |
(chr) full file paths with consistent platform-specific structure
clean_path(tempdir(), "/some/other/path/") # build a single path like file.path clean_path(c(".", tempdir(), "/some/other/path/")) # vectorizedclean_path(tempdir(), "/some/other/path/") # build a single path like file.path clean_path(c(".", tempdir(), "/some/other/path/")) # vectorized
Return on the date-version, not the full path. Does not create a folder.
get_new_version_name(root, date = "today")get_new_version_name(root, date = "today")
root |
(chr) path to root of output results |
date |
(chr) character date in form of "YYYY_MM_DD" or "today". "today" will be interpreted as today's date. |
(chr) new output version of the form "YYYY_MM_DD.VV"
get_new_version_name(root = tempdir(), date = "today") # expect "YYYY_MM_DD.01"get_new_version_name(root = tempdir(), date = "today") # expect "YYYY_MM_DD.01"
Returns the named list of symlink types and their associated properties/functions. Expected entries are:
is_singleton: (logical) whether this symlink type is a singleton (only one per root)
symlink_suffix_fn: (function) function to create symlink name based on version name (for non-singleton symlink types)
ls_regex_fn: (function) function to find a symlink (by version_name for non-singletons) when running ls system calls
extract_regex: (function) function to get the regex pattern to find the symlink type
get_symlink_registry()get_symlink_registry()
(list) the full symlink registry as a named list
get_symlink_registry()get_symlink_registry()
Register a new symlink type
new_symlink_type(symlink_type, is_singleton, verbose = TRUE)new_symlink_type(symlink_type, is_singleton, verbose = TRUE)
symlink_type |
(chr) name of the new symlink type to register. Must not
be a canonical built-in symlink type |
is_singleton |
(lgl) Can there be only one of this symlink type per root
directory? If |
verbose |
(lgl: default |
(invisible NULL) called for side-effect of registering the new symlink type in the package-level registry environment
new_symlink_type("stalled", is_singleton = FALSE)new_symlink_type("stalled", is_singleton = FALSE)
Symlink Composer custom print method
## S3 method for class 'Symlink_Composer' print(x, ...)## S3 method for class 'Symlink_Composer' print(x, ...)
x |
(Symlink_Composer) The SLC class |
... |
(any) Additional arguments to print() |
(stdout)
SLCSLC
Symlink Tool custom print method
## S3 method for class 'Symlink_Tool' print(x, ...)## S3 method for class 'Symlink_Tool' print(x, ...)
x |
(Symlink_Tool) The SLT class |
... |
(any) Additional arguments to |
(stdout)
SLTSLT
Manages multiple pre-instantiated SymlinkTool instances for aggregated query operations across multiple projects.
new()
Initialize the SymlinkComposer
SLC$new(tool_list, verbose = FALSE)
tool_list(named list) Named list of pre-instantiated SLT objects. Names become tool identifiers for combined queries. Example: list( project_a = my_slt_a, project_b = my_slt_b )
verbose(lgl) Control message verbosity
(SymlinkComposer) A composer managing multiple SLT instances
get_tool()
Access individual SLT instances
SLC$get_tool(tool_name)
tool_name(chr) Name of the tool to retrieve
(SLT) The requested SymlinkTool instance
list_tools()
List all tool names
SLC$list_tools()
(chr) Vector of tool names
roundup_all()
Roundup symlinks of a given type across all tools
Valid types are determined by the intersection of symlink_types from
all SLT instances held by this composer. Use $get_common_symlink_types()
to inspect the valid set.
SLC$roundup_all(symlink_type, return_as = c("table", "version_name"))symlink_type(chr) One of the common symlink types across all tools, e.g. "best", "keep", "remove", "latest"
return_as(chr) "table" (default) or "version_name"
(data.table/chr)
get_common_symlink_types()
Return the symlink types common to all held SLT instances
These are the valid values for the symlink_type argument of roundup_all().
SLC$get_common_symlink_types()
(chr) Vector of common symlink type strings
roundup_all_unmarked()
Roundup all unmarked folders across all tools
SLC$roundup_all_unmarked(return_as = c("table", "version_name"))return_as(chr default: "table") or "version_name"
(data.table) Combined results with 'tool_name' column
roundup_all_by_date()
Roundup folders by date across all tools
SLC$roundup_all_by_date(
user_date,
date_selector,
return_as = c("table", "version_name")
)user_date(chr/Date/POSIXct) Date to query
date_selector(chr) One of: 'gt', 'gte', 'lt', 'lte', 'e'
return_as(chr default: "table") or "version_name"
(data.table) Combined results with 'tool_name' column
clone()
The objects of this class are cloneable with this method.
SLC$clone(deep = FALSE)
deepWhether to make a deep clone.
Class for lightweight file-system level data versioning, logs and reports without need for a database. Manages four symlink types: 'best' (validated production), 'latest' (most recent run), 'keep' (archive-worthy), and 'remove' (marked for deletion).
new()
Initialize the SymlinkTool object - an R6 class
The constructor function.
SLT$new( root_list = NULL, central_log_root = NULL, schema_repair = TRUE, verbose = FALSE, verbose_startup = FALSE, csv_reader = "fread_quiet", timezone = Sys.timezone() )
root_list(list) Named list of root directories for
pipeline outputs. This is where version_name folders live - these
are iterative runs of an analysis pipeline.
central_log_root(path) Root directory for the central log.
If you have multiple roots in the root_list, you probably want
the central log to live one level above those roots.
schema_repair(logical) Default TRUE. If TRUE, the tool
will attempt to repair any schema mismatches it finds in the logs
when reading and writing e.g. add new columns if the tool schema has
columns that existing logs do not. If FALSE, the tool will stop and
throw an error if it finds a schema mismatch.
verbose(lgl: default TRUE) control message verbosity - if TRUE, standard message, if FALSE, warn only if something is irregular.
verbose_startup(lgl) see start up warnings, if relevant?
csv_reader(chr) The CSV reader to use (also assigns matching
CSV writer). CAUTION: DO NOT USE data.table::fread if you have any
quotation marks (") in log comments (these lead to exploding series
of quotations). https://github.com/Rdatatable/data.table/issues/4779.
Otherwise use read.csv[2]. Options:
fread_quiet - data.table::fread and suppress warnings (default)
fread - data.table::fread
read.csv - utils::read.csv - safer
read.csv2 - utils::read.csv2 - safer, comma as decimal point, semicolon as field separator
timezone(chr) Default America/Los_Angeles. The timezone to
use for datestamps in logs. Must be a valid OlsonNames() string.
(symlink_tool) A symlink tool object. You can instantiate a.k.a. create multiple objects, each of which has different roots and central logs.
try(SLT$new()) # call with no arguments to see instructions # Tool will not instantiate on Windows unless running with Admin permissions # - requirement for symlink creation on Windows
return_dictionaries()
Return the contents of all private dictionaries.
SLT$return_dictionaries(item_names = NULL)
item_names(chr) Default NULL. If NULL, show all static
internal fields. Otherwise, vector of static field names you want to
see.
(list) of all static internal fields
return_dynamic_fields()
Print the contents of all dynamic fields.
SLT$return_dynamic_fields(item_names = NULL)
item_names(chr) Default NULL. If NULL, show all dynamic
internal fields. Otherwise, vector of dynamic field names you want
to see.
(std_out) Print dynamic field values to std_out.
mark()
Mark a version_name folder with a symlink of the specified type.
Generic dispatch method for all symlink marking. Legacy per-type
methods (mark_best, mark_latest, etc.) are superceded thin
wrappers around this.
SLT$mark(symlink_type, version_name, user_entry)
symlink_type(chr) A registered symlink type, e.g. "best",
"keep", or any type added via new_symlink_type().
version_name(chr) The version_name folder to mark.
user_entry(list) Named list of user log fields.
(std_err) Messages about actions taken.
mark_best()
Please use mark("best", version_name, user_entry) instead.
Enforces:
maximum of one best model
does not go back through history to make a best model from a prior version (not capable, this is what log_tool is for)
Writes:
appends to a log file in the output folder with a date and time stamp
appends a line to the central log file with a date and time stamp
SLT$mark_best(version_name, user_entry)
version_name(chr) The directory name of the output folder that
lives directly under one of the roots you define when you
instantiate the tool.
user_entry(list) Named list of user-defined fields to append to
the log. After making a tool called e.g. slt, call
slt$return_dictionaries("log_fields_user") to find which fields a
user may add. If you want to make your own version of this class,
you may update log_schema in the private$DICT section to allow
for them.
(ste_err) Messages about actions taken.
mark_latest()
Mark an output folder with a "latest" symlink.
Please use mark("latest", version_name, user_entry) instead.
Creates a 'latest' symlink (singleton) in each root. Auto-demotes current 'latest' if different. A folder cannot be both 'latest' and 'best' - this will auto-demote from the conflicting state.
Writes:
appends to a log file in the output folder with a date and time stamp
appends a line to the central log file with a date and time stamp
SLT$mark_latest(version_name, user_entry)
version_name(chr) The directory name of the output folder that
lives directly under one of the roots you define when you
instantiate the tool.
user_entry(list) Named list of user-defined fields to append to
the log. After making a tool called e.g. slt, call
slt$return_dictionaries("log_fields_user") to find which fields a
user may add. If you want to make your own version of this class,
you may update log_schema in the private$DICT section to allow
for them.
(std_err) Messages about actions taken.
mark_keep()
Mark an output folder with a "keep_<version_name>" symlink
Please use mark("keep", version_name, user_entry) instead.
Writes:
appends to a log file in the output folder with a date and time stamp
appends a line to the central log file with a date and time stamp
SLT$mark_keep(version_name, user_entry)
version_name(chr) The directory name of the output folder that
lives directly under one of the roots you define when you
instantiate the tool.
user_entry(list) Named list of user-defined fields to append to
the log. After making a tool called e.g. slt, call
slt$return_dictionaries("log_fields_user") to find which fields a
user may add. If you want to make your own version of this class,
you may update log_schema in the private$DICT section to allow
for them.
(std_err) Messages about actions taken.
mark_remove()
Mark an output folder with a "remove_<version_name>" symlink
Please use mark("remove", version_name, user_entry) instead.
Indication that the results can be deleted
In the future, this will be used to remove old versions of the output, and provide a list of ST-GPR models to delete
Writes:
appends to a log file in the output folder with a date and time stamp
appends a line to the central log file with a date and time stamp
SLT$mark_remove(version_name, user_entry)
version_name(chr) The directory name of the output folder that
lives directly under one of the roots you define when you
instantiate the tool.
user_entry(list) Named list of user-defined fields to append to
the log. After making a tool called e.g. slt, call
slt$return_dictionaries("log_fields_user") to find which fields a
user may add. If you want to make your own version of this class,
you may update log_schema in the private$DICT section to allow
for them.
(std_err) Messages about actions taken.
unmark()
Remove all symlinks for a single version_name in all roots
Writes:
appends to a log file in the output folder with a date and time stamp
does not append to the central log file
SLT$unmark(version_name, user_entry)
version_name(chr) The directory name of the output folder that
lives directly under one of the roots you define when you
instantiate the tool.
user_entry(list) Named list of user-defined fields to append to
the log. After making a tool called e.g. slt, call
slt$return_dictionaries("log_fields_user") to find which fields a
user may add. If you want to make your own version of this class,
you may update log_schema in the private$DICT section to allow
for them.
(std_err) Messages about the symlinks removed.
roundup()
Find all symlinks of a given type across all roots.
Generic dispatch method for all roundup operations. Legacy per-type
methods (roundup_best, roundup_keep, etc.) are superceded thin
wrappers.
SLT$roundup(symlink_type, return_as = c("table", "version_name"))symlink_type(chr) A registered symlink type.
return_as(chr: default "table") or "version_name".
(data.table/chr) A single data.table with results from all
roots, with root_name as the first column, or a vector of
version_names if return_as = version_name.
Table output schema
root_name version_name dir_name dir_name_resolved <char> <char> <char> <char>
roundup_best()
Find all best symlinks in all roots
Please use roundup("best", return_as) instead.
SLT$roundup_best(return_as = c("table", "version_name"))return_as(chr) Default table. Whether to return a data.table with
symlink and resolved paths (table) or just a vector of
version_names (version_name) for easier automated round-ups.
(data.table/chr) A single data.table with results from all
roots, with root_name as the first column, or a vector of
version_names if return_as = version_name.
Table output schema
root_name version_name dir_name dir_name_resolved <char> <char> <char> <char>
roundup_latest()
Find all latest symlinks in all roots
SLT$roundup_latest(return_as = c("table", "version_name"))return_as(chr) Default table. Whether to return a data.table with
symlink and resolved paths (table) or just a vector of
version_names (version_name) for easier automated round-ups.
(data.table/chr) A single data.table with results from all
roots, with root_name as the first column, or a vector of
version_names if return_as = version_name.
Table output schema
root_name version_name dir_name dir_name_resolved <char> <char> <char> <char>
roundup_keep()
Find all keep_ symlinks in all roots
SLT$roundup_keep(return_as = c("table", "version_name"))return_as(chr) Default table. Whether to return a data.table with
symlink and resolved paths (table) or just a vector of
version_names (version_name) for easier automated round-ups.
(data.table/chr) A single data.table with results from all
roots, with root_name as the first column, or a vector of
version_names if return_as = version_name.
Table output schema
root_name version_name dir_name dir_name_resolved <char> <char> <char> <char>
roundup_remove()
Find all remove_ symlinks in all roots
SLT$roundup_remove(return_as = c("table", "version_name"))return_as(chr) Default table. Whether to return a data.table with
symlink and resolved paths (table) or just a vector of
version_names (version_name) for easier automated round-ups.
(data.table/chr) A single data.table with results from all
roots, with root_name as the first column, or a vector of
version_names if return_as = version_name.
Table output schema
root_name version_name dir_name dir_name_resolved <char> <char> <char> <char>
roundup_unmarked()
Find all folders without symlinks in all roots
SLT$roundup_unmarked(return_as = c("table", "version_name"))return_as(chr) Default table. Whether to return a data.table with
symlink and resolved paths (table) or just a vector of
version_names (version_name) for easier automated round-ups.
(data.table/chr) A single data.table with results from all
roots, with root_name as the first column, or a vector of
version_names if return_as = version_name.
Table output schema
root_name version_name dir_name dir_name_resolved <char> <char> <char> <char>
roundup_by_date()
Find all version_name folders by creation date
Only finds folders that have a log, and reads creation date on first
row. User may select dates by (using the date_selector argument):
greater than - gt
greater than or equal to - gte
less than - nt
less than or equal to nte
equal to e
SLT$roundup_by_date(
user_date,
date_selector,
return_as = c("table", "version_name")
)user_date(c("character", "Date", POSIXct", "POSIXt")) A date with class requirements - must be formatted "2020-01-01 or 2020_01_01 or 2020/01/01"
date_selector(chr) See docstring explanation.
return_as(chr) Default table. Whether to return a data.table with
symlink and resolved paths (table) or just a vector of
version_names (version_name) for easier automated round-ups.
(data.table/chr) A single data.table with results from all
roots, with root_name as the first column, or a vector of
version_names if return_as = version_name.
Table output schema
root_name version_name dir_name dir_name_resolved <char> <char> <char> <char>
get_common_new_version_name()
Get a new YYYY_MM_DD.VV version compatible with ALL THE TOOL'S ROOTS
If root1 has 2025_01_01.01 and root2 has 2025_01_01.03, then a new folder would need to be 2025_01_01.04
SLT$get_common_new_version_name(date = "today", root_list = private$DICT$ROOTS)
date(chr) Default "today". The date to use for the new version name. Must be formatted "2020_01_01"
root_list(list) named list of root directories for pipeline
(chr) format YYYY_MM_DD.VV
make_new_version_folder()
Create a new version_name folder in ALL THE TOOL'S
ROOTS
Create a new log in each folder. No symlinks are created. No
user_entry is used.
SLT$make_new_version_folder(version_name = self$get_common_new_version_name())
version_name(chr) The directory name of the
output folder that lives directly under one of the roots you define
when you instantiate the tool. For convenience, user may leave NULL
(default) and get_common_new_version_name() is used on that root.
(std_err) Messages about the folder creation.
make_new_log()
Safely write an empty log file for first pipeline runs
When you start a new pipeline run, make an empty log
helpful if you let this tool manage all your versions
you can roundup version_names by creation date using the log's first entry
the file system doesn't track directory creation dates (at time of writing)
SLT$make_new_log(version_name)
version_name(chr) The directory name of the output folder that
lives directly under one of the roots you define when you
instantiate the tool.
(std_err) Messages about the log creation.
delete_version_folders()
Delete a version_name folder marked with a remove_ symlink from
ALL ITS ROOTS
Removes the symlink(s) and the underlying folder(s), and updates central log if folders were removed.
Writes:
appends a line to the central log file with a date and time stamp
SLT$delete_version_folders(version_name, user_entry, require_user_input = TRUE)
version_name(chr) The directory name of the output folder that
lives directly under one of the roots you define when you
instantiate the tool.
user_entry(list) Named list of user-defined fields to append to
the log. After making a tool called e.g. slt, call
slt$return_dictionaries("log_fields_user") to find which fields a
user may add. If you want to make your own version of this class,
you may update log_schema in the private$DICT section to allow
for them.
require_user_input(lgl) if TRUE, will prompt user to confirm
deletion.
(std_err) Messages about deletion events.
make_reports()
Make all reports
Writes all reports to a summary .csv for every root defined in the
tool.
SLT$make_reports()
(std_err) Messages about where reports were written.
clone()
The objects of this class are cloneable with this method.
SLT$clone(deep = FALSE)
deepWhether to make a deep clone.
## ------------------------------------------------ ## Method `SLT$new` ## ------------------------------------------------ try(SLT$new()) # call with no arguments to see instructions # Tool will not instantiate on Windows unless running with Admin permissions # - requirement for symlink creation on Windows## ------------------------------------------------ ## Method `SLT$new` ## ------------------------------------------------ try(SLT$new()) # call with no arguments to see instructions # Tool will not instantiate on Windows unless running with Admin permissions # - requirement for symlink creation on Windows