diff --git a/.Rbuildignore b/.Rbuildignore index d887369..d2566db 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -2,5 +2,8 @@ ^\.Rproj\.user$ ^LICENSE\.md$ ^README\.Rmd$ +^scratch$ ^gitpins$ ^\.github$ +^.lintr$ +^gitpins_.*$ diff --git a/.gitignore b/.gitignore index 623d753..01a813a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ .DS_Store # Manual additions +/scratch/ /gitpins/ /gitpins_*/ diff --git a/.lintr b/.lintr new file mode 100644 index 0000000..fcfdc4f --- /dev/null +++ b/.lintr @@ -0,0 +1,9 @@ +linters: linters_with_defaults( + infix_spaces_linter = NULL, # 40 + line_length_linter = NULL, # 13 + spaces_inside_linter = NULL, # 9 + object_name_linter = NULL # 5 + ) +exclusions: list( + "man/*.Rd" + ) diff --git a/DESCRIPTION b/DESCRIPTION index 6a3298a..2b2f093 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: gitpins Type: Package Title: Pin urls to local file and version with git -Version: 0.1.3 +Version: 0.1.3.9001 Author: Magnus Thor Torfason Maintainer: Magnus Thor Torfason Description: Pin URLs to local file and version the pins with git. @@ -16,7 +16,8 @@ Imports: digest, gert, here, - jsonlite + jsonlite, + checkmate Suggests: tibble, testthat (>= 3.0.0), @@ -25,6 +26,6 @@ Suggests: Depends: R (>= 4.1.0) Config/testthat/edition: 3 -RoxygenNote: 7.1.2 +RoxygenNote: 7.2.3 URL: https://github.com/torfason/gitpins BugReports: https://github.com/torfason/gitpins/issues diff --git a/NAMESPACE b/NAMESPACE index 96f28e1..f581cf6 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,3 +3,8 @@ export(gitpin) export(list_pins) export(pin) +importFrom(checkmate,assert_flag) +importFrom(checkmate,assert_int) +importFrom(checkmate,assert_number) +importFrom(checkmate,assert_posixct) +importFrom(checkmate,assert_string) diff --git a/R/0_gitpins-package.R b/R/0_gitpins-package.R index 2ab9787..f351e38 100644 --- a/R/0_gitpins-package.R +++ b/R/0_gitpins-package.R @@ -16,6 +16,12 @@ #' To get started, check out the help for the [gitpin()] function, or take a #' look at the info on GitHub (see links below). #' +#' @importFrom checkmate assert_string +#' @importFrom checkmate assert_number +#' @importFrom checkmate assert_flag +#' @importFrom checkmate assert_int +#' @importFrom checkmate assert_posixct +#' #' @docType package #' @name gitpins #' @md diff --git a/R/gitpin.R b/R/gitpin.R index 530204e..e5813cf 100644 --- a/R/gitpin.R +++ b/R/gitpin.R @@ -4,11 +4,14 @@ #' Convert date-time variable to sub-millisecond timestamp #' #' @param the_datetime a date variable -#' @return a character representation of `the_datetime` as a sub-millisecond timestamp +#' @return a character representation of `the_datetime` as a sub-millisecond +#' timestamp #' @md #' @keywords internal tstamp <- function(the_datetime) { - strftime(the_datetime , "%Y-%m-%d %H:%M:%OS5") + assert_posixct(the_datetime) + + strftime(the_datetime, "%Y-%m-%d %H:%M:%OS5") } #' Convert date-time variable to file-compatible timestamp @@ -19,7 +22,9 @@ tstamp <- function(the_datetime) { #' @md #' @keywords internal fstamp <- function(the_datetime) { - strftime(the_datetime , "%Y-%m-%d.%H%M%S") + assert_posixct(the_datetime) + + strftime(the_datetime, "%Y-%m-%d.%H%M%S") } #' Initialize gitpins repository @@ -53,7 +58,8 @@ init_gitpins <- function() { #' @md #' @export pin <- function(url, refresh_hours=12) { - #url <- "https://raw.githubusercontent.com/vincentarelbundock/Rdatasets/master/csv/boot/acme.csv" + assert_string(url) + assert_number(refresh_hours) # Default frequency of downloads, configurable with config_gitpins() # could be to redownload if not the same day as the last download. @@ -64,16 +70,17 @@ pin <- function(url, refresh_hours=12) { stopifnot(!is.null(url) && is.character(url) && length(url)==1) url_hash <- digest::digest(url) timestamp <- Sys.time() - destfile_data <- file.path(.globals$repo,paste0(url_hash,".data")) - destfile_temp <- file.path(.globals$repo,paste0(url_hash,".temp")) - on.exit(if(file.exists(destfile_temp))file.remove(destfile_temp)) - destfile_info <- file.path(.globals$repo,paste0(url_hash,".info")) - destfile_json <- file.path(.globals$repo,paste0(url_hash,".json")) + destfile_data <- file.path(.globals$repo, paste0(url_hash, ".data")) + destfile_temp <- file.path(.globals$repo, paste0(url_hash, ".temp")) + on.exit(if (file.exists(destfile_temp)) file.remove(destfile_temp)) # nolint + destfile_json <- file.path(.globals$repo, paste0(url_hash, ".json")) # Read some metadata, to determine what to do next if ( file.exists(destfile_json) ) { meta_last <- readLines(destfile_json) |> jsonlite::fromJSON() - delta_hours <- as.double(difftime(timestamp, as.POSIXct(meta_last$timestamp), units="hours")) + delta_hours <- as.double(difftime(timestamp, + as.POSIXct(meta_last$timestamp), + units="hours")) if ( delta_hours < refresh_hours ) { recent_version_found <- TRUE } @@ -84,16 +91,16 @@ pin <- function(url, refresh_hours=12) { # Do the download and determine next steps if ( recent_version_found ) { - message(paste("Recent version found, using it ...")) + message(paste("pin() found recent version, using it ...")) } else { tryCatch( - { dl_result <- curl::curl_download(url, destfile_temp, quiet=TRUE) }, - error=function(e) {}, - warning=function(e) {} + { curl::curl_download(url, destfile_temp, quiet=TRUE) }, + error=function(e) {}, # nolint + warning=function(e) {} # nolint ) - if ( !file.exists(destfile_temp) || file.size(destfile_temp)==0) { + if ( !file.exists(destfile_temp) || file.size(destfile_temp)==0 ) { # Download failed in some way if (!file.exists(destfile_data)) { stop("Download failed and no earlier version found: Aborting!") @@ -106,13 +113,12 @@ pin <- function(url, refresh_hours=12) { # Download succeeded message("Downloaded fresh version ...") file.copy(destfile_temp, destfile_data, overwrite = TRUE) - #writeLines(c(timestamp, url), destfile_info) list(timestamp=jsonlite::unbox(tstamp(timestamp)), url=jsonlite::unbox(url)) |> jsonlite::toJSON(pretty = TRUE, simplifyVector=TRUE) |> writeLines(destfile_json) gert::git_add( - basename(c(destfile_data,destfile_json)), # Must be relative to repo root + basename(c(destfile_data, destfile_json)), # Must be relative to repo root repo=.globals$repo) gert::git_commit_all(paste0("[", tstamp(timestamp), "] ", url), repo=.globals$repo) } @@ -138,6 +144,8 @@ gitpin <- pin #' @md #' @export list_pins <- function(history=FALSE) { + assert_flag(history) + init_gitpins() # Function to return empty data.frame on fresh repo instead of erroring @@ -157,19 +165,19 @@ list_pins <- function(history=FALSE) { lapply(as.data.frame) |> do.call(what=rbind) if (is.null(d.result)) d.result <- data.frame(timestamp=character(), url=character()) - d.result <- d.result[order(d.result$timestamp, decreasing=TRUE),] + d.result <- d.result[order(d.result$timestamp, decreasing=TRUE), ] } else { # Return result based on what is in the gitlog logmessages <- get_repo_log_messages() d.result <- data.frame( - timestamp = gsub('\\[(.*)\\].*','\\1',logmessages), - url = gsub('.*\\] (.*)','\\1',logmessages) |> + timestamp = gsub("\\[(.*)\\].*", "\\1", logmessages), + url = gsub(".*\\] (.*)", "\\1", logmessages) |> sub(pattern="\\n", replacement="") ) } # Be nice and return a tibble if it is available - if (requireNamespace("tibble")){ + if (requireNamespace("tibble")) { d.result <- tibble::as_tibble(d.result) } d.result @@ -181,4 +189,3 @@ list_pins <- function(history=FALSE) { clear_old_pins <- function() { stop("not implemented") } - diff --git a/build/build_and_release_process.R b/build/build_and_release_process.R index 06c8ac5..b7fdf72 100644 --- a/build/build_and_release_process.R +++ b/build/build_and_release_process.R @@ -3,7 +3,7 @@ { gpdir <- here::here("gitpins") if (file.exists(gpdir)) { - file.rename(gpdir, paste0(gpdir,"_",fstamp(Sys.time()))) + file.rename(gpdir, paste0(gpdir,"_",gitpins:::fstamp(Sys.time()))) } devtools::build() devtools::document() diff --git a/inst/WORDLIST b/inst/WORDLIST index e2e42e0..861c7d0 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -1,3 +1,4 @@ +CMD +api borked deduplication -CMD diff --git a/man/tstamp.Rd b/man/tstamp.Rd index 7590ef9..fe14a46 100644 --- a/man/tstamp.Rd +++ b/man/tstamp.Rd @@ -10,7 +10,8 @@ tstamp(the_datetime) \item{the_datetime}{a date variable} } \value{ -a character representation of \code{the_datetime} as a sub-millisecond timestamp +a character representation of \code{the_datetime} as a sub-millisecond +timestamp } \description{ Convert date-time variable to sub-millisecond timestamp diff --git a/tests/testthat/test-gitpin-local.R b/tests/testthat/test-gitpin-local.R index 1a76a91..a3fb93f 100644 --- a/tests/testthat/test-gitpin-local.R +++ b/tests/testthat/test-gitpin-local.R @@ -1,23 +1,24 @@ -test_that("gitpins work with local server",{ +test_that("gitpins work with local server", { # Skip test if suggested packages callr and servr are not installed if ( !requireNamespace("callr", quietly = TRUE) || !requireNamespace("servr", quietly = TRUE) ) { - skip() + skip("Packages callr or servr not found, skipping test") } # Set here with reference to the test file here::i_am("tests/testthat/test-gitpin-local.R") |> expect_message("gitpins") # If here does not get us the path to the local www_root, we panic - if(!file.exists(here::here("tests","www_root"))) stop("Web root not found, skipping test") + if (!file.exists(here::here("tests", "www_root"))) + stop("Web root not found, skipping test") # Function to start a local server. callr_servr <- function() { host <- getOption("servr.host", "127.0.0.1") port <- servr:::random_port() - dir <- here::here("tests","www_root") + dir <- here::here("tests", "www_root") proc <- callr::r_bg(servr::httd, args=list(daemon=FALSE, dir=dir, host=host, port=port), package="servr") @@ -75,4 +76,3 @@ test_that("gitpins work with local server",{ "Download failed, using last good version ...") }) - diff --git a/tests/testthat/test-gitpin-remote.R b/tests/testthat/test-gitpin-remote.R index 4b2106c..623a142 100644 --- a/tests/testthat/test-gitpin-remote.R +++ b/tests/testthat/test-gitpin-remote.R @@ -1,5 +1,5 @@ -test_that("gitpin works with remote URLs",{ +test_that("gitpin works with remote URLs", { skip_if_offline() diff --git a/tests/testthat/test-list_gitpins.R b/tests/testthat/test-list_gitpins.R index d8a36d7..9630d2a 100644 --- a/tests/testthat/test-list_gitpins.R +++ b/tests/testthat/test-list_gitpins.R @@ -25,7 +25,7 @@ test_that("listing is in default order", { # Nohist should be subset of hist matches <- listing_hist$timestamp %in% listing_nohist$timestamp - listing_hist_subset <- listing_hist[matches,] + listing_hist_subset <- listing_hist[matches, ] expect_equal(listing_hist_subset, listing_nohist) })