Browse Source

rly working on Windows for sure now

tags/v0.3.0
Bob Rudis 8 years ago
parent
commit
c354d27376
  1. 1
      .Rbuildignore
  2. 9
      DESCRIPTION
  3. 1
      NAMESPACE
  4. 2
      R/wand-package.R
  5. 39
      R/wand.r
  6. 6
      R/zzz.r
  7. 4
      README.Rmd
  8. 4
      README.md
  9. BIN
      inst/db/win/magic.mgc.zip
  10. BIN
      inst/exec/file.exe
  11. 12
      man/get_os.Rd
  12. 4
      man/incant.Rd
  13. 7
      man/magic_wand_file.Rd
  14. 6
      src/Makevars
  15. 7
      src/Makevars.win
  16. 6
      src/wand.cpp
  17. 25
      tests/testthat/test-wand.R
  18. 5
      tools/getfile.R

1
.Rbuildignore

@ -5,3 +5,4 @@
^README\.*html$
^NOTES\.*Rmd$
^NOTES\.*html$
^tools$

9
DESCRIPTION

@ -2,7 +2,7 @@ Package: wand
Type: Package
Title: Retrieve 'Magic' Attributes from Files and Directories
Version: 0.2.0
Date: 2016-08-13
Date: 2016-08-14
Author: Bob Rudis (@hrbrmstr), Christos Zoulas [libmagic]
Maintainer: Bob Rudis <bob@rud.is>
Description: The 'libmagic' library provides functions to determine
@ -10,13 +10,12 @@ Description: The 'libmagic' library provides functions to determine
attributes.
URL: http://github.com/hrbrmstr/wand
BugReports: https://github.com/hrbrmstr/wand/issues
SystemRequirements: libmagic (>= 5.14)
SystemRequirements: libmagic (>= 5.14) for Unix/Linux/macOS; Rtools 3.3+ for Windows
License: AGPL
Suggests:
testthat,
magrittr
testthat
Depends:
R (>= 3.0.0)
R (>= 3.2.0)
Imports:
purrr,
Rcpp,

1
NAMESPACE

@ -10,6 +10,7 @@ import(tidyr)
importFrom(Rcpp,sourceCpp)
importFrom(dplyr,left_join)
importFrom(dplyr,mutate)
importFrom(dplyr,mutate_all)
importFrom(rappdirs,user_cache_dir)
importFrom(utils,unzip)
useDynLib(wand)

2
R/wand-package.R

@ -11,6 +11,6 @@
#' @useDynLib wand
#' @importFrom Rcpp sourceCpp
#' @importFrom utils unzip
#' @importFrom dplyr mutate left_join
#' @importFrom dplyr mutate left_join mutate_all
#' @import stats
NULL

39
R/wand.r

@ -3,7 +3,8 @@
#' @param path character vector of files to use magic on
#' @param magic_db either "\code{system}" (the default) to use the system
#' \code{magic} database or an atomic character vector with a
#' colon-separated list of full paths to custom \code{magic} database(s).
#' colon-separated list of full paths to custom \code{magic} database(s). This parameter
#' is (for the moment) ignored on Windows.
#' @return a \code{tibble} / \code{data.frame} of file magic attributes.
#' Specifically, mime type, encoding, possible file extensions and
#' type description are returned as colums in the data frame along
@ -14,7 +15,6 @@
#' for information on how to create your own \code{magic} database
#' @export
#' @examples
#' library(magrittr)
#' library(dplyr)
#'
#' system.file("img", package="filemagic") %>%
@ -25,24 +25,41 @@ incant <- function(path, magic_db="system") {
if (get_os() == "win") {
file_exe <- system.file("exec/file.exe", package="wand")
found_file <- FALSE
file_exe <- Sys.which("file.exe")
found_file <- file_exe != ""
if (found_file) {
file_version <- suppressWarnings(system2(file_exe, "--version", stdout=TRUE, stderr=TRUE))
found_file <- any(grepl("magic file", file_version))
}
if (!found_file) {
stop(paste0("'file.exe' not found. Please install 'Rtools' and restart R. ",
"See 'https://github.com/stan-dev/rstan/wiki/Install-Rtools-for-Windows' ",
"for more information on how to install 'Rtools'", collapse=""),
call.=FALSE)
}
magic_db <- normalizePath(magic_wand_file())
tf <- tempfile()
writeLines(path, tf)
system2(file_exe,
suppressMessages(
suppressWarnings(
system2(file_exe,
c("--mime-type", "--mime-encoding", "--no-buffer", "--preserve-date",
'--separator "||"', sprintf('--magic-file "%s"', magic_db),
'--separator "||"',
sprintf('--files-from "%s"', tf)),
stdout=TRUE) -> output_1
stdout=TRUE))) -> output_1
system2(file_exe,
suppressMessages(
suppressWarnings(system2(file_exe,
c("--no-buffer", "--preserve-date", '--separator "||"',
sprintf('--magic-file "%s"', magic_db),
sprintf('--files-from "%s"', tf)),
stdout=TRUE) -> output_2
stdout=TRUE))) -> output_2
unlink(tf)
@ -56,13 +73,15 @@ incant <- function(path, magic_db="system") {
as_data_frame() %>%
setNames(c("file", "description")) -> df2
left_join(df1, df2, by="file")
left_join(df1, df2, by="file") %>%
mutate_all(stri_trim_both)
} else {
incant_(path, magic_db)
}
}
#' ripped from rappdirs (ty Hadley!)
get_os <- function () {
if (.Platform$OS.type == "windows") {
"win"

6
R/zzz.r

@ -10,9 +10,12 @@
#'
#' @param refresh ensure the lastest copy of the pacakge "magic"
#' database is used.
#' @note 'magic' files are highly coupled with the version of the \code{file}
#' utility they were built with. This function is provided solely for the
#' off chance that a macOS or Linux/UNIX system's \code{libmagic} library
#' was not configured properly and cannot find the system 'magic' file.
#' @export
#' @examples
#' library(magrittr)
#' library(dplyr)
#'
#' system.file("img", package="filemagic") %>%
@ -27,7 +30,6 @@ magic_wand_file <- function(refresh=FALSE) {
if (!dir.exists(cache)) return(NULL)
if (lib_version() >= 528) vers <- "new" else vers <- "old"
if (get_os() == "win") vers <- "win"
if (refresh | (!file.exists(file.path(rappdirs::user_cache_dir("wandr"), "magic.mgc")))) {
unzip(system.file("db", vers, "magic.mgc.zip", package="wand"),

4
README.Rmd

@ -13,7 +13,7 @@ The `libmagic` library must be installed on *nix/macOS and available to use this
While the package was developed using the 5.28 version of `libmagic` it has been configured to work with older versions. Note that some fields in the resultant data frame might not be available with older library versions. When using the function `magic_wand_file()` it checks for which version of `libmagic` is installed on your system and provides a suitable `magic.mgc` file for it.
The package also works on Windows but it's a bit of a hack because, well, _Windows_. Seriously, folks, use a real operating system. The Windows version makes two `system2()` calls, so it's sub-optimal at best. Help to get it working in C would be greatly appreciated.
The package also works on Windows but it's a bit of a hack because, well, _Windows_. The Windows version makes two `system2()` calls and relies on Rtools being installed and `file.exe` being available on the Windows `PATH`, so it's sub-optimal at best. Help to get it working in C would be greatly appreciated.
The following functions are implemented:
@ -42,6 +42,8 @@ system.file("img", package="wand") %>%
incant() %>%
glimpse()
# Use a non-system magic-file
system.file("img", package="wand") %>%
list.files(full.names=TRUE) %>%
incant(magic_wand_file()) %>%

4
README.md

@ -10,7 +10,7 @@ The `libmagic` library must be installed on \*nix/macOS and available to use thi
While the package was developed using the 5.28 version of `libmagic` it has been configured to work with older versions. Note that some fields in the resultant data frame might not be available with older library versions. When using the function `magic_wand_file()` it checks for which version of `libmagic` is installed on your system and provides a suitable `magic.mgc` file for it.
The package also works on Windows but it's a bit of a hack because, well, *Windows*. Seriously, folks, use a real operating system. The Windows version makes two `system2()` calls, so it's sub-optimal at best. Help to get it working in C would be greatly appreciated.
The package also works on Windows but it's a bit of a hack because, well, *Windows*. The Windows version makes two `system2()` calls and relies on Rtools being installed and `file.exe` being available on the Windows `PATH`, so it's sub-optimal at best. Help to get it working in C would be greatly appreciated.
The following functions are implemented:
@ -79,7 +79,7 @@ library(testthat)
date()
```
## [1] "Sun Aug 14 18:36:44 2016"
## [1] "Mon Aug 15 08:17:44 2016"
``` r
test_dir("tests/")

BIN
inst/db/win/magic.mgc.zip

Binary file not shown.

BIN
inst/exec/file.exe

Binary file not shown.

12
man/get_os.Rd

@ -0,0 +1,12 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/wand.r
\name{get_os}
\alias{get_os}
\title{ripped from rappdirs (ty Hadley!)}
\usage{
get_os()
}
\description{
ripped from rappdirs (ty Hadley!)
}

4
man/incant.Rd

@ -11,7 +11,8 @@ incant(path, magic_db = "system")
\item{magic_db}{either "\code{system}" (the default) to use the system
\code{magic} database or an atomic character vector with a
colon-separated list of full paths to custom \code{magic} database(s).}
colon-separated list of full paths to custom \code{magic} database(s). This parameter
is (for the moment) ignored on Windows.}
}
\value{
a \code{tibble} / \code{data.frame} of file magic attributes.
@ -27,7 +28,6 @@ Various fields might not be available depending on the version
of \code{libmagic} you have installed.
}
\examples{
library(magrittr)
library(dplyr)
system.file("img", package="filemagic") \%>\%

7
man/magic_wand_file.Rd

@ -19,8 +19,13 @@ return the full path to the magic file. Subsequent calls will not have to
perform the decompression unless \code{force} is \code{TRUE} or the
cache directory has been cleared.
}
\note{
'magic' files are highly coupled with the version of the \code{file}
utility they were built with. This function is provided solely for the
off chance that a macOS or Linux/UNIX system's \code{libmagic} library
was not configured properly and cannot find the system 'magic' file.
}
\examples{
library(magrittr)
library(dplyr)
system.file("img", package="filemagic") \%>\%

6
src/Makevars

@ -1,8 +1,2 @@
PKG_LIBS = -lmagic
all: clean
clean:
rm -f $(OBJECTS) wand.dll
.PHONY: all clean

7
src/Makevars.win

@ -1,9 +1,6 @@
all: winlibs
all: clean
clean:
rm -f $(OBJECTS) wand.dll
winlibs:
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/getfile.R"
.PHONY: all winlibs clean
.PHONY: all clean

6
src/wand.cpp

@ -42,6 +42,12 @@ DataFrame incant_(CharacterVector path, std::string magic_db="system") {
mdb = mdbcpp.c_str();
}
// This is "ugh" due to the fact that various versions of the libmagic
// library can't handle loading multiple "cookies" at the same time.
// So, we end up doing way too much extra work to get the individual
// bits of info. I may just switch this over to a single call (all the
// availabel flags) and do string parsing before pushing to CRAN.
for (unsigned int i=0; i<input_size; i++) {
if ((i % 10000) == 0) Rcpp::checkUserInterrupt();

25
tests/testthat/test-wand.R

@ -1,12 +1,13 @@
context("basic functionality")
test_that("we can do something", {
tmp <- incant(list.files(system.file("img", package="wand"), full.names=TRUE),
magic_wand_file())
tmp <- tmp$description
tmp <- unlist(tmp, use.names=FALSE)
tmp <- sort(tmp)
expect_that(tmp[3], equals("C source, ASCII text"))
})
context("basic functionality")
test_that("we can do something", {
tmp <- incant(list.files(system.file("img", package="wand"),
full.names=TRUE),
magic_wand_file())
tmp <- tmp$description
tmp <- unlist(tmp, use.names=FALSE)
tmp <- sort(tmp)
expect_that(substr(tmp[8], 1, 3), equals("PNG"))
})

5
tools/getfile.R

@ -1,5 +0,0 @@
if(getRversion() < "3.3.0") setInternet2()
download.file("https://www.stats.ox.ac.uk/pub/Rtools/goodies/file-5.03.zip", "file.zip", quiet = TRUE)
dir.create("../inst/exec", showWarnings = FALSE)
unzip("file.zip", "file.exe", exdir = "../inst/exec")
unlink("file.zip")
Loading…
Cancel
Save