Skip to content

Commit

Permalink
Merge branch 'r-1.2' into production
Browse files Browse the repository at this point in the history
  • Loading branch information
krlmlr committed Jan 25, 2017
2 parents d35f0dc + 40b57ed commit 662a7c1
Show file tree
Hide file tree
Showing 35 changed files with 750 additions and 171 deletions.
4 changes: 3 additions & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
^.*\.Rproj$
^rprojroot\.Rproj$
^\.Rproj\.user$
^\.gitignore$
^README\.md$
Expand All @@ -20,3 +20,5 @@
^_pkgdown\.yml$
^revdep$
^tic\.R$
^tests/testthat/hierarchy/a/b/\.projectile$
^API$
Binary file removed .deploy_key.enc
Binary file not shown.
10 changes: 0 additions & 10 deletions .deploy_key.pub

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ inst/doc
/docs/
/vignettes/*.html
/revdep/.cache.rds
.projectile
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Header
language: r
sudo: false
dist: trusty
cache: packages
warnings_are_errors: true

Expand Down
37 changes: 37 additions & 0 deletions API
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# API for rprojroot package

## Exported functions

as.root_criterion(x)
find_package_root_file(..., path = ".")
find_remake_root_file(..., path = ".")
find_root(criterion, path = ".")
find_root_file(..., criterion, path = ".")
find_rstudio_root_file(..., path = ".")
find_testthat_root_file(..., path = ".")
get_root_desc(criterion, path)
has_dir(filepath)
has_dirname(dirname, subdir = NULL)
has_file(filepath, contents = NULL, n = -1L)
has_file_pattern(pattern, contents = NULL, n = -1L)
is.root_criterion(x)
root_criterion(testfun, desc, subdir = NULL)

## S3 methods

as.root_criterion.character(x)
as.root_criterion.default(x)
as.root_criterion.root_criterion(x)

## Exported data

criteria: root_criteria (list[9])
from_wd: root_criterion (list[5])
is_git_root: root_criterion (list[5])
is_projectile_project: root_criterion (list[5])
is_r_package: root_criterion (list[5])
is_remake_project: root_criterion (list[5])
is_rstudio_project: root_criterion (list[5])
is_svn_root: root_criterion (list[5])
is_testthat: root_criterion (list[5])
is_vcs_root: root_criterion (list[5])
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: rprojroot
Title: Finding Files in Project Subdirectories
Version: 1.1
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
Expand Down Expand Up @@ -31,3 +31,4 @@ Collate:
'root.R'
'rprojroot-package.R'
'shortcut.R'
Roxygen: list(markdown = TRUE)
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,20 @@ 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)
18 changes: 18 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# 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
Expand Down
83 changes: 54 additions & 29 deletions R/criterion.R
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
#' Is a directory the project root?
#'
#' Objects of the \code{root_criterion} class decide if a
#' Objects of the `root_criterion` class decide if a
#' given directory is a project root.
#'
#' Construct criteria using \code{root_criterion} in a very general fashion
#' by specifying a function with a \code{path} argument, and a description.
#' 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 \code{TRUE}
#' @param testfun A function with one parameter that returns `TRUE`
#' if the directory specified by this parameter is the project root,
#' and \code{FALSE} otherwise
#' @param desc A textual description of the test criterion
#' 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 \code{root_criterion} wit the following members:
#' 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")
#' 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) {
if (!isTRUE(all.equal(names(formals(testfun)), "path"))) {
stop("testfun must be a function with one argument 'path'")
}
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 = ", "),
paste0("`", subdir, "`", collapse = ", "),
")"
)
)
Expand All @@ -44,27 +45,27 @@ root_criterion <- function(testfun, desc, subdir = NULL) {
list(
#' @return
#' \describe{
#' \item{\code{testfun}}{The \code{testfun} argument}
#' \item{`testfun`}{The `testfun` argument}
testfun = testfun,
#' \item{\code{desc}}{The \code{desc} argument}
#' \item{`desc`}{The `desc` argument}
desc = full_desc,
#' \item{\code{subdir}}{The \code{subdir} argument}
#' \item{`subdir`}{The `subdir` argument}
subdir = subdir
),
class = "root_criterion"
)

#' \item{\code{find_file}}{A function with \code{...} argument that returns
#' \item{`find_file`}{A function with `...` 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{"."}.
#' The optional `path` argument specifies the starting directory,
#' which defaults to `"."`.
#' }
criterion$find_file <- make_find_root_file(criterion)
#' \item{\code{make_fix_file}}{A function with a \code{path} argument that
#' \item{`make_fix_file`}{A function with a `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
#' 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.
#' }
#' }
Expand All @@ -74,6 +75,20 @@ root_criterion <- function(testfun, desc, subdir = NULL) {
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
Expand All @@ -86,9 +101,9 @@ is.root_criterion <- function(x) {
as.root_criterion <- function(x) UseMethod("as.root_criterion", x)

#' @details
#' 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}.
#' 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
Expand All @@ -107,20 +122,30 @@ as.root_criterion.default <- function(x) {

#' @export
format.root_criterion <- function(x, ...) {
paste("Root criterion:", x$desc)
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(paste0(format(x), "\n"))
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(
function(path) x$testfun(path) || y$testfun(path),
paste0(x$desc, ", or ", y$desc)
c(x$testfun, y$testfun),
c(x$desc, y$desc)
)
}
14 changes: 7 additions & 7 deletions R/file.R
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#' File paths relative to the root of a directory hierarchy
#'
#' Append an arbitrary number of path components to the root using
#' \code{\link[base]{file.path}}.
#' [base::file.path()].
#'
#' The \code{find_root_file} function is a simple wrapper around
#' \code{\link{find_root}} that
#' The `find_root_file` function is a simple wrapper around
#' [find_root()] that
#' appends an arbitrary number of path components to the root using
#' \code{\link[base]{file.path}}.
#' [base::file.path()].
#'
#' @param criterion A criterion, will be coerced using
#' \code{\link{as.root_criterion}}
#' [as.root_criterion()]
#' @param path The start directory
#' @param ... Further path components passed to \code{\link{file.path}}
#' @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
Expand All @@ -23,7 +23,7 @@
#' has_file("DESCRIPTION", "^Package: ")$make_fix_file(".")
#' }
#'
#' @seealso \code{\link{find_root}} \code{\link[utils]{glob2rx}} \code{\link[base]{file.path}}
#' @seealso [find_root()] [utils::glob2rx()] [base::file.path()]
#'
#' @export
find_root_file <- function(..., criterion, path = ".") {
Expand Down
Loading

0 comments on commit 662a7c1

Please sign in to comment.