From 605f795c3fff7587f2187cddc07e2a3b8afb4ffa Mon Sep 17 00:00:00 2001 From: eanslot Date: Fri, 23 Jan 2026 17:19:18 +0100 Subject: [PATCH 1/2] copy files without inheriting read/write/execute permissions --- R/bs-dependencies.R | 16 +++++++++++++--- tools/compile_component_sass.R | 2 +- tools/yarn_install.R | 27 ++++++++++++++++++--------- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/R/bs-dependencies.R b/R/bs-dependencies.R index 2ddd47e47..e9951159d 100644 --- a/R/bs-dependencies.R +++ b/R/bs-dependencies.R @@ -128,7 +128,7 @@ maybe_precompiled_css <- function(theme, sass_options, precompiled) { } dir.create(out_dir) - file.copy(precompiled_css, out_file) + file.copy(precompiled_css, out_file, copy.mode = FALSE) # Usually sass() would handle file_attachments and dependencies, # but we need to do this manually @@ -176,7 +176,12 @@ sass_compile_theme <- function(theme, sass_options, sass_cache) { bootstrap_javascript_copy_assets <- function(version, to) { js_files <- bootstrap_javascript(version) js_map_files <- bootstrap_javascript_map(version) - success_js_files <- file.copy(c(js_files, js_map_files), to, overwrite = TRUE) + success_js_files <- file.copy( + c(js_files, js_map_files), + to, + overwrite = TRUE, + copy.mode = FALSE + ) if (any(!success_js_files)) { warning( "Failed to copy over bootstrap's javascript files into the htmlDependency() directory." @@ -273,7 +278,12 @@ bs_dependency <- function( basename(outfile) ) } - success <- file.copy(script, dirname(outfile), overwrite = TRUE) + success <- file.copy( + script, + dirname(outfile), + overwrite = TRUE, + copy.mode = FALSE + ) if (!all(success)) { stop( "Failed to copy the following script(s): ", diff --git a/tools/compile_component_sass.R b/tools/compile_component_sass.R index 72cce3c26..a7001b47f 100644 --- a/tools/compile_component_sass.R +++ b/tools/compile_component_sass.R @@ -9,4 +9,4 @@ dep <- component_dependency_sass_(bs_theme()) css <- file.path(dep$src, dep$stylesheet) target_dir <- path_inst("components", "dist") target_css <- file.path(target_dir, "components.css") -file.copy(css, target_css, overwrite = TRUE) +file.copy(css, target_css, overwrite = TRUE, copy.mode = FALSE) diff --git a/tools/yarn_install.R b/tools/yarn_install.R index da6c8226d..f23e0c996 100755 --- a/tools/yarn_install.R +++ b/tools/yarn_install.R @@ -385,12 +385,13 @@ with_dir("inst/lib", { Sys.glob(file.path(src, "*.css")) ) core_files <- core_files[!grepl(theme_js_pattern, basename(core_files))] - file.copy(core_files, dest) + file.copy(core_files, dest, copy.mode = FALSE) # Copy utils file.copy( Sys.glob(file.path(src, "utils", "*.js")), - file.path(dest, "utils") + file.path(dest, "utils"), + copy.mode = FALSE ) # Copy languages (only bundled) @@ -399,13 +400,15 @@ with_dir("inst/lib", { bundled_languages <- bundled_languages[file.exists(bundled_languages)] file.copy( bundled_languages, - file.path(dest, "languages") + file.path(dest, "languages"), + copy.mode = FALSE ) # Copy prism grammars (only bundled) file.copy( file.path(src, "prism", "languages", bundled_lang_files), - file.path(dest, "prism", "languages") + file.path(dest, "prism", "languages"), + copy.mode = FALSE ) # Copy extensions @@ -416,11 +419,12 @@ with_dir("inst/lib", { ) # Copy top-level extension files ext_js <- ext_files[grepl("\\.js$", ext_files)] - file.copy(ext_js, file.path(dest, "extensions")) + file.copy(ext_js, file.path(dest, "extensions"), copy.mode = FALSE) # Copy copyButton extension folder file.copy( Sys.glob(file.path(src, "extensions", "copyButton", "*")), - file.path(dest, "extensions", "copyButton") + file.path(dest, "extensions", "copyButton"), + copy.mode = FALSE ) # ============================================================================ @@ -506,7 +510,8 @@ with_dir("inst/lib", { # Copy themes file.copy( Sys.glob(file.path(src, "themes", "*.css")), - file.path(dest, "themes") + file.path(dest, "themes"), + copy.mode = FALSE ) # Scope theme CSS files to support multiple editors with different themes. @@ -740,7 +745,7 @@ invisible( if (!dir.exists(dest_dir)) { dir.create(dest_dir) } - file.copy(tmp_css, dest_dir) + file.copy(tmp_css, dest_dir, copy.mode = FALSE) # Also save the BS5+ Sass code used to generate the pre-compiled CSS. # This is primarily here to help Quarto more easily replicate bs_theme()'s Sass. @@ -752,7 +757,11 @@ invisible( ) writeLines(theme_sass, file.path(dest_dir, "bootstrap.scss")) # Sanity check that we we can compile by moving file to home dir - file.copy(file.path(dest_dir, "bootstrap.scss"), "bootstrap.scss") + file.copy( + file.path(dest_dir, "bootstrap.scss"), + "bootstrap.scss", + copy.mode = FALSE + ) on.exit(unlink("bootstrap.scss"), add = TRUE) testthat::expect_error(sass(sass_file("bootstrap.scss")), NA) } From de945d62605858b2d4e6dcf67ae3f6b5f8327166 Mon Sep 17 00:00:00 2001 From: eanslot Date: Fri, 23 Jan 2026 17:30:35 +0100 Subject: [PATCH 2/2] update NEWS.md --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index eed32a649..daf550760 100644 --- a/NEWS.md +++ b/NEWS.md @@ -32,6 +32,8 @@ * Fixed an issue where `nav_panel_hidden()` could create navs that were still keyboard-discoverable. (#1264) +* Copy files without inheriting read/write/execute permissions fixing issues when using bslib on immutable operating systems. (#1281) + # bslib 0.9.0 ## Breaking changes