
# NOTE: this script may run more than once over the same tree (on Windows,
# install-boost.cmd invokes install-boost.R once per build variant), so every
# replacement below must be idempotent: re-applying it to already-patched
# sources must be a no-op.

# figure out which files to explore
exts <- c("cpp", "h", "hpp", "inc", "inl", "ipp")
pattern <- sprintf("[.](%s)$", paste(exts, collapse = "|"))

# find all the files we might need to modify
files <- list.files(
   path       = c("boost", "libs"),
   pattern    = pattern,
   full.names = TRUE,
   recursive  = TRUE
)

# skip examples
files <- grep("/(examples?)/", files, value = TRUE, invert = TRUE)

for (file in files) {
   
   # read the file as a string
   contents <- readLines(file, warn = FALSE, encoding = "latin1")
   original <- paste(contents, collapse = "\n")
   replacement <- original
   
   # make replacements
   replacement <- gsub(
      pattern     = "namespace[[:space:]]+boost[[:space:]\\\\\\\\]*{",
      replacement = "namespace rstudio_boost {} namespace boost = rstudio_boost; namespace rstudio_boost {",
      x           = replacement,
      perl        = TRUE
   )
   
   # also needed for some macro Boost stuff
   replacement <- gsub(
      pattern     = "(boost)",
      replacement = "(rstudio_boost)",
      x           = replacement,
      fixed       = TRUE
   )
   
   # for nested namespaces
   replacement <- gsub(
      pattern     = "namespace boost::",
      replacement = "namespace rstudio_boost::",
      x           = replacement,
      fixed       = TRUE
   )

   # Boost.Exception (1.91+) parses __PRETTY_FUNCTION__ at compile time by
   # matching string literals that hard-code the 'boost' namespace; after the
   # rename the compiler emits 'rstudio_boost', so no pattern matches and a
   # static assert fires. Patch the literals to match the renamed namespace.
   # (boost/exception/detail/type_info.hpp)
   replacement <- gsub(
      pattern     = "(?<!rstudio_)boost::n::",
      replacement = "rstudio_boost::n::",
      x           = replacement,
      perl        = TRUE
   )
   
   if (!identical(original, replacement)) {
      writeLines(replacement, con = file, useBytes = TRUE)
      writeLines(sprintf("-- Updated \"%s\"", file))
   }
   
}
