ProjectTemplate icon indicating copy to clipboard operation
ProjectTemplate copied to clipboard

create.project() failing to create .Rproj in the intended directory

Open 3styleJam opened this issue 9 months ago • 6 comments

Steps to reproduce:

  1. Open RStudio. Ensure you are NOT in an RStudio project.
  2. Run install.packages("ProjectTemplate") in the console.
  3. Create a new script "letters_script.R" within the directory "C:/Users/your/working/directory/letters"
  4. Insert the following code into the script, save and run:
library("ProjectTemplate")

create.project(
  project.name = "C:/Users/your/working/directory/letters",
  rstudio.project = TRUE,
  merge.strategy = "allow.non.conflict"
)
  1. The console returns:
#> Error in file(con, "w") : cannot open the connection
#> In addition: Warning message:
#> In file(con, "w") :
#>  cannot open file 
#>'C:/Users/your/working/directory/letters/C:/Users/your/working/directory/letters.Rproj': Invalid argument

Viewing the directory in File Explorer shows folders have been created: cache, config, data e.t.c. , and the "letters_script.R" is still there. The problem is the .Rproj file isn't created and from the error message, the function duplicates the "project.name" argument and concatenates onto itself when generating the file path for the .Rproj file. A fix for this would be much appreciated, thank you.

3styleJam avatar May 12 '25 11:05 3styleJam

That is a really nice edge case @3styleJam! Obviously the way the code works is that the project name is concatenated after the directory.

As a first step, why do you need the full path as the project name? Could the script work with just the project name being letters?

KentonWhite avatar May 12 '25 13:05 KentonWhite

That is a really nice edge case @3styleJam! Obviously the way the code works is that the project name is concatenated after the directory.

As a first step, why do you need the full path as the project name? Could the script work with just the project name being letters?

Hi. When I run "letters_script.R", the current working directory is not "C:/Users/your/working/directory/letters", it is some other drive (in my case a network drive in my organisation). Therefore, if I only have "project.name = letters", it will create the project in the location given by the network drive (including the .Rproj file), not the target directory in the C: drive. There is the workaround of using setwd("C:/Users/your/working/directory") before create.project(...), but using setwd() in R scripts is not best practice and I cant use the {here} package as that relies on already being in an RStudio project. In my mind, if I want to create a brand new project, it's easier to specify the full path so that create.project() can check whether the "letters" directory exists, and if it doesn't exist then it creates it and the other folders as subdirectories: "letters/cache", "letters_data" etc.

3styleJam avatar May 12 '25 13:05 3styleJam

What if there was a directory parameter in the call to create.project?

KentonWhite avatar May 12 '25 13:05 KentonWhite

What if there was a directory parameter in the call to create.project?

Yes a "project.directory" parameter would be good. It's default value could be the current working directory, and on the help page for the function make it clear that the "project.name" is the folder to be created within "project.directory". The concatenation would then be between those arguments.

3styleJam avatar May 12 '25 14:05 3styleJam

I've had a look at the code and should be straight forward. In the file R/create.project.R would need to change line 106 and line 157 to use a parameter project.directory. I'm already planning to do some work on ProjectTemplate this weekend. If you need it sooner I would really appreciate if you could fork the project, make the change, and then submit a PR!

KentonWhite avatar May 12 '25 17:05 KentonWhite

There is the workaround of using setwd("C:/Users/your/working/directory") before create.project(...), but using setwd() in R scripts is not best practice and I cant use the {here} package as that relies on already being in an RStudio project.

By the way, using setwd() in R scripts is only bad practice in case you don't "clean up" after its use. It's similar to opening a database connection and not closing it again once finished. Nobody would claim opening a database connection is bad practice in the first place. To make sure the R environment is left as is, you could just call setwd() from within a function with an on.exit() (https://stat.ethz.ch/R-manual/R-devel/library/base/html/on.exit.html) statement like this:

create_project <- function(path, ...) {
  old <- setwd(path)
  on.exit(setwd(old))

  ...
}

gisler avatar May 27 '25 20:05 gisler