hash_children: Update file checksums to account for child documents

View source: R/utils-built-db.R

hash_childrenR Documentation

Update file checksums to account for child documents


If any R Markdown file contains a child document, its hash will be replaced with the hash of the combined and unnamed hashes of the parent and descendants (aka the lineage).


hash_children(checksums, files, lineage)




the hashes of the parent files


the relative path of the parent files to the root_path


a named list of character vectors specifying absolute paths for the full lineage of parent Markdown or R Markdown files (inclusive). The names will be the relative path of the parent.


a pegboard::Lesson object


When handling child files for lessons, it is important that changes in child files will cause the source file to change as well.

  • The get_lineages() function finds the child files from a pegboard::Lesson object.

  • Because we use a text database that relies on the hash of the file to determine if a file should be rebuilt, hash_children() piggybacks on this paradigm by assigning a unique hash to a parent file with children that is the hash of the vector of hashes of the files. The hash of hashes is created with rlang::hash().


  • get_lineages() a named list of charcter vectors specifying the lineage of parent files. The names are the relative paths of the parents.

  • hash_children() a character vector of hashes of the same length as the parent files.


# This demonstration will show how a temporary database can be set up. It
# will only work with a sandpaper lesson
# setup -----------------------------------------------------------------
# The setup needs to include an R Markdown file with a child file.
tmp <- tempfile()
on.exit(fs::dir_delete(tmp), add = TRUE)
create_lesson(tmp, rmd = FALSE, open = FALSE)
# get namespace to use internal functions
sp <- asNamespace("sandpaper")
db <- fs::path(tmp, "site/built/md5sum.txt")
resources <- fs::path(tmp, c("episodes/introduction.md", "index.md"))
# create child file
writeLines("Hello from another file!\n",
  fs::path(tmp, "episodes", "files", "hi.md"))
# use child file
cat("\n\n```{r child='files/hi.md'}\n```\n",
  file = resources[[1]], append = TRUE)
# convert to Rmd
fs::file_move(resources[[1]], fs::path_ext_set(resources[[1]], "Rmd"))
resources[[1]] <- fs::path_ext_set(resources[[1]], "Rmd")
set_episodes(tmp, fs::path_file(resources[[1]]), write = TRUE)

# get_lineages ------------------------------------------------------
# we can get the child files by scanning the Lesson object
lsn <- sp$this_lesson(tmp)
children <- sp$get_lineages(lsn)

# hash_children ---------------------------------------------------
# get hash of parent
phash <- tools::md5sum(resources[[1]])
rel_parent <- fs::path_rel(resources[[1]], start = tmp)
sp$hash_children(phash, rel_parent, children)
# demonstrate how this works ----------------
# the combined hashes have their names removed and then `rlang::hash()`
# creates the hash of the unnamed hashes.
chash <- tools::md5sum(children[[1]])
hashes <- unname(chash)

zkamvar/sandpaper documentation built on May 11, 2024, 7:26 a.m.