rprojroot/0000755000175100001440000000000013037143624012333 5ustar hornikusersrprojroot/inst/0000755000175100001440000000000013037131577013314 5ustar hornikusersrprojroot/inst/doc/0000755000175100001440000000000013037131577014061 5ustar hornikusersrprojroot/inst/doc/rprojroot.Rmd0000644000175100001440000002052013037131577016564 0ustar hornikusers--- title: "Finding files in project subdirectories" author: "Kirill Müller" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Finding files in project subdirectories} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- The `rprojroot` package solves a seemingly trivial but annoying problem that occurs sooner or later in any largish project: How to find files in subdirectories? Ideally, file paths are relative to the *project root*. Unfortunately, we cannot always be sure about the current working directory: For instance, in RStudio it's sometimes: - the project root (when running R scripts), - a subdirectory (when building vignettes), - again the project root (when executing chunks of a vignette). ```{r} basename(getwd()) ``` In some cases, it's even outside the project root. This vignette starts with a very brief summary that helps you get started, followed by a longer description of the features. ## TL;DR What is your project: An R package? ```{r} rprojroot::is_r_package ``` Or an RStudio project? ```{r} rprojroot::is_rstudio_project ``` Or something else? ```{r} rprojroot::has_file(".git/index") ``` For now, we assume it's an R package: ```{r} root <- rprojroot::is_r_package ``` The `root` object contains a function that helps locating files below the root of your package, regardless of your current working directory. If you are sure that your working directory is somewhere below your project's root, use the `root$find_file()` function: ```{r} readLines(root$find_file("DESCRIPTION"), 3) ``` You can also construct an accessor to your root using the `root$make_fix_file()` function: ```{r} root_file <- root$make_fix_file() ``` Note that `root_file()` is a *function* that works just like `$find_file()` but will find the files even if the current working directory is outside your project: ```{r} withr::with_dir( "../..", readLines(root_file("DESCRIPTION"), 3) ) ``` If you know the absolute path of some directory below your project, but cannot be sure of your current working directory, pass that absolute path to `root$make_fix_file()`: ```r root_file <- root$make_fix_file("C:\\Users\\User Name\\...") ``` Get the path of standalone R scripts or vignettes using the `thisfile()` function in the `kimisc` package: ```r root_file <- root$make_fix_file(dirname(kimisc::thisfile())) ``` The remainder of this vignette describes implementation details and advanced features. ## Project root We assume a self-contained project where all files and directories are located below a common *root* directory. Also, there should be a way to unambiguously identify this root directory. (Often, the root contains a regular file whose name matches a given pattern, and/or whose contents match another pattern.) In this case, the following method reliably finds our project root: - Start the search in any subdirectory of our project - Proceed up the directory hierarchy until the root directory has been identified The Git version control system (and probably many other tools) use a similar approach: A Git command can be executed from within any subdirectory of a repository. ### A simple example The `find_root()` function implements the core functionality. It returns the path to the first directory that matches the filtering criteria, or throws an error if there is no such directory. Filtering criteria are constructed in a generic fashion using the `root_criterion()` function, the `has_file()` function constructs a criterion that checks for the presence of a file with a specific name and specific contents. ```{r} library(rprojroot) # List all files and directories below the root dir(find_root(has_file("DESCRIPTION"))) # Find a file relative to the root file.exists(find_root_file("R", "root.R", criterion = has_file("DESCRIPTION"))) ``` Note that the following code produces identical results when building the vignette *and* when sourcing the chunk in RStudio, provided that the current working directory is the project root or anywhere below. ### Criteria The `has_file()` function (and the more general `root_criterion()`) both return an S3 object of class `root_criterion`: ```{r} has_file("DESCRIPTION") ``` In addition, character values are coerced to `has_file` criteria by default, this coercion is applied automatically by `find_root()`. (This feature is used by the introductory example.) ```{r} as.root_criterion("DESCRIPTION") ``` The return value of these functions can be stored and reused; in fact, the package provides `r length(criteria)` such criteria: ```{r} criteria ``` Defining new criteria is easy: ```{r} has_license <- has_file("LICENSE") has_license is_projecttemplate_project <- has_file("config/global.dcf", "^version: ") is_projecttemplate_project ``` You can also combine criteria via the `|` operator: ```{r} is_r_package | is_rstudio_project ``` ### Shortcuts To avoid specifying the search criteria for the project root every time, shortcut functions can be created. The `find_package_root_file()` is a shortcut for `find_root_file(..., criterion = is_r_package)`: ```{r} # Print first lines of the source for this document head(readLines(find_package_root_file("vignettes", "rprojroot.Rmd"))) ``` To save typing effort, define a shorter alias: ```{r} P <- find_package_root_file # Use a shorter alias file.exists(P("vignettes", "rprojroot.Rmd")) ``` Each criterion actually contains a function that allows finding a file below the root specified by this criterion. As our project does not have a file named `LICENSE`, querying the root results in an error: ```{r error = TRUE} # Use the has_license criterion to find the root R <- has_license$find_file R # Our package does not have a LICENSE file, trying to find the root results in an error R() ``` ### Fixed root We can also create a function that computes a path relative to the root *at creation time*. ```{r} # Define a function that computes file paths below the current root F <- is_r_package$make_fix_file() F # Show contents of the NAMESPACE file in our project readLines(F("NAMESPACE")) ``` This is a more robust alternative to `$find_file()`, because it *fixes* the project directory when `$make_fix_file()` is called, instead of searching for it every time. (For that reason it is also slightly faster, but I doubt this matters in practice.) This function can be used even if we later change the working directory to somewhere outside the project: ```{r} # Print the size of the namespace file, working directory outside the project withr::with_dir( "../..", file.size(F("NAMESPACE")) ) ``` The `make_fix_file()` member function also accepts an optional `path` argument, in case you know your project's root but the current working directory is somewhere outside. Take a look at the `thisfile()` function in the `kimisc` package for getting the path to the current script or `knitr` document. ## `testthat` files Tests run with [`testthat`](https://cran.r-project.org/package=testthat) commonly use files that live below the `tests/testthat` directory. Ideally, this should work in the following situation: - During package development (working directory: package root) - When testing with `devtools::test()` (working directory: `tests/testthat`) - When running `R CMD check` (working directory: a renamed recursive copy of `tests`) The `is_testthat` criterion allows robust lookup of test files. ```{r} is_testthat ``` The example code below lists all files in the [hierarchy](https://github.com/krlmlr/rprojroot/tree/master/tests/testthat/hierarchy) test directory. It uses two project root lookups in total, so that it also works when rendering the vignette (*sigh*): ```{r} dir(is_testthat$find_file("hierarchy", path = is_r_package$find_file())) ``` ## Summary The `rprojroot` package allows easy access to files below a project root if the project root can be identified easily, e.g. if it is the only directory in the whole hierarchy that contains a specific file. This is a robust solution for finding files in largish projects with a subdirectory hierarchy if the current working directory cannot be assumed fixed. (However, at least initially, the current working directory must be somewhere below the project root.) ## Acknowledgement This package was inspired by the gist ["Stop the working directory insanity"](https://gist.github.com/jennybc/362f52446fe1ebc4c49f) by Jennifer Bryan, and by the way Git knows where its files are. rprojroot/inst/doc/rprojroot.html0000644000175100001440000007072313037131577017020 0ustar hornikusers Finding files in project subdirectories

Finding files in project subdirectories

Kirill Müller

2017-01-16

The rprojroot package solves a seemingly trivial but annoying problem that occurs sooner or later in any largish project: How to find files in subdirectories? Ideally, file paths are relative to the project root.

Unfortunately, we cannot always be sure about the current working directory: For instance, in RStudio it’s sometimes:

basename(getwd())
## [1] "vignettes"

In some cases, it’s even outside the project root.

This vignette starts with a very brief summary that helps you get started, followed by a longer description of the features.

TL;DR

What is your project: An R package?

rprojroot::is_r_package
## Root criterion: contains a file `DESCRIPTION` with contents matching `^Package: `

Or an RStudio project?

rprojroot::is_rstudio_project
## Root criterion: contains a file matching `[.]Rproj$` with contents matching `^Version: ` in the first line

Or something else?

rprojroot::has_file(".git/index")
## Root criterion: contains a file `.git/index`

For now, we assume it’s an R package:

root <- rprojroot::is_r_package

The root object contains a function that helps locating files below the root of your package, regardless of your current working directory. If you are sure that your working directory is somewhere below your project’s root, use the root$find_file() function:

readLines(root$find_file("DESCRIPTION"), 3)
## [1] "Package: rprojroot"                            
## [2] "Title: Finding Files in Project Subdirectories"
## [3] "Version: 1.2"

You can also construct an accessor to your root using the root$make_fix_file() function:

root_file <- root$make_fix_file()

Note that root_file() is a function that works just like $find_file() but will find the files even if the current working directory is outside your project:

withr::with_dir(
  "../..",
  readLines(root_file("DESCRIPTION"), 3)
)
## [1] "Package: rprojroot"                            
## [2] "Title: Finding Files in Project Subdirectories"
## [3] "Version: 1.2"

If you know the absolute path of some directory below your project, but cannot be sure of your current working directory, pass that absolute path to root$make_fix_file():

root_file <- root$make_fix_file("C:\\Users\\User Name\\...")

Get the path of standalone R scripts or vignettes using the thisfile() function in the kimisc package:

root_file <- root$make_fix_file(dirname(kimisc::thisfile()))

The remainder of this vignette describes implementation details and advanced features.

Project root

We assume a self-contained project where all files and directories are located below a common root directory. Also, there should be a way to unambiguously identify this root directory. (Often, the root contains a regular file whose name matches a given pattern, and/or whose contents match another pattern.) In this case, the following method reliably finds our project root:

The Git version control system (and probably many other tools) use a similar approach: A Git command can be executed from within any subdirectory of a repository.

A simple example

The find_root() function implements the core functionality. It returns the path to the first directory that matches the filtering criteria, or throws an error if there is no such directory. Filtering criteria are constructed in a generic fashion using the root_criterion() function, the has_file() function constructs a criterion that checks for the presence of a file with a specific name and specific contents.

library(rprojroot)

# List all files and directories below the root
dir(find_root(has_file("DESCRIPTION")))
##  [1] "API"              "DESCRIPTION"      "Makefile"        
##  [4] "NAMESPACE"        "NEWS.md"          "R"               
##  [7] "README.md"        "_pkgdown.yml"     "appveyor.yml"    
## [10] "cran-comments.md" "docs"             "inst"            
## [13] "man"              "readme"           "revdep"          
## [16] "rprojroot.Rproj"  "tests"            "tic.R"           
## [19] "vignettes"
# Find a file relative to the root
file.exists(find_root_file("R", "root.R", criterion = has_file("DESCRIPTION")))
## [1] TRUE

Note that the following code produces identical results when building the vignette and when sourcing the chunk in RStudio, provided that the current working directory is the project root or anywhere below.

Criteria

The has_file() function (and the more general root_criterion()) both return an S3 object of class root_criterion:

has_file("DESCRIPTION")
## Root criterion: contains a file `DESCRIPTION`

In addition, character values are coerced to has_file criteria by default, this coercion is applied automatically by find_root(). (This feature is used by the introductory example.)

as.root_criterion("DESCRIPTION")
## Root criterion: contains a file `DESCRIPTION`

The return value of these functions can be stored and reused; in fact, the package provides 9 such criteria:

criteria
## $is_rstudio_project
## Root criterion: contains a file matching `[.]Rproj$` with contents matching `^Version: ` in the first line
## 
## $is_r_package
## Root criterion: contains a file `DESCRIPTION` with contents matching `^Package: `
## 
## $is_remake_project
## Root criterion: contains a file `remake.yml`
## 
## $is_projectile_project
## Root criterion: contains a file `.projectile`
## 
## $is_git_root
## Root criterion: contains a directory `.git`
## 
## $is_svn_root
## Root criterion: contains a directory `.svn`
## 
## $is_vcs_root
## Root criterion: one of
## - contains a directory `.git`
## - contains a directory `.svn`
## 
## $is_testthat
## Root criterion: directory name is `testthat` (also look in subdirectories: `tests/testthat`, `testthat`)
## 
## $from_wd
## Root criterion: from current working directory
## 
## attr(,"class")
## [1] "root_criteria"

Defining new criteria is easy:

has_license <- has_file("LICENSE")
has_license
## Root criterion: contains a file `LICENSE`
is_projecttemplate_project <- has_file("config/global.dcf", "^version: ")
is_projecttemplate_project
## Root criterion: contains a file `config/global.dcf` with contents matching `^version: `

You can also combine criteria via the | operator:

is_r_package | is_rstudio_project
## Root criterion: one of
## - contains a file `DESCRIPTION` with contents matching `^Package: `
## - contains a file matching `[.]Rproj$` with contents matching `^Version: ` in the first line

Shortcuts

To avoid specifying the search criteria for the project root every time, shortcut functions can be created. The find_package_root_file() is a shortcut for find_root_file(..., criterion = is_r_package):

# Print first lines of the source for this document
head(readLines(find_package_root_file("vignettes", "rprojroot.Rmd")))
## [1] "---"                                               
## [2] "title: \"Finding files in project subdirectories\""
## [3] "author: \"Kirill Müller\""                         
## [4] "date: \"`r Sys.Date()`\""                          
## [5] "output: rmarkdown::html_vignette"                  
## [6] "vignette: >"

To save typing effort, define a shorter alias:

P <- find_package_root_file

# Use a shorter alias
file.exists(P("vignettes", "rprojroot.Rmd"))
## [1] TRUE

Each criterion actually contains a function that allows finding a file below the root specified by this criterion. As our project does not have a file named LICENSE, querying the root results in an error:

# Use the has_license criterion to find the root
R <- has_license$find_file
R
## function (..., path = ".") 
## {
##     find_root_file(..., criterion = criterion, path = path)
## }
## <environment: 0x55ca0ef0cf10>
# Our package does not have a LICENSE file, trying to find the root results in an error
R()
## Error: No root directory found in /tmp/Rtmp76Lko7/Rbuild36db711fd839/rprojroot/vignettes or its parent directories. Root criterion: contains a file `LICENSE`

Fixed root

We can also create a function that computes a path relative to the root at creation time.

# Define a function that computes file paths below the current root
F <- is_r_package$make_fix_file()
F
## function (...) 
## {
##     file.path("/tmp/Rtmp76Lko7/Rbuild36db711fd839/rprojroot", 
##         ...)
## }
## <environment: 0x55ca0cd18718>
# Show contents of the NAMESPACE file in our project
readLines(F("NAMESPACE"))
##  [1] "# Generated by roxygen2: do not edit by hand"
##  [2] ""                                            
##  [3] "S3method(\"|\",root_criterion)"              
##  [4] "S3method(as.root_criterion,character)"       
##  [5] "S3method(as.root_criterion,default)"         
##  [6] "S3method(as.root_criterion,root_criterion)"  
##  [7] "S3method(format,root_criterion)"             
##  [8] "S3method(print,root_criterion)"              
##  [9] "S3method(str,root_criteria)"                 
## [10] "export(as.root_criterion)"                   
## [11] "export(criteria)"                            
## [12] "export(find_package_root_file)"              
## [13] "export(find_remake_root_file)"               
## [14] "export(find_root)"                           
## [15] "export(find_root_file)"                      
## [16] "export(find_rstudio_root_file)"              
## [17] "export(find_testthat_root_file)"             
## [18] "export(from_wd)"                             
## [19] "export(get_root_desc)"                       
## [20] "export(has_dir)"                             
## [21] "export(has_dirname)"                         
## [22] "export(has_file)"                            
## [23] "export(has_file_pattern)"                    
## [24] "export(is.root_criterion)"                   
## [25] "export(is_git_root)"                         
## [26] "export(is_projectile_project)"               
## [27] "export(is_r_package)"                        
## [28] "export(is_remake_project)"                   
## [29] "export(is_rstudio_project)"                  
## [30] "export(is_svn_root)"                         
## [31] "export(is_testthat)"                         
## [32] "export(is_vcs_root)"                         
## [33] "export(root_criterion)"                      
## [34] "import(backports)"                           
## [35] "importFrom(utils,str)"

This is a more robust alternative to $find_file(), because it fixes the project directory when $make_fix_file() is called, instead of searching for it every time. (For that reason it is also slightly faster, but I doubt this matters in practice.)

This function can be used even if we later change the working directory to somewhere outside the project:

# Print the size of the namespace file, working directory outside the project
withr::with_dir(
  "../..",
  file.size(F("NAMESPACE"))
)
## [1] 880

The make_fix_file() member function also accepts an optional path argument, in case you know your project’s root but the current working directory is somewhere outside. Take a look at the thisfile() function in the kimisc package for getting the path to the current script or knitr document.

testthat files

Tests run with testthat commonly use files that live below the tests/testthat directory. Ideally, this should work in the following situation:

The is_testthat criterion allows robust lookup of test files.

is_testthat
## Root criterion: directory name is `testthat` (also look in subdirectories: `tests/testthat`, `testthat`)

The example code below lists all files in the hierarchy test directory. It uses two project root lookups in total, so that it also works when rendering the vignette (sigh):

dir(is_testthat$find_file("hierarchy", path = is_r_package$find_file()))
## [1] "DESCRIPTION"     "a"               "b"               "c"              
## [5] "hierarchy.Rproj"

Summary

The rprojroot package allows easy access to files below a project root if the project root can be identified easily, e.g. if it is the only directory in the whole hierarchy that contains a specific file. This is a robust solution for finding files in largish projects with a subdirectory hierarchy if the current working directory cannot be assumed fixed. (However, at least initially, the current working directory must be somewhere below the project root.)

Acknowledgement

This package was inspired by the gist “Stop the working directory insanity” by Jennifer Bryan, and by the way Git knows where its files are.

rprojroot/inst/doc/rprojroot.R0000644000175100001440000000614313037131577016250 0ustar hornikusers## ------------------------------------------------------------------------ basename(getwd()) ## ------------------------------------------------------------------------ rprojroot::is_r_package ## ------------------------------------------------------------------------ rprojroot::is_rstudio_project ## ------------------------------------------------------------------------ rprojroot::has_file(".git/index") ## ------------------------------------------------------------------------ root <- rprojroot::is_r_package ## ------------------------------------------------------------------------ readLines(root$find_file("DESCRIPTION"), 3) ## ------------------------------------------------------------------------ root_file <- root$make_fix_file() ## ------------------------------------------------------------------------ withr::with_dir( "../..", readLines(root_file("DESCRIPTION"), 3) ) ## ------------------------------------------------------------------------ library(rprojroot) # List all files and directories below the root dir(find_root(has_file("DESCRIPTION"))) # Find a file relative to the root file.exists(find_root_file("R", "root.R", criterion = has_file("DESCRIPTION"))) ## ------------------------------------------------------------------------ has_file("DESCRIPTION") ## ------------------------------------------------------------------------ as.root_criterion("DESCRIPTION") ## ------------------------------------------------------------------------ criteria ## ------------------------------------------------------------------------ has_license <- has_file("LICENSE") has_license is_projecttemplate_project <- has_file("config/global.dcf", "^version: ") is_projecttemplate_project ## ------------------------------------------------------------------------ is_r_package | is_rstudio_project ## ------------------------------------------------------------------------ # Print first lines of the source for this document head(readLines(find_package_root_file("vignettes", "rprojroot.Rmd"))) ## ------------------------------------------------------------------------ P <- find_package_root_file # Use a shorter alias file.exists(P("vignettes", "rprojroot.Rmd")) ## ----error = TRUE-------------------------------------------------------- # Use the has_license criterion to find the root R <- has_license$find_file R # Our package does not have a LICENSE file, trying to find the root results in an error R() ## ------------------------------------------------------------------------ # Define a function that computes file paths below the current root F <- is_r_package$make_fix_file() F # Show contents of the NAMESPACE file in our project readLines(F("NAMESPACE")) ## ------------------------------------------------------------------------ # Print the size of the namespace file, working directory outside the project withr::with_dir( "../..", file.size(F("NAMESPACE")) ) ## ------------------------------------------------------------------------ is_testthat ## ------------------------------------------------------------------------ dir(is_testthat$find_file("hierarchy", path = is_r_package$find_file())) rprojroot/tests/0000755000175100001440000000000012526472104013475 5ustar hornikusersrprojroot/tests/testthat.R0000644000175100001440000000007612526472104015463 0ustar hornikuserslibrary(testthat) library(rprojroot) test_check("rprojroot") rprojroot/tests/testthat/0000755000175100001440000000000013037143624015335 5ustar hornikusersrprojroot/tests/testthat/vcs/0000755000175100001440000000000013037121233016120 5ustar hornikusersrprojroot/tests/testthat/vcs/svn.zip0000644000175100001440000002360413037121233017457 0ustar hornikusersPK 6}/Jsvn/UT ({X'=zXux PK6}/Jsvn/DESCRIPTIONUT ({X({Xux =J1yKW3 HT0j⚹LB$dl|1*ݞ?ӡ>@ %F$v6I̐ A&P"xg=!s1Q)^ ^A-1iUI =Zsp{`wt|ū#Z>da 89hY)Jm̿O_"2ќ+|lXB^˺tkh`FGCoyw_݈PK 6}/J svn/.svn/UT ({X'=zXux PK 6}/JMsvn/.svn/formatUT ({X({Xux 12 PK6}/J 'Rsvn/.svn/wc.dbUT ({X({Xux [ly:WkFS%pxo]YeѦ oApX)RKRAJ%}I4A^CmzyiH7-y-$M (ǶgI39s\T,W60GeEa^k6 x1fw1Jz=g1ֳ3>2^mV.ַ|ycnQV6+;r6Cץ4EN c:3i9өΓxROzR7Az;. #3˹kktp糙jsj&{~/Ib^~Cz~px8ܬL_ót^fyɧLISFRVH\R%T#QM3U"$ʧSF\գ>=%?vKd~=w)' =Kuj|p#ɝ1n ̱'+0cJgՓ5a*SB, z3}Op -v{~"dDW%;'cA-{}g_;7;5~q8c<<>ݨAd'iwhEzCMʪlɨiČj"z9H&OzBz"O,y^G;~_ ZNOE)vf5'W/٧#?~ ;d;F|ȞGB>n46ưC>Nh=8w>?h &clw*ÿ6>) /t>~P ]\oG9|1~wךoֳXzu岶NZۙ=]3g؛5 ^%nRÎS%m"ۯa|t=se[ngߵ*ץ*~xvj$'=!KW Cš_N4Q`Ǟ/J<ˢ_'[dk]EkTM/-Z"ձg z{ב0F1rV#ۑ!";c؃5yau{s:魲Fy.\W կ?îkw⳸n:Xg^@_j̣ytm i7&:5r^ÞGQ1MCP$H%{0*N˻Ʊϼd:fsDnϽikpU\cGýnK!F>36h??1/;[ -_g82.߽%Kh* zc}Rs+y&k|O@h{_뚸#YwL5_hމ Gݿӱ+LNֿM)$<9"ӮD]J`y;^_FބPK 6}/JMsvn/.svn/entriesUT ({X({Xux 12 PK .J svn/.svn/tmp/UT '=zX'=zXux PK 6}/Jsvn/.svn/pristine/UT ({X({Xux PK 6}/Jsvn/.svn/pristine/f0/UT ({X({Xux PK6}/Jash߯c&/pGr3fg$O0؋gR /6a`l+8.!%PmǔɎ5UwVGޠO:]_C9hwvPS:= ڨjrAVS # l`LijR֧5x٦vԱ:D4x붧ԠiW+I@ĕ~~PK 6}/Jsvn/.svn/pristine/f3/UT ({X({Xux PK 6}/JyEFsvn/.svn/pristine/f3/f30dae958ef83fc13091258906c050936e39b8f9.svn-baseUT ({X({Xux File b in root PK 6}/Jsvn/.svn/pristine/da/UT ({X({Xux PK 6}/JFsvn/.svn/pristine/da/da39a3ee5e6b4b0d3255bfef95601890afd80709.svn-baseUT ({X({Xux PK 6}/Jsvn/.svn/pristine/9e/UT ({X({Xux PK 6}/J %JFsvn/.svn/pristine/9e/9ed97191f4672ff9ef5d9659438d776ea57fb6ba.svn-baseUT ({X({Xux File b PK 6}/Jsvn/.svn/pristine/1f/UT ({X({Xux PK6}/JFsvn/.svn/pristine/1f/1fff0ad79f00c81b19245903e27229dff1771fd4.svn-baseUT ({X({Xux =J1yKW3 HT0j⚹LB$dl|1*ݞ?ӡ>@ %F$v6I̐ A&P"xg=!s1Q)^ ^A-1iUI =Zsp{`wt|ū#Z>da 89hY)Jm̿O_"2ќ+|lXB^˺tkh`FGCoyw_݈PK 6}/Jsvn/.svn/wc.db-journalUT ({X({Xux PK 6}/Jsvn/a/UT ({X({Xux PK 6}/Jsvn/a/b/UT ({X({Xux PK 6}/J svn/a/b/aUT ({X({Xux PK 6}/J %J svn/a/b/bUT ({X({Xux File b PK 6}/J svn/a/b/c/UT ({X({Xux PK 6}/J svn/a/b/c/dUT ({X({Xux PK6}/Jash߯c&/pGr3fg$O0؋gR /6a`l+8.!%PmǔɎ5UwVGޠO:]_C9hwvPS:= ڨjrAVS # l`LijR֧5x٦vԱ:D4x붧ԠiW+I@ĕ~~PK 6}/JyEsvn/bUT ({X({Xux File b in root PK 6}/Jsvn/cUT ({X({Xux PK 6}/JAsvn/UT({Xux PK6}/J>svn/DESCRIPTIONUT({Xux PK 6}/J Acsvn/.svn/UT({Xux PK 6}/JMsvn/.svn/formatUT({Xux PK6}/J 'Rsvn/.svn/wc.dbUT({Xux PK 6}/JMsvn/.svn/entriesUT({Xux PK .J Asvn/.svn/tmp/UT'=zXux PK 6}/JA svn/.svn/pristine/UT({Xux PK 6}/JAlsvn/.svn/pristine/f0/UT({Xux PK6}/Jas@ %F$v6I̐ A&P"xg=!s1Q)^ ^A-1iUI =Zsp{`wt|ū#Z>da 89hY)Jm̿O_"2ќ+|lXB^˺tkh`FGCoyw_݈PK .Jgit/a/UT @zX@zXux PK .Jgit/a/b/UT @zX@zXux PK .J git/a/b/aUT @zX@zXux PK .J %J git/a/b/bUT @zX@zXux File b PK .J git/a/b/c/UT @zX@zXux PK .J git/a/b/c/dUT @zX@zXux PK Y.J git/.git/UT ZAzX=zXux PK `.Jgit/.git/hooks/UT =zX=zXux PK`.JO $git/.git/hooks/applypatch-msg.sampleUT =zX=zXux U]N1 s *HHp.nS-l[^o^ܭ7>ɩZ{B!"0([J8˽V&ZfTA=;H9/-Ov`&F3j.[K?@#rvDO BYq+7Sy:Qfm(}DJ 9CSQ ^&4VB09eٝh}6ЃV` Br)}??M PK`.JL $git/.git/hooks/pre-applypatch.sampleUT =zX=zXux U[N1 EK:@VVB=DL&Q>nq,o#S!pWcHƞjO8/ 霷.Eh_p*^L|huV#iت7 Q>ޮ"\'yvFi[R^GgpP|XCMh4`KLZ)0x,W㲵ol6DkȢ;xdi #FQnapB7\>cZŗ6z7"<ϑV\>%2O0 o9J[F 8UVmK(OPRpvs'+aε{@zhngPK`.J git/.git/hooks/commit-msg.sampleUT =zX=zXux }_o0şOqH+VMJ" XD&7l|w&E=Re M]C͍F^S~WrݶҡZVTɷi;OЊ Lշ"0h l'>Oպo ޒ\i ap(Hk{*uFwF G'$d OYo:ye 皒MRϗ >!-7)q]ͳ`:T|G"mm/#U1EY)*R])H6ڛ*?A _H~ uPN6N p8Waj{wypjGXOw|-/]2c\+ }FLj'#(9^j=^k.P~Y8cA1PG8jG䈐d}7+Yg4 _{]EPK`.JI !git/.git/hooks/pre-receive.sampleUT =zX=zXux uPN0<_1}@[ʑ*HV"!UnM;B;vʣqzg3:ZZ; :*Ҙ lVbCZQm2<+MʷWP& Y:Q;앓hJd텄^ի%i$㒟jBk=hq/BK/E3UM2R;TG֡I/y:M4[,R +~EkâveKL q(h_uԌMkS6g9o5^q{~㱯a~"M%qpQ,kbbPK`.J!D%ugit/.git/hooks/update.sampleUT =zX=zXux WQo"7~f܂`IҷHuM*Um:EfnM]]8HH1g曙ofLd&DA7GI+[2NR\ ELŏLJes2l)Ւ4<rA-2 Pc.xǐ6¤z }D%'~!ƁWfbRDI=SWs@ #'vd"X +#S8 zfJeIhڤܤ E-$_%'-\29LH52 {a֗a2Jpt)П4FaOw~˵E$S͝GKY쮤-# P^5m4#zBxJΘ9}[7wfP \jni}J\kWG:IqL{mk).Z| =mn_mF>0.pJp{q`GI*pݓ !X/u;Կcv?15EVY"eʇ!H}nfs}p-;Xqds|(Fu}Բ+&'@(s5 ϟ =wbmU,LA:fW5 :aNpC;]qc@bS*7USݝpt]+!&_󚓝ZBѓVGkXټ9Ww]gDoeg ƚح,b @vJtՎP#n>=>n%-|@Ux|` :m7Pz9YqnU4k˛3k@jFyFG2LU mmFP%;p$끕^ ؛2/[/vM gaCŴ'QJ۩A!Qޭ5' +G6 $R _>)!JÉl\k,)ޮy?PK`.J(git/.git/hooks/prepare-commit-msg.sampleUT =zX=zXux uS]s0|&3M?,[;L) ig[T\Iɏ$9! =e˥ԥ&$ Sz {a|PJzP:'Z,{)ZMb$}QZLύTJx #cQ<%ƀ1Foh#hVX̻4!H& U*G!K3F_h 8/rAbiǺ^Ω8(,Fb%`DWe$0lp u2qlupށh)4Q8Av#{J,+V!bl<-#4Gl>%6fܙO6mc=BV͠ӳ0X)Ω3i46vpq!mfQVcMp*%u 𸕕DTŕX!%B_Kqg"l!jX%H7ͧ92dt~@'rp6>.xNf-3(sCY (oP@Sz38= ;=҄‡>xMHlpk%*2'٫41NTA~!,|]|zw9i㨙,Aq8-_dt㲟Zz%)Qx:zDv~˓PK`.Jz" git/.git/hooks/pre-rebase.sampleUT =zX=zXux XkoF,[E>۸AndıGPbMr3(jsg"-+b﹏ѓofU$zBl4G4?<~NL9, Q*G{ԯhFi-et]ﵱ Zf"cKpZI Ţ$(KKcU<ժ`%xh!)|,̦R?V,f1(y.G*՚%TBBZ358ԕZ3ih- x&Ma0,(|fۄJ,*J1wZqԘ {(ZWjmĚj㢪,<0ɮ% &(^B5xJ4(.ǰ7aBZy"S疲A U" z`Uz3섵F,+>QDO'429wNZfd3̍l0z̦X<~~yvqCwwQ@t % $H+H+b94c(G*@SK#{H7@% w6U{R)@A6/KOSq\e乫 .` 俭ww+EϿS5JfSE,|ݳ&u5h<물>[H( ͉*%!'ۚt<|  뙸sZe>r[oBclvkj+H-QfKv0;HOJFFmXw2\3Npg9=A7:vpưHwn5ҫz2 ۛĪI"$%[F(ר'0v/ ` ެ6J&؄rA,goqx^%GiCQƳStg~3c Qqzw$ۈfLbr<ݓg8wt^a|(sYp+rGpt4{Wj4r7 tN#Jr^J˷o]L#>5 BmwM?7Moί_Pv;\B'f<^ 4D cMߦcɔX(RF0.xzp?"zJoXN^AW,_EeI"|(3. J2-c6 Hdes=Kz}7F W1@ +V&S,Sң~Qg(ve@f+_ gu%q+ 6D0YBQ73'/`KVg.1Bo\ /$:RVn2Ç7=7,. 0xx%%FyXc+]zz@Y~r:UVFmY7 T/Dc&r?Roy"'e-k-@?^F^]^_z;o`+o~ņc O[`Tk{x4tJh;HE`?(%lغʒ-|:Vhwq.A_WI% ˗ݢM;f `9 S\$HyJ*F $Cql;H'Nh8ZT]@wmm8|Ra]/`L/zxgq{ @f;>$k.օ53Wco{!nZ;!aW ʹyt 1W2_!w8^yVӆ2r zQ/c6k]^γ=4!m)goyKp&? t3ș6͜1\ ?w紇Mķ3W/ )>ɇBo=p'K,Z,eKEUu3H>h_SD*{Lq{ u?6&~%~c&V5ߟPKT.J7"Fgit/.git/configUT PAzXPAzXux =A 0ur{I$wsL@j;fY ʝp ('w#&Tn3οP3cN$ں4)v8uO_Y ~2PK`.J7?Igit/.git/descriptionUT =zX=zXux  KMMQ(J-/,/VHM,Q(,VHIUPOI-N.,(SW(Wʧ"iPK W.Jgit/.git/logs/UT UAzXUAzXux PKY.JzxBgit/.git/logs/HEADUT YAzXUAzXux ;0kr-A:u!z! HV .L .\ }C2XA g+QApL5 3PawC1)龝y4chQ TJaniN&oFfJ*kX:4B2sڰ&o8.)TSѼPK W.Jgit/.git/logs/refs/UT UAzXUAzXux PK W.Jgit/.git/logs/refs/heads/UT UAzXUAzXux PKY.JzxBgit/.git/logs/refs/heads/masterUT YAzXUAzXux ;0kr-A:u!z! HV .L .\ }C2XA g+QApL5 3PawC1)龝y4chQ TJaniN&oFfJ*kX:4B2sڰ&o8.)TSѼPK `.J+is git/.git/HEADUT =zX=zXux ref: refs/heads/master PKY.Jڅ{git/.git/indexUT YAzXYAzXux s rf```b*M|whV{c000`F1AKb=po盽,qn` πO?jCT}4{kݚʣnz<5Q?I?9aPs6v9)̱fR>,\ -?`½s IGd\1K$2&T\z8OWmj'ԢĢJ,=!A@*\kgWg {xs\W;j` ɻrs1OiNi~"`  OLf0T0Rl:í+^.Mm~q'+eE*k_V*PK `.Jgit/.git/branches/UT =zX=zXux PK `.Jgit/.git/refs/UT =zX=zXux PK `.Jgit/.git/refs/tags/UT =zX=zXux PK Y.Jgit/.git/refs/heads/UT YAzX=zXux PK Y.JY))git/.git/refs/heads/masterUT YAzXYAzXux 68636ba53c0af48b81340540deb025822c8a5843 PK Y.J"Cgit/.git/COMMIT_EDITMSGUT YAzXUAzXux add hierarchy PK `.Jgit/.git/info/UT =zX=zXux PK`.Jw=!git/.git/info/excludeUT =zX=zXux -A 0Dbv/\yq۟6؍g7Ǽ hc)iX& kOo@.miuk6p72)AȄgKlK s7Qq=ZƏȜ< uY^1+ >bN8Z#Eù깆PK W.Jgit/.git/rr-cache/UT UAzXUAzXux PK Y.Jgit/.git/objects/UT YAzX=zXux PK X.Jgit/.git/objects/11/UT WAzXWAzXux PK X.JP4:git/.git/objects/11/0eb5a45dc2e0464f870e9ba3fe02e034896a17UT WAzXWAzXux x=J@]S\J ]X-.PJՅ\2C3Ý X͝/Jַ0Y\Q' #+}[(kL4jO2q4tʁHx#; UYW 0egZxnwlyGc[UzCb䢦؄}! gh.D{ƠO@6-`^*QxisƄ$qcGJ_PK X.Jgit/.git/objects/a5/UT WAzXWAzXux PK X.Jc'X:git/.git/objects/a5/1ca34cde8238dd99ac22001b1f9f3090dece5fUT WAzXWAzXux xKOR04epIUHRS(/S PK X.Jgit/.git/objects/e6/UT WAzXWAzXux PK X.J:git/.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391UT WAzXWAzXux xKOR0` PK `.Jgit/.git/objects/pack/UT =zX=zXux PK .Jgit/.git/objects/4b/UT @zX@zXux PK .J: :git/.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904UT @zX@zXux x+)JMU0` ,PK X.Jgit/.git/objects/30/UT WAzXWAzXux PK X.JWtu:git/.git/objects/30/e02be1a85ca418689078d43ae19e2d26b7ab42UT WAzXWAzXux x]N0ǽSGLй3偞ACi2OoDzTTZ'In}'0) H_$c3TLZE:_a6Y}}E:h:VKos#NcI)1HqPR)0V܂ .qYidOT"M~r[<{"fTbHSԅ%ت A&jQo_]AV*R <4tsyPK Y.Jgit/.git/objects/2a/UT YAzXYAzXux PK Y.J[..:git/.git/objects/2a/26db49a6962700da5bd4084ae0e5a22d6583eeUT YAzXYAzXux x+)JMU0d040031QHax6M9{wk+qIOD&PK Y.Jgit/.git/objects/6e/UT YAzXYAzXux PK Y.J++:git/.git/objects/6e/d4c082894affb09de26ff4679e444e1c376483UT YAzXYAzXux x+)JMU0`01$:O$l1a1cB PK Y.Jgit/.git/objects/93/UT YAzXYAzXux PK Y.JTp+:git/.git/objects/93/f3e6d4c33c7d336913484b08d11d7f26c5382cUT YAzXYAzXux x+)JMU04`040031Qpq v cۺ$7vً1=071D+:o(K<?fI Kek;s| C%}4{kݚʣnz<*ZXQTP`@ኘ%*X=}EPK W.Jgit/.git/objects/cf/UT UAzXUAzXux PK W.J8:git/.git/objects/cf/3d5641dfc957f7efd3eb04931cae565ef61917UT UAzXUAzXux x 1@Qϩb Îw$;Cfc%XxK~3$FK˚8BEN,K7&:eҟۮ8Lv|:kMmǷ0|YWY=FPK `.Jgit/.git/objects/info/UT =zX=zXux PK Y.Jgit/.git/objects/68/UT YAzXWAzXux PK Y.J~?i:git/.git/objects/68/636ba53c0af48b81340540deb025822c8a5843UT YAzXYAzXux xMJ1 ]?fҟ)IRy#͝h߯c&/pGr3fg$O0؋gR /6a`l+8.!%PmǔɎ5UwVGޠO:]_C9hwvPS:= ڨjrAVS # l`LijR֧5x٦vԱ:D4x붧ԠiW+I@ĕ~~PK .JyEgit/bUT @zX@zXux File b in root PK .Jgit/cUT @zX@zXux PK .JAgit/UT@zXux PK.J>git/DESCRIPTIONUT@zXux PK .JAcgit/a/UT@zXux PK .JAgit/a/b/UT@zXux PK .J git/a/b/aUT@zXux PK .J %J (git/a/b/bUT@zXux PK .J Argit/a/b/c/UT@zXux PK .J git/a/b/c/dUT@zXux PK Y.J Agit/.git/UTZAzXux PK `.JA>git/.git/hooks/UT=zXux PK`.JO $git/.git/hooks/applypatch-msg.sampleUT=zXux PK`.JL $git/.git/hooks/pre-applypatch.sampleUT=zXux PK`.J !cgit/.git/hooks/post-update.sampleUT=zXux PK`.J؏DHgit/.git/hooks/pre-push.sampleUT=zXux PK`.J%0\j = git/.git/hooks/pre-commit.sampleUT=zXux PK`.J :git/.git/hooks/commit-msg.sampleUT=zXux PK`.JI !git/.git/hooks/pre-receive.sampleUT=zXux PK`.J!D%u/git/.git/hooks/update.sampleUT=zXux PK`.J(git/.git/hooks/prepare-commit-msg.sampleUT=zXux PK`.Jz" git/.git/hooks/pre-rebase.sampleUT=zXux PKT.J7"F,"git/.git/configUTPAzXux PK`.J7?I"git/.git/descriptionUT=zXux PK W.JA#git/.git/logs/UTUAzXux PKY.JzxB#git/.git/logs/HEADUTYAzXux PK W.JA$git/.git/logs/refs/UTUAzXux PK W.JA %git/.git/logs/refs/heads/UTUAzXux PKY.JzxB\%git/.git/logs/refs/heads/masterUTYAzXux PK `.J+is \&git/.git/HEADUT=zXux PKY.Jڅ{&git/.git/indexUTYAzXux PK `.JA}(git/.git/branches/UT=zXux PK `.JA(git/.git/refs/UT=zXux PK `.JA)git/.git/refs/tags/UT=zXux PK Y.JA^)git/.git/refs/heads/UTYAzXux PK Y.JY)))git/.git/refs/heads/masterUTYAzXux PK Y.J"C)*git/.git/COMMIT_EDITMSGUTYAzXux PK `.JA*git/.git/info/UT=zXux PK`.Jw=!*git/.git/info/excludeUT=zXux PK W.JA+git/.git/rr-cache/UTUAzXux PK Y.JA,git/.git/objects/UTYAzXux PK X.JAc,git/.git/objects/11/UTWAzXux PK X.JP4:$,git/.git/objects/11/0eb5a45dc2e0464f870e9ba3fe02e034896a17UTWAzXux PK X.JA.git/.git/objects/a5/UTWAzXux PK X.Jc'X:$].git/.git/objects/a5/1ca34cde8238dd99ac22001b1f9f3090dece5fUTWAzXux PK X.JA.git/.git/objects/e6/UTWAzXux PK X.J:$>/git/.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391UTWAzXux PK `.JA/git/.git/objects/pack/UT=zXux PK .JA0git/.git/objects/4b/UT@zXux PK .J: :$_0git/.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904UT@zXux PK X.JA0git/.git/objects/30/UTWAzXux PK X.JWtu:$01git/.git/objects/30/e02be1a85ca418689078d43ae19e2d26b7ab42UTWAzXux PK Y.JA2git/.git/objects/2a/UTYAzXux PK Y.J[..:$3git/.git/objects/2a/26db49a6962700da5bd4084ae0e5a22d6583eeUTYAzXux PK Y.JA3git/.git/objects/6e/UTYAzXux PK Y.J++:$3git/.git/objects/6e/d4c082894affb09de26ff4679e444e1c376483UTYAzXux PK Y.JA4git/.git/objects/93/UTYAzXux PK Y.JTp+:$4git/.git/objects/93/f3e6d4c33c7d336913484b08d11d7f26c5382cUTYAzXux PK W.JA6git/.git/objects/cf/UTUAzXux PK W.J8:$P6git/.git/objects/cf/3d5641dfc957f7efd3eb04931cae565ef61917UTUAzXux PK `.JAJ7git/.git/objects/info/UT=zXux PK Y.JA7git/.git/objects/68/UTYAzXux PK Y.J~?i:$7git/.git/objects/68/636ba53c0af48b81340540deb025822c8a5843UTYAzXux PK X.JE: :$9git/.git/objects/68/21c186de959771d06bbd41d5fe9d4271ee675dUTWAzXux PK Y.JA9git/.git/objects/7e/UTYAzXux PK Y.Jcc:$9git/.git/objects/7e/29db8b3b97c863c3b6533890a3015231cddf61UTYAzXux PK Y.J:git/.git/MERGE_RRUTYAzXux PK.Jas [aut, cre]") Description: What the package does (one paragraph) Depends: R (>= 3.2.0) License: GPL-3 LazyData: true Encoding: UTF-8 rprojroot/tests/testthat/hierarchy/b0000644000175100001440000000001712532326106017452 0ustar hornikusersFile b in root rprojroot/NAMESPACE0000644000175100001440000000156013037121233013544 0ustar hornikusers# Generated by roxygen2: do not edit by hand S3method("|",root_criterion) S3method(as.root_criterion,character) S3method(as.root_criterion,default) S3method(as.root_criterion,root_criterion) S3method(format,root_criterion) S3method(print,root_criterion) S3method(str,root_criteria) export(as.root_criterion) export(criteria) export(find_package_root_file) export(find_remake_root_file) export(find_root) export(find_root_file) export(find_rstudio_root_file) export(find_testthat_root_file) export(from_wd) export(get_root_desc) export(has_dir) export(has_dirname) export(has_file) export(has_file_pattern) export(is.root_criterion) export(is_git_root) export(is_projectile_project) export(is_r_package) export(is_remake_project) export(is_rstudio_project) export(is_svn_root) export(is_testthat) export(is_vcs_root) export(root_criterion) import(backports) importFrom(utils,str) rprojroot/NEWS.md0000644000175100001440000000432613037125011013424 0ustar hornikusers# rprojroot 1.2 (2017-01-15) - New root criteria - `is_projectile_project` recognize projectile projects (#21). - `has_dir()` constructs root criteria that check for existence of a directory. - `is_git_root`, `is_svn_root` and `is_vcs_root` look for a version control system root (#19). - New function - `get_root_desc()` returns the description of the criterion that applies to a given root, useful for composite criteria created with `|`. - Minor enhancements - Improve formatting of alternative criteria (#18). - If root cannot be found, the start path is shown in the error message. - Internal - The `$testfun` member of the `rprojroot` S3 class is now a list of functions instead of a function. # rprojroot 1.1 (2016-10-29) - Compatibility - Compatible with R >= 3.0.0 with the help of the `backports` package. - New root criteria - `is_remake_project` and `find_remake_root_file()` look for [remake](https://github.com/richfitz/remake) project (#17). - `is_testthat` and `find_testthat_root_file()` that looks for `tests/testthat` root (#14). - `from_wd`, useful for creating accessors to a known path (#11). - Minor enhancement - Criteria can be combined with the `|` operator (#15). - Documentation - Add package documentation with a few examples (#13). - Clarify difference between `find_file()` and `make_fix_file()` in vignette (#9). - Remove unexported functions from documentation and examples (#10). - Use `pkgdown` to create website. - Testing - Use Travis instead of wercker. Travis tests three R versions, and OS X. - Improve AppVeyor testing. # rprojroot 1.0-2 (2016-03-28) - Fix test that fails on Windows only on CRAN. # rprojroot 1.0 (2016-03-26) Initial CRAN release. - S3 class `root_criterion`: - Member functions: `find_file()` and `make_fix_file()` - `root_criterion()` - `as.root_criterion()` - `is.root_criterion()` - `has_file()` - `has_file_pattern()` - Built-in criteria: - `is_r_package` - `is_rstudio_project` - Getting started: - `find_package_root_file()` - `find_rstudio_root_file()` - Use a custom notion of a project root: - `find_root()` - `find_root_file()` - Vignette rprojroot/R/0000755000175100001440000000000013037124543012533 5ustar hornikusersrprojroot/R/has-file.R0000644000175100001440000001307613037126274014360 0ustar hornikusersformat_lines <- function(n) { if (n == 1) "line" else paste0(n, " lines") } #' @details #' The `has_file` function constructs a criterion that checks for the #' existence of a specific file (which itself can be in a subdirectory of the #' root) with specific contents. #' #' @rdname root_criterion #' @param filepath File path (can contain directories) #' @param contents Regular expression to match the file contents #' @inheritParams base::readLines #' @export has_file <- function(filepath, contents = NULL, n = -1L) { force(filepath) force(contents) force(n) testfun <- eval(bquote(function(path) { testfile <- file.path(path, .(filepath)) if (!file.exists(testfile)) return(FALSE) if (is_dir(testfile)) return(FALSE) match_contents(testfile, .(contents), .(n)) })) desc <- paste0( "contains a file `", filepath, "`", if (!is.null(contents)) { paste0(" with contents matching `", contents, "`", if (n >= 0L) paste0(" in the first ", format_lines(n))) }) root_criterion(testfun, desc) } #' @details #' The `has_dir` function constructs a criterion that checks for the #' existence of a specific directory. #' #' @rdname root_criterion #' @export has_dir <- function(filepath) { force(filepath) testfun <- eval(bquote(function(path) { testfile <- file.path(path, .(filepath)) if (!file.exists(testfile)) return(FALSE) is_dir(testfile) })) desc <- paste0("contains a directory `", filepath, "`") root_criterion(testfun, desc) } #' @details #' The `has_file_pattern` function constructs a criterion that checks for the #' existence of a file that matches a pattern, with specific contents. #' #' @rdname root_criterion #' @param pattern Regular expression to match the file name #' @inheritParams base::readLines #' @export has_file_pattern <- function(pattern, contents = NULL, n = -1L) { force(pattern) force(contents) force(n) testfun <- eval(bquote(function(path) { files <- list_files(path, .(pattern)) for (f in files) { if (!match_contents(f, .(contents), .(n))) { next } return(TRUE) } return(FALSE) })) desc <- paste0( "contains a file matching `", pattern, "`", if (!is.null(contents)) { paste0(" with contents matching `", contents, "`", if (n >= 0L) paste0(" in the first ", format_lines(n))) }) root_criterion(testfun, desc) } #' @details #' The `has_dirname` function constructs a criterion that checks if the #' [base::dirname()] has a specific name. #' #' @rdname root_criterion #' @param dirname A directory name, without subdirectories #' @export has_dirname <- function(dirname, subdir = NULL) { force(dirname) testfun <- eval(bquote(function(path) { dir.exists(file.path(dirname(path), .(dirname))) })) desc <- paste0("directory name is `", dirname, "`") root_criterion(testfun, desc, subdir = subdir) } #' @export is_rstudio_project <- has_file_pattern("[.]Rproj$", contents = "^Version: ", n = 1L) #' @export is_r_package <- has_file("DESCRIPTION", contents = "^Package: ") #' @export is_remake_project <- has_file("remake.yml") #' @export is_projectile_project <- has_file(".projectile") #' @export is_git_root <- has_dir(".git") #' @export is_svn_root <- has_dir(".svn") #' @export is_vcs_root <- is_git_root | is_svn_root #' @export is_testthat <- has_dirname("testthat", c("tests/testthat", "testthat")) #' @export from_wd <- root_criterion(function(path) TRUE, "from current working directory") #' Prespecified criteria #' #' This is a collection of commonly used root criteria. #' #' @export criteria <- structure( list( is_rstudio_project = is_rstudio_project, is_r_package = is_r_package, is_remake_project = is_remake_project, is_projectile_project = is_projectile_project, is_git_root = is_git_root, is_svn_root = is_svn_root, is_vcs_root = is_vcs_root, is_testthat = is_testthat, from_wd = from_wd ), class = "root_criteria") #' @export #' @importFrom utils str str.root_criteria <- function(object, ...) { str(lapply(object, format)) } #' @details #' `is_rstudio_project` looks for a file with extension `.Rproj`. #' #' @rdname criteria #' @export "is_rstudio_project" #' @details #' `is_r_package` looks for a `DESCRIPTION` file. #' #' @rdname criteria #' @export "is_r_package" #' @details #' `is_remake_project` looks for a `remake.yml` file. #' #' @rdname criteria #' @export "is_remake_project" #' @details #' `is_projectile_project` looks for a `.projectile` file. #' #' @rdname criteria #' @export "is_projectile_project" #' @details #' `is_git_project` looks for a `.git` directory. #' #' @rdname criteria #' @export "is_git_root" #' @details #' `is_svn_project` looks for a `.svn` directory. #' #' @rdname criteria #' @export "is_svn_root" #' @details #' `is_vcs_project` looks for the root of a version control #' system, currently only Git and SVN are supported. #' #' @rdname criteria #' @export "is_vcs_root" #' @details #' `is_testthat` looks for the `testthat` directory, works when #' developing, testing, and checking a package. #' #' @rdname criteria #' @export "is_testthat" #' @details #' `from_wd` uses the current working directory. #' #' @rdname criteria #' @export "from_wd" list_files <- function(path, filename) { files <- dir(path = path, pattern = filename, all.files = TRUE, full.names = TRUE) dirs <- is_dir(files) files <- files[!dirs] files } is_dir <- function(x) { dir.exists(x) } match_contents <- function(f, contents, n) { if (is.null(contents)) { return(TRUE) } fc <- readLines(f, n) any(grepl(contents, fc)) } rprojroot/R/shortcut.R0000644000175100001440000000054513037124543014535 0ustar hornikusers#' @rdname find_root_file #' @export find_rstudio_root_file <- is_rstudio_project$find_file #' @rdname find_root_file #' @export find_package_root_file <- is_r_package$find_file #' @rdname find_root_file #' @export find_remake_root_file <- is_remake_project$find_file #' @rdname find_root_file #' @export find_testthat_root_file <- is_testthat$find_file rprojroot/R/file.R0000644000175100001440000000211313037124543013572 0ustar hornikusers#' File paths relative to the root of a directory hierarchy #' #' Append an arbitrary number of path components to the root using #' [base::file.path()]. #' #' The `find_root_file` function is a simple wrapper around #' [find_root()] that #' appends an arbitrary number of path components to the root using #' [base::file.path()]. #' #' @param criterion A criterion, will be coerced using #' [as.root_criterion()] #' @param path The start directory #' @param ... Further path components passed to [file.path()] #' @return The normalized path of the root as specified by the search criteria, #' with the additional path components appended. #' Throws an error if no root is found #' #' @examples #' \dontrun{ #' find_package_root_file("tests", "testthat.R") #' has_file("DESCRIPTION", "^Package: ")$find_file #' has_file("DESCRIPTION", "^Package: ")$make_fix_file(".") #' } #' #' @seealso [find_root()] [utils::glob2rx()] [base::file.path()] #' #' @export find_root_file <- function(..., criterion, path = ".") { root <- find_root(criterion = criterion, path = path) file.path(root, ...) } rprojroot/R/rprojroot-package.R0000644000175100001440000000055113037124543016310 0ustar hornikusers#' @details #' See the "Value" section in [root_criterion()] for documentation #' of root criterion objects, and [criteria()] for useful predefined #' root criteria. #' #' @examples #' criteria #' \dontrun{ #' is_r_package$find_file("NAMESPACE") #' root_fun <- is_r_package$make_fix_file() #' root_fun("NAMESPACE") #' } #' @import backports #' @api "_PACKAGE" rprojroot/R/root.R0000644000175100001440000000461113037124543013643 0ustar hornikusers#' Find the root of a directory hierarchy #' #' A \emph{root} is defined as a directory that contains a regular file #' whose name matches a given pattern and which optionally contains a given text. #' The search for a root starts at a given directory (the working directory #' by default), and proceeds up the directory hierarchy. #' #' Starting from the working directory, the `find_root` function searches #' for the root. #' If a root is found, the `...` arguments are used to construct a path; #' thus, if no extra arguments are given, the root is returned. #' If no root is found, an error is thrown. #' #' @inheritParams find_root_file #' @return The normalized path of the root as specified by the search criterion. #' Throws an error if no root is found #' #' @examples #' \dontrun{ #' find_root(glob2rx("DESCRIPTION"), "^Package: ") #' } #' #' @seealso [utils::glob2rx()] [file.path()] #' #' @export find_root <- function(criterion, path = ".") { criterion <- as.root_criterion(criterion) start_path <- get_start_path(path, criterion$subdir) path <- start_path for (i in seq_len(.MAX_DEPTH)) { for (f in criterion$testfun) { if (f(path)) { return(path) } } if (is_root(path)) { stop("No root directory found in ", start_path, " or its parent directories. ", paste(format(criterion), collapse = "\n"), call. = FALSE) } path <- dirname(path) } stop("Maximum search of ", .MAX_DEPTH, " exceeded. Last path: ", path) } .MAX_DEPTH <- 100L get_start_path <- function(path, subdirs) { path <- normalizePath(path, winslash = "/", mustWork = TRUE) for (subdir in subdirs) { subdir_path <- file.path(path, subdir) if (dir.exists(subdir_path)) { return(subdir_path) } } path } # Borrowed from devtools is_root <- function(path) { identical(normalizePath(path, winslash = "/"), normalizePath(dirname(path), winslash = "/")) } #' @rdname find_root #' @description `get_root_desc()` returns the description of the criterion #' for a root path. This is especially useful for composite root criteria #' created with [|.root_criterion()]. #' @export get_root_desc <- function(criterion, path) { for (i in seq_along(criterion$testfun)) { if (criterion$testfun[[i]](path)) { return(criterion$desc[[i]]) } } stop("path is not a root. ", paste(format(criterion), collapse = "\n"), call. = FALSE) } rprojroot/R/criterion.R0000644000175100001440000001007113037124556014657 0ustar hornikusers#' Is a directory the project root? #' #' Objects of the `root_criterion` class decide if a #' given directory is a project root. #' #' Construct criteria using `root_criterion` in a very general fashion #' by specifying a function with a `path` argument, and a description. #' #' @param testfun A function with one parameter that returns `TRUE` #' if the directory specified by this parameter is the project root, #' and `FALSE` otherwise. Can also be a list of such functions. #' @param desc A textual description of the test criterion, of the same length #' as `testfun` #' @param subdir Subdirectories to start the search in, if found #' #' @return #' An S3 object of class `root_criterion` wit the following members: #' #' @include rrmake.R #' @export #' #' @examples #' root_criterion(function(path) file.exists(file.path(path, "somefile")), "has somefile") #' has_file("DESCRIPTION") #' is_r_package #' is_r_package$find_file #' \dontrun{ #' is_r_package$make_fix_file(".") #' } root_criterion <- function(testfun, desc, subdir = NULL) { testfun <- check_testfun(testfun) stopifnot(length(desc) == length(testfun)) full_desc <- paste0( desc, if (!is.null(subdir)) paste0( " (also look in subdirectories: ", paste0("`", subdir, "`", collapse = ", "), ")" ) ) criterion <- structure( list( #' @return #' \describe{ #' \item{`testfun`}{The `testfun` argument} testfun = testfun, #' \item{`desc`}{The `desc` argument} desc = full_desc, #' \item{`subdir`}{The `subdir` argument} subdir = subdir ), class = "root_criterion" ) #' \item{`find_file`}{A function with `...` argument that returns #' for a path relative to the root specified by this criterion. #' The optional `path` argument specifies the starting directory, #' which defaults to `"."`. #' } criterion$find_file <- make_find_root_file(criterion) #' \item{`make_fix_file`}{A function with a `path` argument that #' returns a function that finds paths relative to the root. For a #' criterion `cr`, the result of `cr$make_fix_file(".")(...)` #' is identical to `cr$find_file(...)`. The function created by #' `make_fix_file` can be saved to a variable to be more independent #' of the current working directory. #' } #' } criterion$make_fix_file <- function(path = getwd()) make_fix_root_file(criterion, path) criterion } check_testfun <- function(testfun) { if (is.function(testfun)) { testfun <- list(testfun) } for (f in testfun) { if (!isTRUE(all.equal(names(formals(f)), "path"))) { stop("All functions in testfun must have exactly one argument 'path'") } } testfun } #' @rdname root_criterion #' @param x An object #' @export is.root_criterion <- function(x) { inherits(x, "root_criterion") } #' @rdname root_criterion #' @export as.root_criterion <- function(x) UseMethod("as.root_criterion", x) #' @details #' The `as.root_criterion` function accepts objects of class #' `root_criterion`, and character values; the latter will be #' converted to criteria using `has_file`. #' #' @rdname root_criterion #' @export as.root_criterion.character <- function(x) { has_file(x) } #' @rdname root_criterion #' @export as.root_criterion.root_criterion <- identity #' @export as.root_criterion.default <- function(x) { stop("Cannot coerce ", x, " to type root_criterion.") } #' @export format.root_criterion <- function(x, ...) { if (length(x$desc) > 1) { c("Root criterion: one of", paste0("- ", x$desc)) } else { paste0("Root criterion: ", x$desc) } } #' @export print.root_criterion <- function(x, ...) { cat(format(x), sep = "\n") invisible(x) } #' @export #' @rdname root_criterion #' @details Root criteria can be combined with the `|` operator. The result is a #' composite root criterion that requires either of the original criteria to #' match. #' @param y An object `|.root_criterion` <- function(x, y) { stopifnot(is.root_criterion(y)) root_criterion( c(x$testfun, y$testfun), c(x$desc, y$desc) ) } rprojroot/R/rrmake.R0000644000175100001440000000053313037124543014140 0ustar hornikusersmake_find_root_file <- function(criterion) { force(criterion) eval(bquote(function(..., path = ".") { find_root_file(..., criterion = criterion, path = path) })) } make_fix_root_file <- function(criterion, path) { root <- find_root(criterion = criterion, path = path) eval(bquote(function(...) { file.path(.(root), ...) })) } rprojroot/vignettes/0000755000175100001440000000000013037131577014347 5ustar hornikusersrprojroot/vignettes/rprojroot.Rmd0000644000175100001440000002052013003223251017032 0ustar hornikusers--- title: "Finding files in project subdirectories" author: "Kirill Müller" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Finding files in project subdirectories} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- The `rprojroot` package solves a seemingly trivial but annoying problem that occurs sooner or later in any largish project: How to find files in subdirectories? Ideally, file paths are relative to the *project root*. Unfortunately, we cannot always be sure about the current working directory: For instance, in RStudio it's sometimes: - the project root (when running R scripts), - a subdirectory (when building vignettes), - again the project root (when executing chunks of a vignette). ```{r} basename(getwd()) ``` In some cases, it's even outside the project root. This vignette starts with a very brief summary that helps you get started, followed by a longer description of the features. ## TL;DR What is your project: An R package? ```{r} rprojroot::is_r_package ``` Or an RStudio project? ```{r} rprojroot::is_rstudio_project ``` Or something else? ```{r} rprojroot::has_file(".git/index") ``` For now, we assume it's an R package: ```{r} root <- rprojroot::is_r_package ``` The `root` object contains a function that helps locating files below the root of your package, regardless of your current working directory. If you are sure that your working directory is somewhere below your project's root, use the `root$find_file()` function: ```{r} readLines(root$find_file("DESCRIPTION"), 3) ``` You can also construct an accessor to your root using the `root$make_fix_file()` function: ```{r} root_file <- root$make_fix_file() ``` Note that `root_file()` is a *function* that works just like `$find_file()` but will find the files even if the current working directory is outside your project: ```{r} withr::with_dir( "../..", readLines(root_file("DESCRIPTION"), 3) ) ``` If you know the absolute path of some directory below your project, but cannot be sure of your current working directory, pass that absolute path to `root$make_fix_file()`: ```r root_file <- root$make_fix_file("C:\\Users\\User Name\\...") ``` Get the path of standalone R scripts or vignettes using the `thisfile()` function in the `kimisc` package: ```r root_file <- root$make_fix_file(dirname(kimisc::thisfile())) ``` The remainder of this vignette describes implementation details and advanced features. ## Project root We assume a self-contained project where all files and directories are located below a common *root* directory. Also, there should be a way to unambiguously identify this root directory. (Often, the root contains a regular file whose name matches a given pattern, and/or whose contents match another pattern.) In this case, the following method reliably finds our project root: - Start the search in any subdirectory of our project - Proceed up the directory hierarchy until the root directory has been identified The Git version control system (and probably many other tools) use a similar approach: A Git command can be executed from within any subdirectory of a repository. ### A simple example The `find_root()` function implements the core functionality. It returns the path to the first directory that matches the filtering criteria, or throws an error if there is no such directory. Filtering criteria are constructed in a generic fashion using the `root_criterion()` function, the `has_file()` function constructs a criterion that checks for the presence of a file with a specific name and specific contents. ```{r} library(rprojroot) # List all files and directories below the root dir(find_root(has_file("DESCRIPTION"))) # Find a file relative to the root file.exists(find_root_file("R", "root.R", criterion = has_file("DESCRIPTION"))) ``` Note that the following code produces identical results when building the vignette *and* when sourcing the chunk in RStudio, provided that the current working directory is the project root or anywhere below. ### Criteria The `has_file()` function (and the more general `root_criterion()`) both return an S3 object of class `root_criterion`: ```{r} has_file("DESCRIPTION") ``` In addition, character values are coerced to `has_file` criteria by default, this coercion is applied automatically by `find_root()`. (This feature is used by the introductory example.) ```{r} as.root_criterion("DESCRIPTION") ``` The return value of these functions can be stored and reused; in fact, the package provides `r length(criteria)` such criteria: ```{r} criteria ``` Defining new criteria is easy: ```{r} has_license <- has_file("LICENSE") has_license is_projecttemplate_project <- has_file("config/global.dcf", "^version: ") is_projecttemplate_project ``` You can also combine criteria via the `|` operator: ```{r} is_r_package | is_rstudio_project ``` ### Shortcuts To avoid specifying the search criteria for the project root every time, shortcut functions can be created. The `find_package_root_file()` is a shortcut for `find_root_file(..., criterion = is_r_package)`: ```{r} # Print first lines of the source for this document head(readLines(find_package_root_file("vignettes", "rprojroot.Rmd"))) ``` To save typing effort, define a shorter alias: ```{r} P <- find_package_root_file # Use a shorter alias file.exists(P("vignettes", "rprojroot.Rmd")) ``` Each criterion actually contains a function that allows finding a file below the root specified by this criterion. As our project does not have a file named `LICENSE`, querying the root results in an error: ```{r error = TRUE} # Use the has_license criterion to find the root R <- has_license$find_file R # Our package does not have a LICENSE file, trying to find the root results in an error R() ``` ### Fixed root We can also create a function that computes a path relative to the root *at creation time*. ```{r} # Define a function that computes file paths below the current root F <- is_r_package$make_fix_file() F # Show contents of the NAMESPACE file in our project readLines(F("NAMESPACE")) ``` This is a more robust alternative to `$find_file()`, because it *fixes* the project directory when `$make_fix_file()` is called, instead of searching for it every time. (For that reason it is also slightly faster, but I doubt this matters in practice.) This function can be used even if we later change the working directory to somewhere outside the project: ```{r} # Print the size of the namespace file, working directory outside the project withr::with_dir( "../..", file.size(F("NAMESPACE")) ) ``` The `make_fix_file()` member function also accepts an optional `path` argument, in case you know your project's root but the current working directory is somewhere outside. Take a look at the `thisfile()` function in the `kimisc` package for getting the path to the current script or `knitr` document. ## `testthat` files Tests run with [`testthat`](https://cran.r-project.org/package=testthat) commonly use files that live below the `tests/testthat` directory. Ideally, this should work in the following situation: - During package development (working directory: package root) - When testing with `devtools::test()` (working directory: `tests/testthat`) - When running `R CMD check` (working directory: a renamed recursive copy of `tests`) The `is_testthat` criterion allows robust lookup of test files. ```{r} is_testthat ``` The example code below lists all files in the [hierarchy](https://github.com/krlmlr/rprojroot/tree/master/tests/testthat/hierarchy) test directory. It uses two project root lookups in total, so that it also works when rendering the vignette (*sigh*): ```{r} dir(is_testthat$find_file("hierarchy", path = is_r_package$find_file())) ``` ## Summary The `rprojroot` package allows easy access to files below a project root if the project root can be identified easily, e.g. if it is the only directory in the whole hierarchy that contains a specific file. This is a robust solution for finding files in largish projects with a subdirectory hierarchy if the current working directory cannot be assumed fixed. (However, at least initially, the current working directory must be somewhere below the project root.) ## Acknowledgement This package was inspired by the gist ["Stop the working directory insanity"](https://gist.github.com/jennybc/362f52446fe1ebc4c49f) by Jennifer Bryan, and by the way Git knows where its files are. rprojroot/MD50000644000175100001440000000424113037143624012644 0ustar hornikusers09fc8e111b014442f6569ac39cfff43f *DESCRIPTION 04765b617541cee07297676a210d25d3 *NAMESPACE 2d0469a219c83ed66c4e2695d4ff2d1c *NEWS.md da5b8d6d5d1ea8a0aa1c4a1cfed314ff *R/criterion.R 3283d4a6f17606ad0193bace804ed012 *R/file.R 1050ecdd048dce13bbf81615de85489f *R/has-file.R d87a8501549770bd80068475e78671fe *R/root.R 0688a81a507c7639e2b2cec0edad2dbf *R/rprojroot-package.R dd227290335dea57e2a1031a5b5beb35 *R/rrmake.R 4de9a9bbf48372e1505dd1550bee0418 *R/shortcut.R 0415d9530ea3a983814164d735e5db9e *build/vignette.rds 0634afa63b0e9c96760bcdce54655942 *inst/doc/rprojroot.R 7855fbb459b9e137bc458294b20db80c *inst/doc/rprojroot.Rmd 9e32800aeeef65fcddc218dcaa367682 *inst/doc/rprojroot.html 6a14df38876e8de0b3a24e689aa98cf7 *man/criteria.Rd df64533edc92ee73830a13070b418d54 *man/find_root.Rd 5accd629c3b4aa22c6a484b2a52ed0a2 *man/find_root_file.Rd 4a89be5e4f191328f2a7e8b6f31a8ba6 *man/root_criterion.Rd a7d033b76a25c7abfb137de00b3da294 *man/rprojroot-package.Rd 1d802d92f687ffbb11ee26ae68396d94 *tests/testthat.R 3e6320af0b5c1a4ab2bc220759c31553 *tests/testthat/hierarchy/DESCRIPTION d41d8cd98f00b204e9800998ecf8427e *tests/testthat/hierarchy/a/b/a b16de7308a1f8d6f4f98b1a558ea957d *tests/testthat/hierarchy/a/b/b d41d8cd98f00b204e9800998ecf8427e *tests/testthat/hierarchy/a/b/c/d d41d8cd98f00b204e9800998ecf8427e *tests/testthat/hierarchy/a/remake.yml 55e116ea754236d78e4e6342adbe3661 *tests/testthat/hierarchy/b d41d8cd98f00b204e9800998ecf8427e *tests/testthat/hierarchy/c 3936ed002c1dd1fa5dc7a13d99d5df86 *tests/testthat/hierarchy/hierarchy.Rproj d41d8cd98f00b204e9800998ecf8427e *tests/testthat/package/DESCRIPTION d41d8cd98f00b204e9800998ecf8427e *tests/testthat/package/tests/testthat.R d41d8cd98f00b204e9800998ecf8427e *tests/testthat/package/tests/testthat/test-something.R 06e74a052aa3a2ab9a51a5135802a55b *tests/testthat/test-criterion.R ce3ca96d5d38e1c0972d639a81f659c1 *tests/testthat/test-make.R 006eb32f50098d057c0a9cfb6ac4d0ba *tests/testthat/test-root.R ec33c4973b9fac9b680322d60d6807ac *tests/testthat/test-testthat.R d8879d25ee21b0f84992020d95500aaf *tests/testthat/vcs/git.zip 28e9555632b66c264d026cd065dda0db *tests/testthat/vcs/svn.zip 7855fbb459b9e137bc458294b20db80c *vignettes/rprojroot.Rmd rprojroot/build/0000755000175100001440000000000013037131577013436 5ustar hornikusersrprojroot/build/vignette.rds0000644000175100001440000000034113037131577015773 0ustar hornikusersmQ0  `Lxnx ŋ!":3ěO.av}m LL ) 7 +K)RъۈqXN+qTDLHF+"תD{>0@g<)&!-)'?h4rGﵐ=gw+S އQäh[:5o< 4`4O*]C~ srprojroot/DESCRIPTION0000644000175100001440000000202713037143624014042 0ustar hornikusersPackage: rprojroot Title: Finding Files in Project Subdirectories Version: 1.2 Authors@R: person(given = "Kirill", family = "Müller", role = c("aut", "cre"), email = "krlmlr+r@mailbox.org") Description: Robust, reliable and flexible paths to files below a project root. The 'root' of a project is defined as a directory that matches a certain criterion, e.g., it contains a certain regular file. Depends: R (>= 3.0.0) Imports: backports Suggests: testthat, knitr, withr, rmarkdown VignetteBuilder: knitr License: GPL-3 LazyData: true Encoding: UTF-8 URL: https://github.com/krlmlr/rprojroot, https://krlmlr.github.io/rprojroot BugReports: https://github.com/krlmlr/rprojroot/issues RoxygenNote: 5.0.1.9000 Collate: 'rrmake.R' 'criterion.R' 'file.R' 'has-file.R' 'root.R' 'rprojroot-package.R' 'shortcut.R' NeedsCompilation: no Packaged: 2017-01-16 11:50:23 UTC; muelleki Author: Kirill Müller [aut, cre] Maintainer: Kirill Müller Repository: CRAN Date/Publication: 2017-01-16 14:16:04 rprojroot/man/0000755000175100001440000000000013037121233013076 5ustar hornikusersrprojroot/man/find_root.Rd0000644000175100001440000000270513037121233015354 0ustar hornikusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/root.R \name{find_root} \alias{find_root} \alias{get_root_desc} \title{Find the root of a directory hierarchy} \usage{ find_root(criterion, path = ".") get_root_desc(criterion, path) } \arguments{ \item{criterion}{A criterion, will be coerced using \code{\link[=as.root_criterion]{as.root_criterion()}}} \item{path}{The start directory} } \value{ The normalized path of the root as specified by the search criterion. Throws an error if no root is found } \description{ A \emph{root} is defined as a directory that contains a regular file whose name matches a given pattern and which optionally contains a given text. The search for a root starts at a given directory (the working directory by default), and proceeds up the directory hierarchy. \code{get_root_desc()} returns the description of the criterion for a root path. This is especially useful for composite root criteria created with \code{\link[=|.root_criterion]{|.root_criterion()}}. } \details{ Starting from the working directory, the \code{find_root} function searches for the root. If a root is found, the \code{...} arguments are used to construct a path; thus, if no extra arguments are given, the root is returned. If no root is found, an error is thrown. } \examples{ \dontrun{ find_root(glob2rx("DESCRIPTION"), "^Package: ") } } \seealso{ \code{\link[utils:glob2rx]{utils::glob2rx()}} \code{\link[=file.path]{file.path()}} } rprojroot/man/find_root_file.Rd0000644000175100001440000000314013037121233016345 0ustar hornikusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/file.R, R/shortcut.R \name{find_root_file} \alias{find_root_file} \alias{find_rstudio_root_file} \alias{find_package_root_file} \alias{find_remake_root_file} \alias{find_testthat_root_file} \title{File paths relative to the root of a directory hierarchy} \usage{ find_root_file(..., criterion, path = ".") find_rstudio_root_file(..., path = ".") find_package_root_file(..., path = ".") find_remake_root_file(..., path = ".") find_testthat_root_file(..., path = ".") } \arguments{ \item{...}{Further path components passed to \code{\link[=file.path]{file.path()}}} \item{criterion}{A criterion, will be coerced using \code{\link[=as.root_criterion]{as.root_criterion()}}} \item{path}{The start directory} } \value{ The normalized path of the root as specified by the search criteria, with the additional path components appended. Throws an error if no root is found } \description{ Append an arbitrary number of path components to the root using \code{\link[base:file.path]{base::file.path()}}. } \details{ The \code{find_root_file} function is a simple wrapper around \code{\link[=find_root]{find_root()}} that appends an arbitrary number of path components to the root using \code{\link[base:file.path]{base::file.path()}}. } \examples{ \dontrun{ find_package_root_file("tests", "testthat.R") has_file("DESCRIPTION", "^Package: ")$find_file has_file("DESCRIPTION", "^Package: ")$make_fix_file(".") } } \seealso{ \code{\link[=find_root]{find_root()}} \code{\link[utils:glob2rx]{utils::glob2rx()}} \code{\link[base:file.path]{base::file.path()}} } rprojroot/man/criteria.Rd0000644000175100001440000000247713037121233015201 0ustar hornikusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/has-file.R \docType{data} \name{criteria} \alias{criteria} \alias{is_rstudio_project} \alias{is_r_package} \alias{is_remake_project} \alias{is_projectile_project} \alias{is_git_root} \alias{is_svn_root} \alias{is_vcs_root} \alias{is_testthat} \alias{from_wd} \title{Prespecified criteria} \format{An object of class \code{root_criteria} of length 9.} \usage{ criteria is_rstudio_project is_r_package is_remake_project is_projectile_project is_git_root is_svn_root is_vcs_root is_testthat from_wd } \description{ This is a collection of commonly used root criteria. } \details{ \code{is_rstudio_project} looks for a file with extension \code{.Rproj}. \code{is_r_package} looks for a \code{DESCRIPTION} file. \code{is_remake_project} looks for a \code{remake.yml} file. \code{is_projectile_project} looks for a \code{.projectile} file. \code{is_git_project} looks for a \code{.git} directory. \code{is_svn_project} looks for a \code{.svn} directory. \code{is_vcs_project} looks for the root of a version control system, currently only Git and SVN are supported. \code{is_testthat} looks for the \code{testthat} directory, works when developing, testing, and checking a package. \code{from_wd} uses the current working directory. } \keyword{datasets} rprojroot/man/root_criterion.Rd0000644000175100001440000000737313037121233016440 0ustar hornikusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/criterion.R, R/has-file.R \name{root_criterion} \alias{root_criterion} \alias{is.root_criterion} \alias{as.root_criterion} \alias{as.root_criterion.character} \alias{as.root_criterion.root_criterion} \alias{|.root_criterion} \alias{has_file} \alias{has_dir} \alias{has_file_pattern} \alias{has_dirname} \title{Is a directory the project root?} \usage{ root_criterion(testfun, desc, subdir = NULL) is.root_criterion(x) as.root_criterion(x) \method{as.root_criterion}{character}(x) \method{as.root_criterion}{root_criterion}(x) \method{|}{root_criterion}(x, y) has_file(filepath, contents = NULL, n = -1L) has_dir(filepath) has_file_pattern(pattern, contents = NULL, n = -1L) has_dirname(dirname, subdir = NULL) } \arguments{ \item{testfun}{A function with one parameter that returns \code{TRUE} if the directory specified by this parameter is the project root, and \code{FALSE} otherwise. Can also be a list of such functions.} \item{desc}{A textual description of the test criterion, of the same length as \code{testfun}} \item{subdir}{Subdirectories to start the search in, if found} \item{x}{An object} \item{y}{An object} \item{filepath}{File path (can contain directories)} \item{contents}{Regular expression to match the file contents} \item{n}{integer. The (maximal) number of lines to read. Negative values indicate that one should read up to the end of input on the connection.} \item{pattern}{Regular expression to match the file name} \item{dirname}{A directory name, without subdirectories} } \value{ An S3 object of class \code{root_criterion} wit the following members: \describe{ \item{\code{testfun}}{The \code{testfun} argument} \item{\code{desc}}{The \code{desc} argument} \item{\code{subdir}}{The \code{subdir} argument} \item{\code{find_file}}{A function with \code{...} argument that returns for a path relative to the root specified by this criterion. The optional \code{path} argument specifies the starting directory, which defaults to \code{"."}. } \item{\code{make_fix_file}}{A function with a \code{path} argument that returns a function that finds paths relative to the root. For a criterion \code{cr}, the result of \code{cr$make_fix_file(".")(...)} is identical to \code{cr$find_file(...)}. The function created by \code{make_fix_file} can be saved to a variable to be more independent of the current working directory. } } } \description{ Objects of the \code{root_criterion} class decide if a given directory is a project root. } \details{ Construct criteria using \code{root_criterion} in a very general fashion by specifying a function with a \code{path} argument, and a description. The \code{as.root_criterion} function accepts objects of class \code{root_criterion}, and character values; the latter will be converted to criteria using \code{has_file}. Root criteria can be combined with the \code{|} operator. The result is a composite root criterion that requires either of the original criteria to match. The \code{has_file} function constructs a criterion that checks for the existence of a specific file (which itself can be in a subdirectory of the root) with specific contents. The \code{has_dir} function constructs a criterion that checks for the existence of a specific directory. The \code{has_file_pattern} function constructs a criterion that checks for the existence of a file that matches a pattern, with specific contents. The \code{has_dirname} function constructs a criterion that checks if the \code{\link[base:dirname]{base::dirname()}} has a specific name. } \examples{ root_criterion(function(path) file.exists(file.path(path, "somefile")), "has somefile") has_file("DESCRIPTION") is_r_package is_r_package$find_file \dontrun{ is_r_package$make_fix_file(".") } } rprojroot/man/rprojroot-package.Rd0000644000175100001440000000207313037121233017020 0ustar hornikusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rprojroot-package.R \docType{package} \name{rprojroot-package} \alias{rprojroot} \alias{rprojroot-package} \title{rprojroot: Finding Files in Project Subdirectories} \description{ Robust, reliable and flexible paths to files below a project root. The 'root' of a project is defined as a directory that matches a certain criterion, e.g., it contains a certain regular file. } \details{ See the "Value" section in \code{\link[=root_criterion]{root_criterion()}} for documentation of root criterion objects, and \code{\link[=criteria]{criteria()}} for useful predefined root criteria. } \examples{ criteria \dontrun{ is_r_package$find_file("NAMESPACE") root_fun <- is_r_package$make_fix_file() root_fun("NAMESPACE") } } \seealso{ Useful links: \itemize{ \item \url{https://github.com/krlmlr/rprojroot} \item \url{https://krlmlr.github.io/rprojroot} \item Report bugs at \url{https://github.com/krlmlr/rprojroot/issues} } } \author{ \strong{Maintainer}: Kirill Müller \email{krlmlr+r@mailbox.org} }