rstudio / rsconnect

Publish Shiny Applications, RMarkdown Documents, Jupyter Notebooks, Plumber APIs, and more
http://rstudio.github.io/rsconnect/
131 stars 80 forks source link

Support full `.gitignore` syntax in `.rcsignore` #774

Open ColinFay opened 1 year ago

ColinFay commented 1 year ago

Issue

The . rcsignore file doesn't work with :

  1. folders that are listed as folder/ instead of folder
  2. files that are in subdirectories

Diagnosis

  1. For dev/ : the setdiff here is not smart enough : https://github.com/rstudio/rsconnect/blob/cf0972d0d69357cf2bc81ab140f940085aac92cb/R/bundleFiles.R#L200

list.files() (that created the contents object) will do

[1] "DESCRIPTION" "dev"         "inst"        "man"         "NAMESPACE"  
[6] "R" 

When a directory can usually be written folder/ in an ignore file.

  1. The list file that creates the contents object doesn't list subfolders: recursiveBundleFiles doesn't do a recursive in the list file https://github.com/rstudio/rsconnect/blob/cf0972d0d69357cf2bc81ab140f940085aac92cb/R/bundleFiles.R#L137

How to reproduce

  1. Go to /tmp & create a golem app:
; cd /tmp && Rscript -e 'golem::create_golem("reprexrsconnect")' && cd reprexrsconnect
  1. Add 'DESCRIPTION' to .rscignore => works as expected
; echo 'DESCRIPTION' >> .rscignore  
; ls
DESCRIPTION     NAMESPACE       R               dev             inst            man
; Rscript -e 'rsconnect::listDeploymentFiles(".")'
 [1] ".here"                    ".Rbuildignore"           
 [3] "dev/01_start.R"           "dev/02_dev.R"            
 [5] "dev/03_deploy.R"          "dev/run_dev.R"           
 [7] "inst/app/www/favicon.ico" "inst/golem-config.yml"   
 [9] "man/run_app.Rd"           "NAMESPACE"               
[11] "R/app_config.R"           "R/app_server.R"          
[13] "R/app_ui.R"               "R/run_app.R"
  1. Trying to ignore dev/ => doesn't work
; echo 'dev/' >> .rscignore
; Rscript -e 'rsconnect::listDeploymentFiles(".")'
 [1] ".here"                    ".Rbuildignore"           
 [3] "dev/01_start.R"           "dev/02_dev.R"            
 [5] "dev/03_deploy.R"          "dev/run_dev.R"           
 [7] "inst/app/www/favicon.ico" "inst/golem-config.yml"   
 [9] "man/run_app.Rd"           "NAMESPACE"               
[11] "R/app_config.R"           "R/app_server.R"          
[13] "R/app_ui.R"               "R/run_app.R"      
  1. Trying to ignore dev/01_start.R => doesn't work
 ;echo 'dev/01_start.R' >> .rscignore 
 [1] ".here"                    ".Rbuildignore"           
 [3] ".rscignor"                "dev/01_start.R"          
 [5] "dev/02_dev.R"             "dev/03_deploy.R"         
 [7] "dev/run_dev.R"            "inst/app/www/favicon.ico"
 [9] "inst/golem-config.yml"    "man/run_app.Rd"          
[11] "NAMESPACE"                "R/app_config.R"          
[13] "R/app_server.R"           "R/app_ui.R"              
[15] "R/run_app.R"             
  1. Printing the rscignore just to be sure
; cat .rscignore 
DESCRIPTION
dev/
dev/01_start.R

Happy to help with submitting a patch if you want :)

hadley commented 1 year ago

Do you mind creating a reprex for me? The following code looks correct to me.

library(rsconnect)

dir <- withr::local_tempdir()
dir.create(file.path(dir, "a", "b"), recursive = TRUE)
file.create(file.path(dir, c("x", "a/y", "a/b/z")))
#> [1] TRUE TRUE TRUE
listDeploymentFiles(dir)
#> [1] "a/b/z" "a/y"   "x"

writeLines("y", file.path(dir, "a", ".rscignore"))
listDeploymentFiles(dir)
#> [1] "a/b/z" "x"

writeLines(c("y", "b"), file.path(dir, "a", ".rscignore"))
listDeploymentFiles(dir)
#> [1] "x"

Created on 2023-03-16 with reprex v2.0.2

hadley commented 1 year ago

Or are you asking about this?

#' *  You can exclude additional files by listing them in in a `.rscignore`
#'    file. This file must have one file or directory per line (with path
#'    relative to the current directory). It doesn't support wildcards, or
#'    ignoring files in subdirectories.
hadley commented 1 year ago

This is not technically supported, but it's a popular request, so I'll bite the bullet and implement it. See implementation in renv for a starting point: https://github.com/rstudio/renv/blob/main/R/renvignore.R.

Looking forward, should read both .rscignore and .connectignore.