desc/0000755000176200001440000000000013272151205011166 5ustar liggesusersdesc/inst/0000755000176200001440000000000013272041600012140 5ustar liggesusersdesc/inst/README.Rmd0000644000176200001440000000763713272041565013570 0ustar liggesusers ```{r, setup, echo = FALSE, message = FALSE} knitr::opts_chunk$set( comment = "#>", tidy = FALSE, error = FALSE, fig.width = 8, fig.height = 8) ``` # desc > Parse DESCRIPTION files [![Linux Build Status](https://travis-ci.org/r-lib/desc.svg?branch=master)](https://travis-ci.org/r-lib/desc) [![Windows Build status](https://ci.appveyor.com/api/projects/status/github/r-lib/desc?svg=true)](https://ci.appveyor.com/project/gaborcsardi/desc) [![](http://www.r-pkg.org/badges/version/desc)](http://www.r-pkg.org/pkg/desc) [![CRAN RStudio mirror downloads](http://cranlogs.r-pkg.org/badges/desc)](http://www.r-pkg.org/pkg/desc) [![Coverage Status](https://img.shields.io/codecov/c/github/r-lib/desc/master.svg)](https://codecov.io/github/r-lib/desc?branch=master) Parse, manipulate and reformat DESCRIPTION files. The package provides two APIs, one is object oriented, the other one is procedural and manipulates the files *in place*. --- - [Installation](#installation) - [The object oriented API](#the-oo-api) - [Introduction](#introduction) - [Loading or creating new `DESCRIPTION` files](#loading-or-creating-new-description-files) - [Normalizing `DESCRIPTION` files](#normalizing-description-files) - [Querying, changing and removing fields](#querying-changing-and-removing-fields) - [Dependencies](#dependencies) - [Collate fields](#collate-fields) - [Authors](#authors) - [The procedural API](#the-procedural-api) - [License](#license) ## Installation ```{r eval = FALSE} source("https://install-github.me/r-lib/desc") ``` ## The object oriented API ```{r} library(desc) ``` ### Introduction The object oriented API uses [R6](https://github.com/wch/R6) classes. ### Loading or creating new `DESCRIPTION` files A new `description` object can be created by reading a `DESCRPTION` file form the disk. By default the `DESCRIPTION` file in the current directory is read: ```{r} desc <- description$new() desc ``` A new object can also be created from scratch: ```{r} desc2 <- description$new("!new") desc2 ``` ### Normalizing `DESCRIPTION` files Most `DESCRIPTION` fields may be formatted in multiple equivalent ways. `desc` does not reformat fields, unless they are updated or reformatting is explicitly requested via a call to the `normalize()` method or using the `normalize` argument of the `write()` method. ### Querying, changing and removing fields `get()` and `set()` queries or updates a field: ```{r} desc$set("Package", "foo") desc$get("Package") ``` They work with multiple fields as well: ```{r} desc$set(Package = "bar", Title = "Bar Package") desc$get(c("Package", "Title")) ``` ### Dependencies Package dependencies can be set and updated via an easier API: ```{r} desc$get_deps() desc$set_dep("mvtnorm") desc$set_dep("Rcpp", "LinkingTo") desc$get_deps() desc ``` ### Collate fields Collate fields can be queried and set using simple character vectors of file names: ```{r} desc$set_collate(list.files("../R")) desc$get_collate() ``` ### Authors Authors information, when specified via the `Authors@R` field, also has a simplified API: ```{r} desc <- description$new("DESCRIPTION2") desc$get_authors() desc$add_author("Bugs", "Bunny", email = "bb@acme.com") desc$add_me() desc$get_authors() ``` ## The procedural API The procedural API is simpler to use for one-off `DESCRIPTION` manipulation, since it does not require dealing with `description` objects. Each object oriented method has a procedural counterpart that works on a file, and potentially writes its result back to the same file. For example, adding a new dependency to `DESCRIPTION` in the current working directory can be done with ```{r} desc_set_dep("newpackage", "Suggests") ``` This added `newpackage` to the `Suggests` field: ```{r} desc_get("Suggests") ``` So the full list of dependencies are now ```{r} desc_get_deps() ``` ## License MIT © [Gábor Csárdi](https://github.com/gaborcsardi), [RStudio Inc](https://github.com/rstudio) desc/inst/NEWS.md0000644000176200001440000000263213272041260013243 0ustar liggesusers # 1.2.0 * Add `get_field()` method, with easier to use failure and fallback semantics (#62) * Use the `Encoding` field to read and write DESCRIPTION with the corect encoding. UTF-8 is always used internall by desc. (#52, #53) * Add `get_built()` function to parse the Built field used in package binaries. (#48, @jimhester) * `get_deps()` (and `desc_get_deps()`) return a zero-row data frame instead of `NULL` for packages without any dependencies, for consistency. * Empty `DESCRIPTION` files are handled more gracefully, as are querying no fields with `desc_get()` * `Remotes`, `VignetteBuilder` and `RdMacros` fields are syntax checked. (#59, @krlmlr) * Account for non-URL content in the `URL` field (#57, @jennybc) * Allow for IETF region subtag in `Language` field (#55, @jeroen) * Fix continuation lines in output * `get_deps()` returns empty data frame if no dependencies, instead of `NULL` # 1.1.1 * Relax the R >= 3.2.0 dependency, R 3.1.0 is enough now. # 1.1.0 * Fix bug when adding authors and there is no `Authors@R` field * Get `DESCRIPTION` from package archives (#40) * Fix but in `del_dep()` and `has_dep()`, they only worked if the package was attached. # 1.0.1 * Fix formatting of `Collate` fields, they always start at a new line now. * Fix formatting of `Authors@R` fields, when changed. * Keep trailing space after the `:` character, see #14 # 1.0.0 First public release. desc/inst/README.md0000644000176200001440000001722313272041600013424 0ustar liggesusers # desc > Parse DESCRIPTION files [![Linux Build Status](https://travis-ci.org/r-lib/desc.svg?branch=master)](https://travis-ci.org/r-lib/desc) [![Windows Build status](https://ci.appveyor.com/api/projects/status/github/r-lib/desc?svg=true)](https://ci.appveyor.com/project/gaborcsardi/desc) [![](http://www.r-pkg.org/badges/version/desc)](http://www.r-pkg.org/pkg/desc) [![CRAN RStudio mirror downloads](http://cranlogs.r-pkg.org/badges/desc)](http://www.r-pkg.org/pkg/desc) [![Coverage Status](https://img.shields.io/codecov/c/github/r-lib/desc/master.svg)](https://codecov.io/github/r-lib/desc?branch=master) Parse, manipulate and reformat DESCRIPTION files. The package provides two APIs, one is object oriented, the other one is procedural and manipulates the files *in place*. --- - [Installation](#installation) - [The object oriented API](#the-oo-api) - [Introduction](#introduction) - [Loading or creating new `DESCRIPTION` files](#loading-or-creating-new-description-files) - [Normalizing `DESCRIPTION` files](#normalizing-description-files) - [Querying, changing and removing fields](#querying-changing-and-removing-fields) - [Dependencies](#dependencies) - [Collate fields](#collate-fields) - [Authors](#authors) - [The procedural API](#the-procedural-api) - [License](#license) ## Installation ```r source("https://install-github.me/r-lib/desc") ``` ## The object oriented API ```r library(desc) ``` ### Introduction The object oriented API uses [R6](https://github.com/wch/R6) classes. ### Loading or creating new `DESCRIPTION` files A new `description` object can be created by reading a `DESCRPTION` file form the disk. By default the `DESCRIPTION` file in the current directory is read: ```r desc <- description$new() desc ``` ``` #> Package: desc #> Title: Manipulate DESCRIPTION Files #> Version: 1.0.0 #> Author: Gábor Csárdi #> Maintainer: Gábor Csárdi #> Description: Tools to read, write, create, and manipulate DESCRIPTION #> files. It is intented for packages that create or manipulate other #> packages. #> License: MIT + file LICENSE #> URL: https://github.com/r-lib/desc #> BugReports: https://github.com/r-lib/desc/issues #> Imports: #> R6 #> Suggests: #> testthat, #> whoami, #> newpackage #> Encoding: UTF-8 #> LazyData: true #> RoxygenNote: 5.0.0 ``` A new object can also be created from scratch: ```r desc2 <- description$new("!new") desc2 ``` ``` #> Package: {{ Package }} #> Title: {{ Title }} #> Version: 1.0.0 #> Authors@R (parsed): #> * Jo Doe [aut, cre] #> Maintainer: {{ Maintainer }} #> Description: {{ Description }} #> License: {{ License }} #> URL: {{ URL }} #> BugReports: {{ BugReports }} #> Encoding: UTF-8 #> LazyData: true ``` ### Normalizing `DESCRIPTION` files Most `DESCRIPTION` fields may be formatted in multiple equivalent ways. `desc` does not reformat fields, unless they are updated or reformatting is explicitly requested via a call to the `normalize()` method or using the `normalize` argument of the `write()` method. ### Querying, changing and removing fields `get()` and `set()` queries or updates a field: ```r desc$set("Package", "foo") desc$get("Package") ``` ``` #> Package #> "foo" ``` They work with multiple fields as well: ```r desc$set(Package = "bar", Title = "Bar Package") desc$get(c("Package", "Title")) ``` ``` #> Package Title #> "bar" "Bar Package" ``` ### Dependencies Package dependencies can be set and updated via an easier API: ```r desc$get_deps() ``` ``` #> type package version #> 1 Suggests testthat * #> 2 Suggests whoami * #> 3 Suggests newpackage * #> 4 Imports R6 * ``` ```r desc$set_dep("mvtnorm") desc$set_dep("Rcpp", "LinkingTo") desc$get_deps() ``` ``` #> type package version #> 1 Suggests testthat * #> 2 Suggests whoami * #> 3 Suggests newpackage * #> 4 Imports R6 * #> 5 Imports mvtnorm * #> 6 LinkingTo Rcpp * ``` ```r desc ``` ``` #> Package: bar #> Title: Bar Package #> Version: 1.0.0 #> Author: Gábor Csárdi #> Maintainer: Gábor Csárdi #> Description: Tools to read, write, create, and manipulate DESCRIPTION #> files. It is intented for packages that create or manipulate other #> packages. #> License: MIT + file LICENSE #> URL: https://github.com/r-lib/desc #> BugReports: https://github.com/r-lib/desc/issues #> Imports: #> R6, #> mvtnorm #> Suggests: #> testthat, #> whoami, #> newpackage #> LinkingTo: #> Rcpp #> Encoding: UTF-8 #> LazyData: true #> RoxygenNote: 5.0.0 ``` ### Collate fields Collate fields can be queried and set using simple character vectors of file names: ```r desc$set_collate(list.files("../R")) desc$get_collate() ``` ``` #> [1] "assertions.R" "authors-at-r.R" "classes.R" #> [4] "collate.R" "constants.R" "deps.R" #> [7] "description.R" "encoding.R" "latex.R" #> [10] "non-oo-api.R" "package-archives.R" "read.R" #> [13] "remotes.R" "str.R" "syntax_checks.R" #> [16] "urls.R" "utils.R" "validate.R" #> [19] "version.R" ``` ### Authors Authors information, when specified via the `Authors@R` field, also has a simplified API: ```r desc <- description$new("DESCRIPTION2") desc$get_authors() ``` ``` #> [1] "Hadley Wickham [aut, cre, cph]" #> [2] "Peter Danenberg [aut, cph]" #> [3] "Manuel Eugster [aut, cph]" #> [4] "RStudio [cph]" ``` ```r desc$add_author("Bugs", "Bunny", email = "bb@acme.com") desc$add_me() desc$get_authors() ``` ``` #> [1] "Hadley Wickham [aut, cre, cph]" #> [2] "Peter Danenberg [aut, cph]" #> [3] "Manuel Eugster [aut, cph]" #> [4] "RStudio [cph]" #> [5] "Bugs Bunny " #> [6] "Gabor Csardi [ctb]" ``` ## The procedural API The procedural API is simpler to use for one-off `DESCRIPTION` manipulation, since it does not require dealing with `description` objects. Each object oriented method has a procedural counterpart that works on a file, and potentially writes its result back to the same file. For example, adding a new dependency to `DESCRIPTION` in the current working directory can be done with ```r desc_set_dep("newpackage", "Suggests") ``` ``` #> Package: desc #> Title: Manipulate DESCRIPTION Files #> Version: 1.0.0 #> Author: Gábor Csárdi #> Maintainer: Gábor Csárdi #> Description: Tools to read, write, create, and manipulate DESCRIPTION #> files. It is intented for packages that create or manipulate other #> packages. #> License: MIT + file LICENSE #> URL: https://github.com/r-lib/desc #> BugReports: https://github.com/r-lib/desc/issues #> Imports: #> R6 #> Suggests: #> testthat, #> whoami, #> newpackage #> Encoding: UTF-8 #> LazyData: true #> RoxygenNote: 5.0.0 ``` This added `newpackage` to the `Suggests` field: ```r desc_get("Suggests") ``` ``` #> Suggests #> "\n testthat,\n whoami,\n newpackage" ``` So the full list of dependencies are now ```r desc_get_deps() ``` ``` #> type package version #> 1 Suggests testthat * #> 2 Suggests whoami * #> 3 Suggests newpackage * #> 4 Imports R6 * ``` ## License MIT © [Gábor Csárdi](https://github.com/gaborcsardi), [RStudio Inc](https://github.com/rstudio) desc/inst/DESCRIPTION0000644000176200001440000000101213140567212013646 0ustar liggesusersPackage: desc Title: Manipulate DESCRIPTION Files Version: 1.0.0 Author: Gábor Csárdi Maintainer: Gábor Csárdi Description: Tools to read, write, create, and manipulate DESCRIPTION files. It is intented for packages that create or manipulate other packages. License: MIT + file LICENSE LazyData: true URL: https://github.com/r-lib/desc BugReports: https://github.com/r-lib/desc/issues Suggests: testthat, whoami, newpackage Imports: R6 RoxygenNote: 5.0.0 Encoding: UTF-8 desc/inst/DESCRIPTION20000644000176200001440000000252013140567212013735 0ustar liggesusersPackage: roxygen2 Title: In-Source Documentation for R Description: A 'Doxygen'-like in-source documentation system for Rd, collation, and 'NAMESPACE' files. URL: https://github.com/klutometis/roxygen Version: 4.1.1.9000 License: GPL (>= 2) Authors@R: c( person("Hadley", "Wickham",, "h.wickham@gmail.com", c("aut", "cre", "cph")), person("Peter", "Danenberg",, "pcd@roxygen.org", c("aut", "cph")), person("Manuel", "Eugster", role = c("aut", "cph")), person("RStudio", role = "cph") ) Depends: R (>= 3.0.2) Imports: stringr (>= 0.5), brew, digest, methods, Rcpp (>= 0.11.0) Suggests: testthat (>= 0.8.0), knitr VignetteBuilder: knitr LinkingTo: Rcpp Collate: 'RcppExports.R' 'alias.R' 'description.R' 'family.R' 'inherit-params.R' 'minidesc.R' 'object-defaults.R' 'object-from-call.R' 'object.R' 'order-params.R' 'parse-preref.R' 'parse-registry.R' 'parse.R' 'rc.R' 'rd-escape.R' 'rd-file-api.R' 'rd-parse.R' 'rd-tag-api.R' 'roclet-collate.R' 'roclet-namespace.R' 'roclet-rd.R' 'roclet-vignette.R' 'roclet.R' 'roxygen.R' 'roxygenize.R' 's3.R' 'safety.R' 'source.R' 'template.R' 'topic-name.R' 'topo-sort.R' 'usage.R' 'util-locale.R' 'utils.R' RoxygenNote: 4.1.1.9000 desc/tests/0000755000176200001440000000000013202433665012336 5ustar liggesusersdesc/tests/testthat.R0000644000176200001440000000011213202433665014313 0ustar liggesuserslibrary(testthat) library(desc) test_check("desc", reporter = "summary") desc/tests/testthat/0000755000176200001440000000000013272151205014170 5ustar liggesusersdesc/tests/testthat/test-encoding.R0000644000176200001440000000420413202433077017061 0ustar liggesusers context("Encoding") test_that("Encoding field is observed", { expect_silent( desc <- description$new( text = paste0( "Package: foo\n", "Title: Foo Package\n", "Author: Package Author\n", "Maintainer: Package Author \n", "Description: The great foo package.\n", "License: GPL\n", "Encoding: UTF-8\n" ) ) ) expect_silent(desc$set(Author = "Gábor Csárdi")) }) test_that("Unset Encoding results warning", { expect_warning( desc <- description$new( text = paste0( "Package: foo\n", "Title: Foo Package\n", "Author: Package Author\n", "Maintainer: Gábor Csárdi \n", "Description: The great foo package.\n", "License: GPL\n" ) ), "Encoding" ) expect_warning(desc$set(Author = "Gábor Csárdi"), "Encoding") }) test_that("different encoding is converted to UTF-8 when reading", { expect_silent( desc <- description$new( text = paste0( "Package: foo\n", "Title: Foo Package\n", "Author: Package Author\n", "Maintainer: G\xE1bor Cs\xE1rdi \n", "Description: The great foo package.\n", "License: GPL\n", "Encoding: latin1\n" ) ) ) expect_equal(Encoding(desc$get("Maintainer")), "UTF-8") expect_silent(desc$set(Author = "G\u00e1bor Cs\u00e1rdi")) }) test_that("encoding is converted to specified when writing", { desc <- description$new( text = paste0( "Package: foo\n", "Title: Foo Package\n", "Author: Package Author\n", "Maintainer: G\xE1bor Cs\xE1rdi \n", "Description: The great foo package.\n", "License: GPL\n", "Encoding: latin1\n" ) ) desc$write(file = tmp <- tempfile()) on.exit(unlink(tmp)) tmpf <- file(tmp, encoding = "", open = "r") lines <- readLines(tmpf, encoding = "latin1") close(tmpf) maint <- grep("^Maintainer", lines, value = TRUE) exp <- "Maintainer: G\xE1bor Cs\xE1rdi " Encoding(exp) <- "latin1" expect_equal(charToRaw(maint), charToRaw(exp)) }) desc/tests/testthat/test-utils.R0000644000176200001440000000237313140567212016440 0ustar liggesusers context("Utility functions") test_that("check_for_package works", { expect_true(check_for_package("utils")) expect_error( check_for_package("foobarfoobarfoobar"), "Package 'foobarfoobarfoobar' is needed" ) }) test_that("is_ascii", { expect_true(is_ascii("")) expect_true(is_ascii("a")) expect_true(is_ascii(rawToChar(as.raw(127)))) expect_equal( is_ascii(character()), logical() ) expect_equal( is_ascii(c("a", "b")), c(TRUE, TRUE) ) expect_false(is_ascii(rawToChar(as.raw(128)))) }) test_that("is_url", { expect_true(is_url("http://acme.com")) expect_true(is_url("https://acme.com")) expect_true(is_url("ftp://this.is.it")) expect_equal(is_url(character()), logical()) expect_false(is_url("")) expect_false(is_url("this.is.not")) expect_false(is_url("http://")) expect_false(is_url("http:/this.is.no")) expect_equal( is_url(c("http://acme.com", "http://index.me")), c(TRUE, TRUE) ) expect_equal( is_url(c("foo", "https://foo.bar")), c(FALSE, TRUE) ) }) test_that("is_url_list", { expect_true(is_url_list("")) expect_true(is_url_list("http://foo.bar")) expect_false(is_url_list("this is not it")) expect_false(is_url_list("http://so.far.so.good, oh, no!")) }) desc/tests/testthat/test-built.R0000644000176200001440000000065013272146073016417 0ustar liggesusers context("BUILT") test_that("get built", { desc <- description$new("D4") expect_identical( desc$get_built(), list(R = R_system_version("3.4.1"), Platform = "x86_64-apple-darwin15.6.0", Date = "2017-09-14 20:30:19 UTC", OStype = "unix") ) }) test_that("corrupted Build field", { desc <- description$new("!new") desc$set(Built = "foobar") expect_error(desc$get_built(), "corrupted") }) desc/tests/testthat/test-desc.R0000644000176200001440000000016513140567212016213 0ustar liggesusers context("desc") test_that("desc wrapper works", { expect_equal( desc("D2"), description$new("D2") ) }) desc/tests/testthat/fixtures/0000755000176200001440000000000013272143532016045 5ustar liggesusersdesc/tests/testthat/fixtures/pkg_1.0.0.zip0000644000176200001440000000123313272143525020067 0ustar liggesusersPK Lpkg/UT IZUZux PKHX8J|aFpkg/DESCRIPTIONUT 84XIZux ]A0 E>/(Ha") f&ڈ6S\Q[QV NRHS#]}"R-Ⱥ4LS4osd;a|G쐦}GmvO-;vqpkg/DESCRIPTIONUT84Xux PK 7X8J Lpkg/NAMESPACEUT4Xux PKdesc/tests/testthat/fixtures/notpkg_1.0.tar.gz0000644000176200001440000000021413140567212021050 0ustar liggesusers1XA 0F=ay-B87("y߄ݻT5(o"J0!ڠw˪|ϥVs.e_l?%MZpݿ{(desc/tests/testthat/fixtures/pkg_1.0.0.tgz0000644000176200001440000000522413140567212020072 0ustar liggesusers[ xUmi+y@[#/()NI2t 3@KV- حɣcAB@Q((;3 ZZ6euLfs'gzN8#3?ݜgɚ+ BxҪN,,Ae QZ AUZYr8ëĭ4ccqN޲(NBNBr,#4`XDdq.у|tq phW U;IJiF(`m D)ܥ%0yМ`Kx8c#n*UB٤𰼞g#> TJKCPA*5(dnwa"5?O0T4Cg]n_w’hxmMx)kIIᰖX#ՋFDA(z`wDcKgY=Q˽Qo+TMxRuCzRL ռ=-glj^8R5 v)-GS)^8x%wc!xr6Ђׇ51"{ {ɍ\R%k~Ϻ2BKN׵ǿѨ$w+-|gB.Ydr 7؅˜-O˒OiQ,kQolc?|dTy5+r{gZÈo{OEO&sOlWjk5 gU};1/{?q մ =;E[3L)e&! >Pɯ6㠻qת_7on$v&5jn^ښ .}U0Yd0+s{L_ CI1/o_@C[g=sDƗ)2zP9 e8[]h{X??t5%%RAE^('X2t3p-eߐK촼QdѼ{$.Q4/zL?xwTu? vlE [>3;-':sm66r۩&g_^\30{#}p]+.ӓ]K5VMzu [/ۙxowߔsek="еuz9Ն)ӎU5=m?DՃF}ɵx8<N1 J:ҴEw%97ut:)R#Q Wux dLMe `|vV:+`x*3,p%'[1\98ΫreJI3Nb+)U"F vR-ۍN8`4;`Mp8D)9>,MN 8%xJsD'T`s Kpi>Ρ#0/E'T䴱‘&7+ h~Aa섁t;Y~h'-,cK+pN4 J)8+< o =0½,8E:=z`K0AU;|*VAaT"r fmNtB o40cm1!Is|t*F2( b a'3BGyj(8HaFYx-xf^/h=f4(8@yj@z"jBąclLյ~*!_NyzP"9"U,єpJթ|,_k&h@7 yf$Npn끛,CMK%BA3X~ *juZ0I'PP?u'ljz@rPmC%z!|(:wEe08v^N9 w߽8҆S7۩̪B^A:]\م(Уm 29)vm[ϡR/;ٔOv-]Z?6bq(BY&q֌]4?˷0`1'q8H"?t4Bdesc/tests/testthat/fixtures/xxx.tar.gz0000644000176200001440000000021413140567212020017 0ustar liggesusers1XA 0F=ay-B87("y߄ݻT5(o"J0!ڠw˪|ϥVs.e_l?%MZpݿ{(desc/tests/testthat/fixtures/pkg_1.0.0.tar.gz0000644000176200001440000000051513272063323020471 0ustar liggesusersn0 sSZu!$``6Ti8lOPئI;OJ;r2{]ð8$a'H"D8`dHAFƥR6EM)sn sJ$*vdz :J> NvMc \*r]u=_0]䇚o|HU \iZPdLB.I><k/(LYStGeСGB4!,1<E:/4_鍟q矅kWv desc/tests/testthat/fixtures/pkg_1.0.0_R_x86_64-pc-linux-gnu.tar.gz0000644000176200001440000000561613140567212024323 0ustar liggesusers\ XWVFlZU|FRdrk" "T@DZIfHF&83jQQ\zTkՕzuZ[YQ궺ح;3-[-d?3*=!*9.)%n\-HV i-F(TZU)ZQ(u  /aQ3,8ZRjF8P ܭ' PN34(ZƠfQ JcM2"|V>1jG Pv3pQ$j F:0:(ֆӀ,?Ix‚;1I2%NϏFYTXڅC81QI[<5@u=)@#JB RS @m-)OwrJHʂTj0q`th Y=H*X #`hDW!n%.u(s',*oChnvAW)FٳX7W"{?RM?8 IՊOw?I8YDi:)U"ɂA"Fw0q,M@㿶w 4Z]pmCzd׮ zy2WEG\,Tż0mQ_4reкJ}q;f׆ei/(-7(SF\a+?W6ϼyoс=ӷoYRUDw5'*+^~i^:ezr%v@["oMЉoBFǦwV`oBζdC\KY͚/N8C3ufɋuo-vyJ,qd&|@vV~K.BZNk**>Ws`6m4[% vXfYW_m W# ko-Z'{G-i`<3p|SwDwNm۷/am^;~76gy"7I 貂{UoIzRnLK*gZvnznBYz~N̼U{k',o\l&(зmŢy{| Zw|:u3Blm|F 6Zg,+®ڭK3RUJm캡a"׼O&yﱲI3 LsV..\ۯ:18mNw2''3S֭lO_ ]̥=DKLYz/}tí7+}9\6O7.L*>}ߊȮ.Mc-'L=!id6?B!o߆WR8u T:qǻGIe_שkuolB|b:uNWZ| 9>/gN3;Q^:]8H/2v{;  9v*0=?ʡa_{] *^]g]=zw.uYoqh%AY}|XUGw^ r\izEf< ^/:T}%㓫x!Ɏ[D.7__^!qQ)F )uT|\tU\ MIO ,MXX|tHm,幹p h<%YKQl[#IMQPg'LC((f2!4SrSiF;2q(>EDH(+oI!e<H8I$~?-R Hdesc/tests/testthat/fixtures/xxx.zip0000644000176200001440000000024013140567212017413 0ustar liggesusersPK U8JgtxxxUT 0XXux xxx PK U8JgtxxxUT0Xux PKIAdesc/tests/testthat/fixtures/xxx.gz0000644000176200001440000000003413140567212017232 0ustar liggesusers0Xxxxgtdesc/tests/testthat/test-idempotent.R0000644000176200001440000000144613140567212017450 0ustar liggesusers context("Nice behavior") test_that("dependencies are not reformatted if new value is the same", { desc <- description$new("D1") desc$set("Imports", "R6") before <- desc$get("Imports") desc$set_dep("R6") after <- desc$get("Imports") expect_equal(before, after) desc <- description$new("D1") desc$set("Imports", "R6") before <- desc$get("Imports") desc$set_deps(data.frame(package = "R6", type = "Imports", version = "*")) after <- desc$get("Imports") expect_equal(before, after) }) test_that("collate fields are not reformatted if new value is the same", { desc <- description$new("D1") desc$set("Collate", "'foo.R' 'bar.R' foobar.R") before <- desc$get("Collate") desc$set_collate(desc$get_collate()) after <- desc$get("Collate") expect_equal(before, after) }) desc/tests/testthat/test-repair.R0000644000176200001440000000277613140567212016571 0ustar liggesuserscontext("repair") test_that("normalization", { desc <- description$new("!new") desc$set("Imports", "foo, bar, foobar") before_fields <- desc$fields() before_data <- desc$get(before_fields) desc$normalize() after_fields <- desc$fields() after_data <- desc$get(after_fields) expect_equal(sort(before_fields), sort(after_fields)) expect_lt(match("Imports", after_fields), match("Imports", before_fields)) expect_gt(match("LazyData", after_fields), match("LazyData", before_fields)) expect_equal(after_data[["Imports"]], "\n foo,\n bar,\n foobar") }) test_that("reformatting", { desc <- description$new("!new") desc$set("Imports", "foo, bar, foobar") before_fields <- desc$fields() before_data <- desc$get(before_fields) desc$reformat_fields() after_fields <- desc$fields() after_data <- desc$get(after_fields) expect_equal(before_fields, after_fields) expect_equal(after_data[["Imports"]], "\n foo,\n bar,\n foobar") }) test_that("reordering", { desc <- description$new("!new") desc$set("Imports", "foo, bar, foobar") before_fields <- desc$fields() before_data <- desc$get(before_fields) desc$reorder_fields() after_fields <- desc$fields() after_data <- desc$get(after_fields) expect_equal(sort(before_fields), sort(after_fields)) expect_lt(match("Imports", after_fields), match("Imports", before_fields)) expect_gt(match("LazyData", after_fields), match("LazyData", before_fields)) expect_identical(before_data[after_fields], after_data) }) desc/tests/testthat/D10000644000176200001440000000074713140567212014372 0ustar liggesusersPackage: desc Title: Manipulate DESCRIPTION Files Version: 1.0.0 Author: Gábor Csárdi Maintainer: Gábor Csárdi Description: Tools to read, write, create, and manipulate DESCRIPTION files. It is intented for packages that create or manipulate other packages. License: MIT + file LICENSE URL: https://github.com/r-pkgs/desc BugReports: https://github.com/r-pkgs/desc/issues Imports: R6 Suggests: testthat VignetteBuilder: knitr Encoding: UTF-8 desc/tests/testthat/test-urls.R0000644000176200001440000000206113244347461016266 0ustar liggesusers context("URL") test_that("get, set, etc. urls", { desc <- description$new("D2") expect_identical( desc$get_urls(), "https://github.com/klutometis/roxygen" ) desc$set_urls(c("https://foo.bar", "http://x.y")) expect_identical(desc$get_urls(), c("https://foo.bar", "http://x.y")) desc$add_urls("http://another.one") expect_identical( desc$get_urls(), c("https://foo.bar", "http://x.y", "http://another.one") ) desc$del_urls("^http://") expect_identical(desc$get_urls(), "https://foo.bar") desc$clear_urls() expect_identical(desc$get_urls(), character()) desc$add_urls("http://another.one") expect_identical(desc$get_urls(), "http://another.one") desc$del_urls("another.one") expect_identical(desc$get_urls(), character()) expect_identical(desc$get("URL"), c(URL = NA_character_)) }) test_that("leading newlines and embedded descriptors are ignored", { desc <- description$new("D8") expect_identical( desc$get_urls(), c("https://github.com/ropensci/hunspell#readme", "https://hunspell.github.io") ) }) desc/tests/testthat/test-to_latex.R0000644000176200001440000000122413202435270017106 0ustar liggesuserscontext("to_latex") test_that("Test expected LaTeX output", { desc <- description$new("!new") desc$set_authors(person("Kirill", "Müller", email = "aaa@bbb.xx", role = "cre")) desc$set(Package = "Test.Package", Title = "Must be in Title Case", Description = "Words not in the dictionary must be 'quoted'. \"Double quotes\" can also be used, as well as \\_{}[]^$#%. Must end with a full stop.", License = "CC-BY-SA", URL = "http://somewhere.io, http://somewhereel.se", BugReports = "http://somewhere.io/trac") expect_output_file(print(desc$to_latex()), "output/to_latex.tex", update = FALSE) }) desc/tests/testthat/D70000644000176200001440000000164613202453765014405 0ustar liggesusersPackage: doBy Version: 4.5-15 Title: Groupwise Statistics, LSmeans, Linear Contrasts, Utilities Author: Sren Hjsgaard and Ulrich Halekoh Maintainer: Sren Hjsgaard Description: The facilities can roughly be grouped as: . 1) Facilities for groupwise computations of summary statistics and other facilities for working with grouped data: 'do' something to data stratified 'by' some variables. . 2) LSmeans (least-squares means), general linear contrasts. . 3) Miscellaneous other utilities. Encoding: latin1 URL: http://people.math.aau.dk/~sorenh/software/doBy/ ZipData: no License: GPL (>= 2) Depends: R (>= 3.2.0), methods Imports: MASS, Matrix Suggests: pbkrtest (>= 0.4-6), ggplot2, multcomp, geepack, lme4, survival NeedsCompilation: no Packaged: 2016-03-31 03:26:07 UTC; sorenh Repository: CRAN Date/Publication: 2016-03-31 17:38:50 desc/tests/testthat/test-collate.R0000644000176200001440000000721213140567212016720 0ustar liggesusers context("Collate API") test_that("set_collate and get_collate work", { desc <- description$new("D1") files <- c("foo.R", "bar.R", "foobar.R") desc$set_collate(files) expect_equal(desc$get_collate(), files) expect_equal(desc$get_collate(which = "windows"), character()) expect_equal(desc$get_collate(which = "unix"), character()) files2 <- c(files, "foo-win.R") desc$set_collate(files2, which = "windows") expect_equal(desc$get_collate("windows"), files2) expect_equal(desc$get_collate(which = "main"), files) expect_equal(desc$get_collate(which = "unix"), character()) files3 <- c(files, "foo-unix.R") desc$set_collate(files3, which = "unix") expect_equal(desc$get_collate(which = "unix"), files3) expect_equal(desc$get_collate(which = "windows"), files2) expect_equal(desc$get_collate(which = "main"), files) }) test_that("del_collate works", { desc <- description$new("D1") files <- c("foo.R", "bar.R", "foobar.R") files2 <- c(files, "foo-win.R") files3 <- c(files, "foo-unix.R") desc$set_collate(files, which = "main") desc$set_collate(files2, which = "windows") desc$set_collate(files3, which = "unix") desc$del_collate(which = "windows") expect_equal(desc$get_collate(which = "windows"), character()) expect_equal(desc$get_collate(which = "main"), files) expect_equal(desc$get_collate(which = "unix"), files3) desc$del_collate() expect_equal(desc$get_collate(which = "windows"), character()) expect_equal(desc$get_collate(which = "main"), character()) expect_equal(desc$get_collate(which = "unix"), character()) }) test_that("add_to_collate works", { desc <- description$new("D1") desc$add_to_collate("bar.R") expect_equal(desc$get_collate(), "bar.R") desc$add_to_collate("foo.R") expect_equal(desc$get_collate(), c("bar.R", "foo.R")) desc$add_to_collate("foobar.R", which = "windows") expect_equal(desc$get_collate(), c("bar.R", "foo.R")) expect_equal(desc$get_collate(which = "windows"), "foobar.R") desc$add_to_collate("foobar2.R") expect_equal(desc$get_collate(), c("bar.R", "foo.R", "foobar2.R")) expect_equal(desc$get_collate(which = "windows"), c("foobar.R", "foobar2.R")) }) test_that("del_from_collate works", { desc <- description$new("D1") files <- c("foo.R", "bar.R", "foobar.R") files2 <- c(files, "foo-win.R") files3 <- c(files, "foo-unix.R") desc$set_collate(files, which = "main") desc$set_collate(files2, which = "windows") desc$set_collate(files3, which = "unix") desc$del_from_collate("foo.R") expect_equal(desc$get_collate(which = "main"), c("bar.R", "foobar.R")) expect_equal(desc$get_collate(which = "windows"), c("bar.R", "foobar.R", "foo-win.R")) expect_equal(desc$get_collate(which = "unix"), c("bar.R", "foobar.R", "foo-unix.R")) desc$del_from_collate("bar.R", which = "windows") expect_equal(desc$get_collate(which = "main"), c("bar.R", "foobar.R")) expect_equal(desc$get_collate(which = "windows"), c("foobar.R", "foo-win.R")) expect_equal(desc$get_collate(which = "unix"), c("bar.R", "foobar.R", "foo-unix.R")) }) test_that("add to all collate fields", { desc <- description$new("D1") desc$set_collate(c("f1.R", "f2.R"), which = "main") desc$set_collate(c("f3.R", "f4.R"), which = "win") desc$add_to_collate("f5.R", which = "all") expect_equal( desc$get_collate(which = "main"), c("f1.R", "f2.R", "f5.R") ) expect_equal( desc$get_collate(which = "win"), c("f3.R", "f4.R", "f5.R") ) }) test_that("deleting from non-existing collate does nothing", { desc <- description$new("D1") expect_silent(desc$del_from_collate('foo.R')) }) desc/tests/testthat/D20000644000176200001440000000267013140567212014370 0ustar liggesusersPackage: roxygen2 Title: In-Source Documentation for R Description: A 'Doxygen'-like in-source documentation system for Rd, collation, and 'NAMESPACE' files. URL: https://github.com/klutometis/roxygen Version: 4.1.1.9000 License: GPL (>= 2) Authors@R: c( person("Hadley", "Wickham",, "h.wickham@gmail.com", c("aut", "cre", "cph")), person("Peter", "Danenberg",, "pcd@roxygen.org", c("aut", "cph")), person("Manuel", "Eugster", role = c("aut", "cph")), person("RStudio", role = "cph") ) Depends: R (>= 3.0.2) Imports: stringr (>= 0.5), brew, digest, methods, Rcpp (>= 0.11.0) Suggests: testthat (>= 0.8.0), knitr VignetteBuilder: knitr LinkingTo: Rcpp Collate: 'RcppExports.R' 'alias.R' 'description.R' 'family.R' 'inherit-params.R' 'minidesc.R' 'object-defaults.R' 'object-from-call.R' 'object.R' 'order-params.R' 'parse-preref.R' 'parse-registry.R' 'parse.R' 'rc.R' 'rd-escape.R' 'rd-file-api.R' 'rd-parse.R' 'rd-tag-api.R' 'roclet-collate.R' 'roclet-namespace.R' 'roclet-rd.R' 'roclet-vignette.R' 'roclet.R' 'roxygen.R' 'roxygenize.R' 's3.R' 'safety.R' 'source.R' 'template.R' 'topic-name.R' 'topo-sort.R' 'usage.R' 'util-locale.R' 'utils.R' RoxygenNote: 4.1.1.9000 Encoding: UTF-8 Remotes: foo/digest, svn::https://github.com/hadley/stringr, local::/pkgs/testthat desc/tests/testthat/test-checks.R0000644000176200001440000000711313140567212016535 0ustar liggesusers context("Syntax checks") test_that("checking other fields is always ok", { desc <- description$new("D1") desc$set("Note", "Blah-blah") expect_equal(desc$get("Note"), c(Note = "Blah-blah")) }) test_that("we catch syntax errors", { desc <- description$new("D1") expect_warning( desc$set("Package", "444!!! not a valid package name"), "must only contain ASCII letters.*must start with a letter" ) expect_warning( desc$set("Package", "4aaaa"), "must start with a letter" ) }) test_that("generic field check is always true", { field <- list(key = "XY", value = "foobar") class(field) <- "DescriptionField" expect_silent(check_field(field, warn = TRUE)) expect_true(check_field(field)) }) test_chk <- function(field, value, warn_msg, warn = TRUE, class = field) { rec <- list(key = field, value = value) class(rec) <- c(paste0("Description", class), "DescriptionField") test_that(paste(field, "syntax"), { if (warn) { expect_warning(check_field(rec, warn = TRUE), warn_msg) } else { expect_silent(check_field(rec, warn = TRUE)) } }) } test_chk("License", "GPL", warn = FALSE) test_chk("License", "", "must not be empty") test_chk("License", "almost good but \x80", "only ASCII characters") test_chk("Title", "This is a Good Title", warn = FALSE) test_chk("Title", "", "must not be empty") test_chk("Title", "Not a good title.", "must not end with a period") test_chk("Title", "Good title by Bugs Bunny et al.", warn = FALSE) test_chk("Maintainer", "Bugs Bunny ", warn = FALSE) test_chk("Maintainer", "ORPHANED", warn = FALSE) test_chk("Maintainer", "", "must not be empty") test_chk("Maintainer", "foobar", "must contain an email address") test_chk("RepoList", "", warn = FALSE) test_chk("RepoList", "http://cran.rstudio.com", warn = FALSE) test_chk("RepoList", "http://cran.rstudio.com, https://cran.r-project.org", warn = FALSE) test_chk("RepoList", "foobar", "must be a comma .* repository URLs") test_chk("RepoList", "http://foo.bar http://fobar", "must be a comma") test_chk("URL", "http://acme.com", warn = FALSE) test_chk("URL", "not this one", "must be a http, https or ftp URL") test_chk("URLList", "", warn = FALSE) test_chk("URLList", "http://cran.rstudio.com", warn = FALSE) test_chk("URLList", "http://cran.rstudio.com, https://cran.r-project.org", warn = FALSE) test_chk("URLList", "foobar", "must be a comma .* URLs") test_chk("URLList", "http://foo.bar http://fobar", "must be a comma") test_chk("Priority", "recommended", warn = FALSE) test_chk("Priority", "foobar", "must be one of") test_chk("LazyLoad", "yes", warn = FALSE, class = "Logical") test_chk("LazyLoad", "foobar", "must be one of", class = "Logical") test_chk("VignetteBuilder", "devtools, knitr", warn = FALSE, class = "PackageList") test_chk("VignetteBuilder", "this is not", "must be a comma", class = "PackageList") test_chk("Encoding", "UTF-8", warn = FALSE) test_chk("Encoding", "foobar", "must be one of") test_chk("OSType", "unix", warn = FALSE) test_chk("OSType", "foobar", "must be one of") test_chk("Type", "Translation", warn = FALSE) test_chk("Type", "foobar", "must be either") test_chk("Classification", "", warn = FALSE) test_chk("Language", "hun, deu", warn = FALSE) test_chk("Language", "this is not", "must be a list of IETF language") test_chk("Date", "2015-01-21", warn = FALSE) test_chk("Date", "foobar", "must be an ISO date") test_chk("Compression", "gzip", warn = FALSE) test_chk("Compression", "foobar", "must be one of") test_chk("Repository", "", warn = FALSE) test_chk("AddedByRCMD", "", warn = FALSE) desc/tests/testthat/test-write.R0000644000176200001440000000210513272064467016435 0ustar liggesusers context("Write") test_that("can write to file", { desc <- description$new("!new") tmp <- tempfile() desc$write(tmp) desc2 <- description$new(tmp) expect_equal(desc$str(), desc2$str()) }) test_that("normalization while writing to file", { desc <- description$new("!new") desc$set("Imports", "foo, bar, foobar") tmp <- tempfile() desc$write(tmp) desc$normalize() desc2 <- description$new(tmp) expect_equal(desc$str(), desc2$str()) }) test_that("whitespace after : if field was updated", { on.exit(unlink(c(t1, t2), recursive = TRUE), add = TRUE) ## Space is kept if it was there desc <- description$new(text = "Imports: \n one,\n two\n") desc$set_dep("doh") desc$write(t1 <- tempfile()) expect_equal( readLines(t1), c("Imports: ", " one,", " two,", " doh") ) ## Space is not added if it was not there desc <- description$new(text = "Imports:\n one,\n two\n") desc$set_dep("doh") desc$write(t2 <- tempfile()) expect_equal( readLines(t2), c("Imports:", " one,", " two,", " doh") ) }) desc/tests/testthat/test-create.R0000644000176200001440000000430713140567212016542 0ustar liggesusers context("Constructors") test_that("can create new object", { desc <- description$new("!new") expect_true(!is.na(desc$get("Package"))) expect_true(!is.na(desc$get("Title"))) expect_true(!is.na(desc$get("Version"))) expect_true(!is.na(desc$get("Authors@R"))) expect_true(!is.na(desc$get("Maintainer"))) expect_true(!is.na(desc$get("Description"))) expect_true(!is.na(desc$get("License"))) expect_true(!is.na(desc$get("LazyData"))) expect_true(!is.na(desc$get("URL"))) expect_true(!is.na(desc$get("BugReports"))) }) test_that("can read object from file", { desc <- description$new("D1") expect_true(!is.na(desc$get("Package"))) expect_true(!is.na(desc$get("Title"))) expect_true(!is.na(desc$get("Version"))) expect_true(!is.na(desc$get("Author"))) expect_true(!is.na(desc$get("Maintainer"))) expect_true(!is.na(desc$get("Description"))) expect_true(!is.na(desc$get("License"))) expect_true(!is.na(desc$get("URL"))) expect_true(!is.na(desc$get("BugReports"))) }) test_that("can read object from character vector", { lines <- readLines("D1") desc <- description$new(text = lines) expect_true(!is.na(desc$get("Package"))) expect_true(!is.na(desc$get("Title"))) expect_true(!is.na(desc$get("Version"))) expect_true(!is.na(desc$get("Author"))) expect_true(!is.na(desc$get("Maintainer"))) expect_true(!is.na(desc$get("Description"))) expect_true(!is.na(desc$get("License"))) expect_true(!is.na(desc$get("URL"))) expect_true(!is.na(desc$get("BugReports"))) }) test_that("DESCRPTION is read by default", { wd <- getwd() on.exit(setwd(wd), add = TRUE) setwd("files") d1 <- description$new() d2 <- description$new("DESCRIPTION") expect_equal(d1, d2) }) test_that("From installed package", { desc <- description$new(package = "utils") expect_match(desc$get("Author"), "Core Team") expect_error( description$new(package = "fgsdgsdhldsknfglkedsfgsdf"), "Cannot find DESCRIPTION for installed package" ) }) test_that("Package root is found", { wd <- getwd() on.exit(setwd(wd), add = TRUE) setwd("files") d1 <- description$new() dir.create("subdir", showWarnings = FALSE) setwd("subdir") d2 <- description$new() expect_equal(d1, d2) }) desc/tests/testthat/test-validation.R0000644000176200001440000000025413140567212017426 0ustar liggesusers context("Validation") test_that("validation is not implemented", { desc <- description$new("!new") expect_warning( desc$validate(), "not implemented" ) }) desc/tests/testthat/test-non-oo.R0000644000176200001440000001310713244347461016511 0ustar liggesusers context("Non OO API") test_that("desc_add_author", { d <- temp_desc() on.exit(unlink(d)) x <- desc_add_author(file = d, "Bunny", "Bugs", "bugs.bunny@acme.com") expect_match(desc_get(file = d, "Authors@R"), "Bunny") }) test_that("desc_add_me", { d <- temp_desc() on.exit(unlink(d)) with_mock( `whoami::fullname` = function() "First Last", `whoami::email_address` = function() "first.last@dom.com", x <- desc_add_me(file = d) ) expect_match(desc_get(file = d, "Authors@R"), "First") expect_match(desc_get(file = d, "Authors@R"), "first.last@dom.com") }) test_that("desc_add_role", { d <- temp_desc() on.exit(unlink(d)) x <- desc_add_role(file = d, "ctb", given = "Manuel") expect_match( as.character(desc_get_author(file = d, role = "ctb")), "Manuel" ) }) test_that("desc_add_to_collate et al.", { d <- temp_desc() on.exit(unlink(d)) expect_true("roxygenize.R" %in% desc_get_collate(file = d)) x <- desc_del_from_collate(file = d, "roxygenize.R") expect_false("roxygenize.R" %in% desc_get_collate(file = d)) x <- desc_add_to_collate(file = d, "roxygenize.R") expect_true("roxygenize.R" %in% desc_get_collate(file = d)) }) test_that("desc_get_maintainer, desc_change_maintainer", { d <- temp_desc() on.exit(unlink(d)) expect_match( as.character(desc_get_maintainer(file = d)), "Hadley" ) x <- desc_change_maintainer(file = d, given = "Peter") expect_match( as.character(desc_get_maintainer(file = d)), "Peter" ) }) test_that("desc_set, desc_get, desc_del", { d <- temp_desc() on.exit(unlink(d)) expect_equal( desc_get(file = d, c("Package", "Version")), c(Package = "roxygen2", Version = "4.1.1.9000") ) desc_set(file = d, Package = "foobar") expect_equal( desc_get(file = d, c("Package", "Version")), c(Package = "foobar", Version = "4.1.1.9000") ) }) test_that("desc_del_author", { d <- temp_desc() on.exit(unlink(d)) desc_del_author(file = d, given = "Peter") expect_false( any(grepl("Peter", as.character(desc_get_authors(file = d)))) ) }) test_that("desc_del_collate", { d <- temp_desc() on.exit(unlink(d)) desc_del_collate(file = d) expect_equal( desc_get(file = d, "Collate"), c(Collate = NA_character_) ) }) test_that("desc_del_dep", { d <- temp_desc() on.exit(unlink(d)) expect_true( "testthat" %in% desc_get_deps(file = d)$package ) desc_del_dep(file = d, "testthat") expect_false( "testthat" %in% desc_get_deps(file = d)$package ) }) test_that("desc_del_deps", { d <- temp_desc() on.exit(unlink(d)) desc_del_deps(file = d) expect_equal(nrow(desc_get_deps(file = d)), 0) }) test_that("desc_del_role", { d <- temp_desc() on.exit(unlink(d)) desc_del_role(file = d, "aut", given = "Manuel") expect_false( any(grepl("Manuel", desc_get_author(file = d, role = "aut"))) ) }) test_that("desc_fields", { d <- temp_desc() on.exit(unlink(d)) expect_true( all(c("Package", "Title", "Version", "URL", "Collate") %in% desc_fields(file = d)) ) }) test_that("desc_has_fields", { d <- temp_desc() on.exit(unlink(d)) expect_equal( desc_has_fields(file = d, c("Package", "foobar", "Collate")), c(TRUE, FALSE, TRUE) ) }) test_that("desc_normalize", { d <- temp_desc() on.exit(unlink(d)) desc <- description$new(d) desc_normalize(file = d) desc$normalize() d2 <- tempfile() on.exit(unlink(d2), add = TRUE) desc$write(d2) expect_equal(readLines(d), readLines(d2)) }) test_that("desc_print", { d <- temp_desc() on.exit(unlink(d)) capt <- capture.output(description$new("D2")$print()) expect_output( desc_print(file = d), paste(capt, collapse = "\n"), fixed = TRUE ) }) test_that("desc_reformat_fields", { d <- temp_desc() on.exit(unlink(d)) desc_reformat_fields(file = d) expect_equal( desc_get(file = d, "Description"), description$new("D2")$reformat_fields()$get("Description") ) }) test_that("desc_reorder_fields", { d <- temp_desc() on.exit(unlink(d)) desc_reorder_fields(file = d) expect_equal( desc_fields(file = d), c("Package", "Title", "Version", "Authors@R", "Description", "License", "URL", "Depends", "Imports", "Suggests", "LinkingTo", "VignetteBuilder", "Remotes", "Encoding", "RoxygenNote", "Collate") ) }) test_that("desc_set_authors", { d <- temp_desc("D1") on.exit(unlink(d)) desc_set_authors(file = d, desc_get_authors(file = "D2")) expect_equal( desc_get_authors(file = d), desc_get_authors("D2") ) }) test_that("desc_set_collate", { d <- temp_desc() on.exit(unlink(d)) desc_set_collate(file = d, c("foo.R", "bar.R")) expect_equal( desc_get_collate(file = d), c("foo.R", "bar.R") ) }) test_that("desc_set_dep", { d <- temp_desc() on.exit(unlink(d)) desc_set_dep(file = d, "foobar", type = "Suggests") expect_true( "foobar" %in% desc_get_deps(file = d)$package ) }) test_that("desc_set_deps", { d <- temp_desc() on.exit(unlink(d)) desc_set_deps(file = d, desc_get_deps(file = "D1")) expect_equal( desc_get_deps(file = d), desc_get_deps(file = "D1") ) }) test_that("desc_to_latex", { expect_equal( desc_to_latex(file = "D2"), description$new("D2")$to_latex() ) }) test_that("desc_validate", { expect_warning( desc_validate(file = "D1"), "not implemented" ) }) test_that("can write back automatically found DESCRIPTION file", { dir.create(tmp <- tempfile()) file.copy(file.path("files", "DESCRIPTION"), tmp) withr::with_dir( tmp, desc_set_dep("somepackage", "Suggests") ) expect_true("somepackage" %in% desc_get_deps(file = tmp)$package) }) desc/tests/testthat/D50000644000176200001440000000066313140567212014373 0ustar liggesusersPackage: desc Title: Manipulate DESCRIPTION Files Version: 1.0.0 Author: Gábor Csárdi Maintainer: Gábor Csárdi Description: Tools to read, write, create, and manipulate DESCRIPTION files. It is intented for packages that create or manipulate other packages. License: MIT + file LICENSE Imports: httrmock, lintr Remotes: jimhester/lintr Encoding: UTF-8 Remotes: gaborcsardi/httrmock desc/tests/testthat/test-deps.R0000644000176200001440000000772513174052164016243 0ustar liggesusers context("Dependencies") test_that("get_deps", { desc <- description$new("D1") res <- data.frame( stringsAsFactors = FALSE, type = c("Imports", "Suggests"), package = c("R6", "testthat"), version = c("*", "*") ) expect_equal(desc$get_deps(), res) }) test_that("set_dep", { desc <- description$new("D1") desc$set_dep("igraph") res <- data.frame( stringsAsFactors = FALSE, type = c("Imports", "Imports", "Suggests"), package = c("R6", "igraph", "testthat"), version = c("*", "*", "*") ) expect_equal(desc$get_deps(), res) desc$set_dep("igraph", version = ">= 1.0.0") res <- data.frame( stringsAsFactors = FALSE, type = c("Imports", "Imports", "Suggests"), package = c("R6", "igraph", "testthat"), version = c("*", ">= 1.0.0", "*") ) expect_equal(desc$get_deps(), res) desc$set_dep("igraph", type = "Depends", version = ">= 1.0.0") res <- data.frame( stringsAsFactors = FALSE, type = c("Imports", "Imports", "Suggests", "Depends"), package = c("R6", "igraph", "testthat", "igraph"), version = c("*", ">= 1.0.0", "*", ">= 1.0.0") ) expect_equal(desc$get_deps(), res) }) test_that("set_dep for the first dependency", { desc <- description$new("!new") expect_equal(eval(formals(desc$set_dep)[["type"]])[[1L]], "Imports") desc$set_dep("igraph") res <- data.frame( stringsAsFactors = FALSE, type = c("Imports"), package = c("igraph"), version = c("*") ) expect_equal(desc$get_deps(), res) }) test_that("del_dep", { desc <- description$new("D1") desc$set_dep("igraph") desc$set_dep("igraph", type = "Depends", version = ">= 1.0.0") desc$del_dep("igraph") res <- data.frame( stringsAsFactors = FALSE, type = c("Imports", "Suggests"), package = c("R6", "testthat"), version = c("*", "*") ) expect_equal(desc$get_deps(), res) desc <- description$new("D1") desc$set_dep("igraph") desc$set_dep("igraph", type = "Depends", version = ">= 1.0.0") desc$del_dep("igraph", type = "Imports") res <- data.frame( stringsAsFactors = FALSE, type = c("Imports", "Suggests", "Depends"), package = c("R6", "testthat", "igraph"), version = c("*", "*", ">= 1.0.0") ) expect_equal(desc$get_deps(), res) }) test_that("deleting all dependencies", { desc <- description$new("D1") desc$del_deps() expect_equal(desc$get("Imports"), c(Imports = NA_character_)) expect_equal(desc$get("Suggests"), c(Suggests = NA_character_)) }) test_that("deleting a non-dependency is OK", { desc <- description$new("D1") before <- desc$get("Imports") desc$del_dep("foobar", "Imports") after <- desc$get("Imports") expect_equal(before, after) }) test_that("has_dep", { desc <- description$new("D1") expect_true(desc$has_dep("R6")) expect_true(desc$has_dep("testthat")) expect_true(desc$has_dep("R6", "Imports")) expect_true(desc$has_dep("testthat", "Suggests")) expect_false(desc$has_dep("foobar")) expect_false(desc$has_dep("testthat", "Imports")) expect_error(desc$has_dep(123)) expect_error(desc$has_dep("testthat", "xxx")) }) test_that("issue #34 is fine (empty dep fields)", { empty_deps <- data.frame( stringsAsFactors = FALSE, type = character(), package = character(), version = character() ) desc <- description$new("D4") expect_silent(deps <- desc$get_deps()) expect_equal(deps, empty_deps) desc$set(Imports = "") expect_silent(deps <- desc$get_deps()) expect_equal(deps, empty_deps) expect_silent(desc$set_deps(deps)) expect_silent(deps <- desc$get_deps()) expect_equal(deps, empty_deps) }) test_that("no dependencies at all", { empty_deps <- data.frame( stringsAsFactors = FALSE, type = character(), package = character(), version = character() ) desc <- description$new("D6") expect_silent(deps <- desc$get_deps()) expect_equal(deps, empty_deps) expect_silent(desc$set_deps(deps)) expect_silent(deps <- desc$get_deps()) expect_equal(deps, empty_deps) }) desc/tests/testthat/D60000644000176200001440000000063413174052160014370 0ustar liggesusersPackage: desc Title: Manipulate DESCRIPTION Files Version: 1.0.0 Author: Gábor Csárdi Maintainer: Gábor Csárdi Description: Tools to read, write, create, and manipulate DESCRIPTION files. It is intented for packages that create or manipulate other packages. License: MIT + file LICENSE Encoding: UTF-8 Built: R 3.4.1; x86_64-apple-darwin15.6.0; 2017-09-14 20:30:19 UTC; unix desc/tests/testthat/D30000644000176200001440000000254213140567212014367 0ustar liggesusersPackage: roxygen2 Title: In-Source Documentation for R Description: A 'Doxygen'-like in-source documentation system for Rd, collation, and 'NAMESPACE' files. URL: https://github.com/klutometis/roxygen Version: 4.1.1.9000 License: GPL (>= 2) Authors@R: c( person("Hadley", "Wickham",, "h.wickham@gmail.com", c("aut", "cre", "cph")), person("Peter", "Danenberg",, "pcd@roxygen.org", c("aut", "cph")), person("Manuel", "Eugster", role = c("aut", "cph")), person("RStudio", role = "cph") ) Depends: R (>= 3.0.2) Imports: stringr (>= 0.5), brew, digest, methods, Rcpp (>= 0.11.0) Suggests: testthat (>= 0.8.0), knitr VignetteBuilder: knitr LinkingTo: Rcpp Collate: 'RcppExports.R' 'alias.R' 'description.R' 'family.R' 'inherit-params.R' 'minidesc.R' 'object-defaults.R' 'object-from-call.R' 'object.R' 'order-params.R' 'parse-preref.R' 'parse-registry.R' 'parse.R' 'rc.R' 'rd-escape.R' 'rd-file-api.R' 'rd-parse.R' 'rd-tag-api.R' 'roclet-collate.R' 'roclet-namespace.R' 'roclet-rd.R' 'roclet-vignette.R' 'roclet.R' 'roxygen.R' 'roxygenize.R' 's3.R' 'safety.R' 'source.R' 'template.R' 'topic-name.R' 'topo-sort.R' 'usage.R' 'util-locale.R' 'utils.R' RoxygenNote: 4.1.1.9000 Encoding: UTF-8 desc/tests/testthat/output/0000755000176200001440000000000013140567212015533 5ustar liggesusersdesc/tests/testthat/output/to_latex.tex0000644000176200001440000000126413202433131020066 0ustar liggesusers\begin{description} \raggedright{} \item[Package] Test.Package \item[Title] Must be in Title Case \item[Version] 1.0.0 \item[Authors@R] ~\\ \begin{description} \item[cre] Kirill Müller <\href{mailto:aaa@bbb.xx}{aaa@bbb.xx}> \end{description} \item[Maintainer] \{\{ Maintainer \}\} \item[Description] Words not in the dictionary must be `quoted'. ``Double quotes'' can also be used, as well as \textbackslash \_\{\}[]\^\$\#\%. Must end with a full stop. \item[License] CC-BY-SA \item[URL] \url{http://somewhere.io}, \url{http://somewhereel.se} \item[BugReports] \url{http://somewhere.io/trac} \item[Encoding] UTF-8 \item[LazyData] true \end{description} desc/tests/testthat/test-trailing-ws.R0000644000176200001440000000261013140567212017532 0ustar liggesusers context("Absense of trailing WS is kept") test_that("No WS is kept if field is not modified", { d <- description$new("D3") tmp <- tempfile() on.exit(unlink(tmp), add = TRUE) d$write(tmp) expect_equal(readLines("D3"), readLines(tmp)) }) test_that("WS is present in newly created fields", { d <- description$new("D3") tmp <- tempfile() on.exit(unlink(tmp), add = TRUE) d$set("Foobar" = "\n TRAZ") d$write(tmp) contents <- paste0(paste0(readLines(tmp), collapse = "\n"), "\n") expect_match(contents, "\nFoobar: \n TRAZ\n") }) test_that("WS is present in newly created files", { desc <- description$new("!new") tmp <- tempfile() on.exit(unlink(tmp), add = TRUE) desc$write(tmp) contents <- paste0(readLines(tmp), collapse = "\n") expect_match(contents, "\nAuthors@R: \n") }) test_that("WS is added if field is changed", { d <- description$new("D3") tmp <- tempfile() on.exit(unlink(tmp), add = TRUE) d$add_author("Gabor", "Csardi", "foo@bar.com") d$write(tmp) contents <- paste0(readLines(tmp), collapse = "\n") expect_match(contents, "Authors@R: \n") }) test_that("No WS is added if an other field is changed", { d <- description$new("D3") tmp <- tempfile() on.exit(unlink(tmp), add = TRUE) d$add_author("Gabor", "Csardi", "foo@bar.com") d$write(tmp) contents <- paste0(readLines(tmp), collapse = "\n") expect_match(contents, "Imports:\n") }) desc/tests/testthat/test-authors.R0000644000176200001440000001164713202436770016774 0ustar liggesusers context("Authors") test_that("we can get the authors", { desc <- description$new("D2") ans <- c( person("Hadley", "Wickham", email = "h.wickham@gmail.com", role = c("aut", "cre", "cph")), person("Peter", "Danenberg", email = "pcd@roxygen.org", role = c("aut", "cph")), person("Manuel", "Eugster", role = c("aut", "cph")), person("RStudio", role = "cph") ) expect_identical(desc$get_authors(), ans) }) test_that("we can set the authors", { desc1 <- description$new("D1") desc2 <- description$new("D2") desc1$set_authors(desc2$get_authors()) expect_identical(desc1$get_authors(), desc2$get_authors()) }) test_that("we can add an author", { desc <- description$new("D2") desc$add_author("Gábor", "Csárdi", email = "csardi.gabor@gmail.com", role = "ctb", comment = "Really?") expect_identical( format(desc$get_authors()[5]), "Gábor Csárdi [ctb] (Really?)" ) }) test_that("we can search for authors", { desc <- description$new("D2") authors <- desc$get_authors() expect_equal( search_for_author(authors, given = "Hadley")$index, 1L ) }) test_that("we can add a role to an author", { desc <- description$new("D2") desc$add_author("Gábor", "Csárdi", email = "csardi.gabor@gmail.com", role = "ctb", comment = "Really?") desc$add_role(given = "Gábor", role = "cph") expect_identical( format(desc$get_authors()[5]), "Gábor Csárdi [ctb, cph] (Really?)" ) }) test_that("we can delete an author", { desc <- description$new("D2") desc$del_author(given = "Hadley") desc$del_author(family = "Danenberg") ans <- c( person("Manuel", "Eugster", role = c("aut", "cph")), person("RStudio", role = "cph") ) expect_identical(desc$get_authors(), ans) }) test_that("we can delete a role", { desc <- description$new("D2") desc$add_author("Gábor", "Csárdi", email = "csardi.gabor@gmail.com", role = "ctb", comment = "Really?") desc$add_role(given = "Gábor", role = "cph") desc$del_role(family = "Csárdi", role = "ctb") expect_identical( format(desc$get_authors()[5]), "Gábor Csárdi [cph] (Really?)" ) }) test_that("we can change the maintainer", { desc <- description$new("D2") desc$change_maintainer(given = "Peter") ans <- c( person("Hadley", "Wickham", email = "h.wickham@gmail.com", role = c("aut", "cph")), person("Peter", "Danenberg", email = "pcd@roxygen.org", role = c("aut", "cph", "cre")), person("Manuel", "Eugster", role = c("aut", "cph")), person("RStudio", role = "cph") ) expect_identical(desc$get_authors(), ans) }) test_that("add_me works", { desc <- description$new("D2") with_mock( `desc:::check_for_package` = function(...) TRUE, `whoami::fullname` = function() "Bugs Bunny", `whoami::email_address` = function() "bugs.bunny@acme.com", desc$add_me(comment = "Yikes!") ) expect_identical( format(desc$get_authors()[5]), "Bugs Bunny [ctb] (Yikes!)" ) }) test_that("error if not Authors@R field", { desc <- description$new("D1") expect_error( desc$get_authors(), "No 'Authors@R' field" ) }) test_that("message if not author to delete does not exist", { desc <- description$new("D2") expect_message( desc$del_author(given = "Gábor"), "Could not find author to remove" ) }) test_that("get_author is OK", { D2 <- description$new("D2") expect_equal( D2$get_author(role = "cre"), person( given = "Hadley", family = "Wickham", email = "h.wickham@gmail.com", role = c("aut", "cre", "cph"), comment = NULL ) ) expect_equal( D2$get_author(role = "aut"), D2$get_authors()[1:3] ) D1 <- description$new("D1") expect_null(D1$get_author(role = "cre")) }) test_that("get_maintainer is OK, too", { D1 <- description$new("D1") expect_equal( D1$get_maintainer(), "G\u00e1bor Cs\u00e1rdi " ) D2 <- description$new("D2") expect_equal( D2$get_maintainer(), "Hadley Wickham " ) D1$del("Maintainer") expect_equal( D1$get_maintainer(), NA_character_ ) }) test_that("add_author if there is no Authors@R field", { D1 <- description$new("D1") D1$add_author("Gabor", "Csardi", "csardi.gabor@gmail.com", role = "ctb") expect_identical( format(D1$get_authors()[1]), "Gabor Csardi [ctb]" ) }) test_that("add myself if there is no Authors@R field", { D1 <- description$new("D1") with_mock( `desc:::check_for_package` = function(...) TRUE, `whoami::fullname` = function() "Bugs Bunny", `whoami::email_address` = function() "bugs.bunny@acme.com", D1$add_me(comment = "Yikes!") ) expect_identical( format(D1$get_authors()[1]), "Bugs Bunny [ctb] (Yikes!)" ) }) desc/tests/testthat/test-assertions.R0000644000176200001440000000030513160676472017476 0ustar liggesusers context("Assertions") test_that("is_existing_file", { miss <- basename(tempfile()) withr::with_dir( tempdir(), expect_error(desc::desc(miss), paste0(miss, ".*does not exist")) ) }) desc/tests/testthat/files/0000755000176200001440000000000013272146160015276 5ustar liggesusersdesc/tests/testthat/files/DESCRIPTION0000644000176200001440000000074713140567212017013 0ustar liggesusersPackage: desc Title: Manipulate DESCRIPTION Files Version: 1.0.0 Author: Gábor Csárdi Maintainer: Gábor Csárdi Description: Tools to read, write, create, and manipulate DESCRIPTION files. It is intented for packages that create or manipulate other packages. License: MIT + file LICENSE URL: https://github.com/r-pkgs/desc BugReports: https://github.com/r-pkgs/desc/issues Imports: R6 Suggests: testthat VignetteBuilder: knitr Encoding: UTF-8 desc/tests/testthat/test-queries.R0000644000176200001440000000550213272065331016753 0ustar liggesusers context("Queries") test_that("get works", { desc <- description$new("D1") expect_equal(desc$get("Package"), c(Package = "desc")) expect_equal(desc$get("Version"), c(Version = "1.0.0")) expect_equal(desc$get("Author"), c(Author = "G\u00e1bor Cs\u00e1rdi")) expect_equal(desc$get("Imports"), c(Imports = "\n R6")) }) test_that("get nothing", { desc <- description$new("D1") empty <- structure(character(), names = character()) expect_identical(desc$get(character()), empty) }) test_that("get_field works", { desc <- description$new("D1") expect_identical(desc$get_field("Package"), "desc") expect_identical(desc$get_field("Version"), "1.0.0") expect_identical(desc$get_field("Author"), "G\u00e1bor Cs\u00e1rdi") expect_identical(desc$get_field("Imports"), "R6") expect_identical(desc$get_field("Imports", trim_ws = FALSE), "\n R6") expect_error( desc$get_field("package"), "Field 'package' not found" ) }) test_that("get_or_fail works", { desc <- description$new("D1") expect_equal(desc$get_or_fail("Package"), c(Package = "desc")) expect_equal(desc$get_or_fail("Version"), c(Version = "1.0.0")) expect_equal(desc$get_or_fail("Author"), c(Author = "G\u00e1bor Cs\u00e1rdi")) expect_equal(desc$get_or_fail("Imports"), c(Imports = "\n R6")) expect_equal( desc$get_or_fail(c("Package", "Version")), c(Package = "desc", Version = "1.0.0") ) expect_error( desc$get_or_fail("package"), "Could not find DESCRIPTION field.*package" ) expect_error( desc$get_or_fail(c("Package", "versionx")), "Could not find DESCRIPTION field.*versionx" ) expect_error( desc$get_or_fail(c("Package", "versionx", "foobar")), "Could not find DESCRIPTION fields.*versionx.*foobar" ) }) test_that("set works", { desc <- description$new("D1") expect_equal(desc$get("Package"), c(Package = "desc")) desc$set(Package = "foobar") expect_equal(desc$get("Package"), c(Package = "foobar")) desc$set("Package", "foo") expect_equal(desc$get("Package"), c(Package = "foo")) desc$set(Version = "100.0", Author = "Bugs Bunny") expect_equal(desc$get("Version"), c(Version = "100.0")) expect_equal(desc$get("Author"), c(Author = "Bugs Bunny")) desc$set("Description", "Foo\n foobar\n foobar2.") expect_equal(desc$get("Description"), c(Description = "Foo\n foobar\n foobar2.")) }) test_that("get with non-exixting fields", { desc <- description$new("D1") expect_equal(desc$get("foobar"), c(foobar = NA_character_)) }) test_that("del works", { desc <- description$new("D1") desc$del("Package") expect_equal(desc$get("Package"), c(Package = NA_character_)) expect_false(is.na(desc$get("Title"))) }) test_that("set errors on invalid input", { desc <- description$new("D1") expect_error( desc$set("foobar"), "needs two unnamed args" ) }) desc/tests/testthat/test-remotes.R0000644000176200001440000000207713244347461016766 0ustar liggesusers context("REMOTE") test_that("get, set, etc. remotes", { desc <- description$new("D2") expect_identical( desc$get_remotes(), c("foo/digest", "svn::https://github.com/hadley/stringr", "local::/pkgs/testthat" ) ) desc$set_remotes(c("bar/knitr", "local::/pkgs/Rcpp")) expect_identical(desc$get_remotes(), c("bar/knitr", "local::/pkgs/Rcpp")) desc$add_remotes("github::brewer/brew") expect_identical( desc$get_remotes(), c("bar/knitr", "local::/pkgs/Rcpp", "github::brewer/brew") ) desc$del_remotes("^local::") expect_identical( desc$get_remotes(), c("bar/knitr", "github::brewer/brew") ) desc$clear_remotes() expect_identical(desc$get_remotes(), character()) desc$add_remotes("hadley/stringr") expect_identical(desc$get_remotes(), "hadley/stringr") desc$del_remotes("stringr") expect_identical(desc$get_remotes(), character()) expect_identical(desc$get("Remotes"), c(Remotes = NA_character_)) expect_warning( desc$set("Remotes", "my remote"), "must be a comma separated list of remotes" ) }) desc/tests/testthat/test-versions.R0000644000176200001440000000325513140567212017150 0ustar liggesusers context("Version") test_that("get_version", { desc <- description$new("D1") v <- desc$get_version() expect_true(inherits(v, "package_version")) expect_equal(as.character(v), "1.0.0") desc$del("Version") expect_error(desc$get_version()) }) test_that("set_version", { desc <- description$new("D1") desc$set_version("2.1.3")$set_version("2.1.4") expect_equal(desc$get_version(), package_version("2.1.4")) desc$set_version(package_version("1.9.10.100")) expect_equal(desc$get_version(), package_version("1.9.10.100")) expect_error(desc$set_version("1")) expect_error(desc$set_version("1.0.0-dev")) }) test_that("bump_version", { desc <- description$new("D1") cases <- list( c("1.2.3", "major", "2.0.0"), c("1.2.3", "minor", "1.3.0"), c("1.2.3", "patch", "1.2.4"), c("1.2.3", "dev", "1.2.3.9000"), c("1.5", "major", "2.0"), c("1.5", "minor", "1.6"), c("1.5", "patch", "1.5.1"), c("1.5", "dev", "1.5.0.9000"), c("1.2.3.9000", "major", "2.0.0"), c("1.2.3.9000", "minor", "1.3.0"), c("1.2.3.9000", "patch", "1.2.4"), c("1.2.3.9000", "dev", "1.2.3.9001"), list("1.2.3", 1, "2.0.0"), list("1.2.3", 2, "1.3.0"), list("1.2.3", 3, "1.2.4"), list("1.2.3", 4, "1.2.3.9000"), list("1.5", 1, "2.0"), list("1.5", 2, "1.6"), list("1.5", 3, "1.5.1"), list("1.5", 4, "1.5.0.9000"), list("1.2.3.9000", 1, "2.0.0"), list("1.2.3.9000", 2, "1.3.0"), list("1.2.3.9000", 3, "1.2.4"), list("1.2.3.9000", 4, "1.2.3.9001") ) for (c in cases) { expect_equal( desc$set_version(c[[1]])$bump_version(c[[2]])$get_version(), package_version(c[[3]]) ) } }) desc/tests/testthat/helper.R0000644000176200001440000000013113140567212015570 0ustar liggesusers temp_desc <- function(file = "D2") { tmp <- tempfile() file.copy(file, tmp) tmp } desc/tests/testthat/D40000644000176200001440000000064513160675307014401 0ustar liggesusersPackage: desc Title: Manipulate DESCRIPTION Files Version: 1.0.0 Author: Gábor Csárdi Maintainer: Gábor Csárdi Description: Tools to read, write, create, and manipulate DESCRIPTION files. It is intented for packages that create or manipulate other packages. License: MIT + file LICENSE Depends: Encoding: UTF-8 Built: R 3.4.1; x86_64-apple-darwin15.6.0; 2017-09-14 20:30:19 UTC; unix desc/tests/testthat/test-archives.R0000644000176200001440000000532213272145675017114 0ustar liggesusers context("Package archives") test_that("is_zip_file", { expect_true(is_zip_file(file.path("fixtures", "xxx.zip"))) expect_false(is_zip_file(file.path("fixtures", "xxx.gz"))) expect_false(is_zip_file(file.path("fixtures", "xxx.tar.gz"))) }) test_that("is_gz_file", { expect_false(is_gz_file(file.path("fixtures", "xxx.zip"))) expect_true(is_gz_file(file.path("fixtures", "xxx.gz"))) expect_true(is_gz_file(file.path("fixtures", "xxx.tar.gz"))) }) test_that("is_tar_gz_file", { expect_false(is_tar_gz_file(file.path("fixtures", "xxx.zip"))) expect_false(is_tar_gz_file(file.path("fixtures", "xxx.gz"))) expect_true(is_tar_gz_file(file.path("fixtures", "xxx.tar.gz"))) }) test_that("is_valid_package_file_name", { pos <- c( "foo_1.0.tar.gz", "a1_0.2.tar.gz", "A0_1.2-4.tar.gz", "foo_1.0.tgz", "a1_0.2.tgz", "A0_1.2-4.tgz", "foo_1.0.zip", "a1_0.2.zip", "A0_1.2-4.zip", "R6_2.2.0_R_x86_64-pc-linux-gnu.tar.gz" ) neg <- c( "1foo_1.0.tar.gz", # cannot start with number "x_1.5.tar.gz", # must be at least two characters "xx-1.5.tar.gz", # dash separator is invalid "foo_1.tar.gz", # version number must have 2 comps "foo_1.0.tar.gzx", # invalid file extension "foo_1.0.zipfile" # invalid file extension ) for (x in pos) expect_true(is_valid_package_file_name(x), info = x) for (x in neg) expect_false(is_valid_package_file_name(x), info = x) }) test_that("is_package_archive", { pos <- file.path("fixtures", c( "pkg_1.0.0.tar.gz", "pkg_1.0.0.tgz", "pkg_1.0.0_R_x86_64-pc-linux-gnu.tar.gz" )) neg <- file.path("fixtures", c("xxx.zip", "xxx.gz", "xxx.tar.gz")) for (x in pos) expect_true(is_package_archive(x), info = x) for (x in neg) expect_false(is_package_archive(x), info = x) }) test_that("get_description_from_package", { d1 <- description$new(file.path("fixtures", "pkg_1.0.0.tar.gz")) d2 <- description$new(file.path("fixtures", "pkg_1.0.0.tgz")) d3 <- description$new(file.path( "fixtures", "pkg_1.0.0_R_x86_64-pc-linux-gnu.tar.gz" )) d4 <- description$new(file.path("fixtures", "pkg_1.0.0.zip")) expect_equal(d1$get("Package"), c(Package = "pkg")) expect_equal(d2$get("Package"), c(Package = "pkg")) expect_equal(d3$get("Package"), c(Package = "pkg")) expect_equal(d4$get("Package"), c(Package = "pkg")) expect_error( d4 <- description$new(file.path("fixtures", "notpkg_1.0.tar.gz")), "Cannot extract DESCRIPTION" ) }) test_that("write errors if from archive", { d <- description$new(file.path("fixtures", "pkg_1.0.0.tar.gz")) expect_error(d$write(), "Cannot write back DESCRIPTION") }) desc/tests/testthat/D80000644000176200001440000000217313244347461014403 0ustar liggesusersPackage: hunspell Type: Package Title: High-Performance Stemmer, Tokenizer, and Spell Checker Version: 2.9 Depends: R (>= 3.0.2) Encoding: UTF-8 Authors@R: c( person("Jeroen", "Ooms", ,"jeroen@berkeley.edu", role = c("aut", "cre")), person("Authors of libhunspell", role = "cph", comment = "see AUTHORS file")) Description: Low level spell checker and morphological analyzer based on the famous 'hunspell' library . The package can analyze or check individual words as well as parse text, latex, html or xml documents. For a more user-friendly interface use the 'spelling' package which builds on this package to automate checking of files, documentation and vignettes in all common formats. License: GPL-2 | LGPL-2.1 | MPL-1.1 URL: https://github.com/ropensci/hunspell#readme (devel) https://hunspell.github.io (upstream) BugReports: https://github.com/ropensci/hunspell/issues Imports: Rcpp, digest LinkingTo: Rcpp (>= 0.12.12) Suggests: spelling, testthat, pdftools, janeaustenr, wordcloud2, knitr, rmarkdown VignetteBuilder: knitr RoxygenNote: 6.0.1.9000 desc/tests/testthat/test-read.R0000644000176200001440000000176713244477525016235 0ustar liggesusers context("DCF reader") test_that("DCF reader works", { desc <- description$new("D1") expect_equal(desc$get("Package"), c(Package = "desc")) expect_equal(desc$get("Version"), c(Version = "1.0.0")) expect_equal(desc$get("Author"), c(Author = "G\u00e1bor Cs\u00e1rdi")) expect_equal(desc$get("Imports"), c(Imports = "\n R6")) }) test_that("DCF reader keeps whitespace", { desc <- description$new("D1") expect_equal(desc$get("Suggests"), c(Suggests = "\n testthat")) expect_equal(desc$get("Description"), c( Description = paste0( "Tools to read, write, create, and manipulate DESCRIPTION\n", " files. It is intented for packages that create or manipulate other\n", " packages." ) )) }) test_that("duplicate fields, #43", { expect_error( description$new("D5"), "Duplicate DESCRIPTION fields.*Remotes" ) }) test_that("Empty DESCRIPTION", { expect_error(description$new(text = ""), NA) expect_error(description$new(text = character()), NA) }) desc/tests/testthat/test-str.R0000644000176200001440000000403213202454360016100 0ustar liggesusers context("Formatting") test_that("str orders fields", { desc <- description$new("!new") desc$del("Package") desc$set("Package", "foobar") expect_match(crayon::strip_style(desc$str()), "^Package:") }) test_that("str formats some fields specially", { desc <- description$new("!new") desc$set("Imports", "pkg1, pkg2, \n pkg3, pkg4") expect_match( crayon::strip_style(desc$str()), "Imports:\n pkg1,\n pkg2,\n pkg3,\n pkg4" ) desc$set("Collate", "file1.R 'file2.R' 'file with spaces.R' file4.R") expect_match( crayon::strip_style(desc$str()), "Collate:\n 'file1.R'\n 'file2.R'\n 'file with spaces.R'\n 'file4.R'" ) }) test_that("str formats authors properly", { desc <- description$new("D2") expect_equal( crayon::strip_style(desc$str(by_field = TRUE)[["Authors@R"]]), paste0( "Authors@R:\n ", "c(person(given = \"Hadley\",\n ", "family = \"Wickham\",\n ", "role = c(\"aut\", \"cre\", \"cph\"),\n ", "email = \"h.wickham@gmail.com\"),\n ", "person(given = \"Peter\",\n ", "family = \"Danenberg\",\n ", "role = c(\"aut\", \"cph\"),\n ", "email = \"pcd@roxygen.org\"),\n ", "person(given = \"Manuel\",\n ", "family = \"Eugster\",\n ", "role = c(\"aut\", \"cph\")),\n ", "person(given = \"RStudio\",\n ", "role = \"cph\"))" ) ) }) test_that("authors are printed to the screen properly", { desc <- description$new("D2") expect_output( print(desc), "(parsed): * Hadley Wickham [aut, cre, cph] * Peter Danenberg [aut, cph] * Manuel Eugster [aut, cph] * RStudio [cph]", fixed = TRUE ) }) test_that("continuation lines", { desc <- description$new("D7") t1 <- desc$str(normalize = TRUE) t2 <- desc$str(normalize = FALSE) expect_false(grepl("\n[ \t]*\n", t1)) expect_false(grepl("\n[ \t]*\n", t2)) }) desc/NAMESPACE0000644000176200001440000000637013260674766012436 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(check_field,DescriptionAddedByRCMD) S3method(check_field,DescriptionAuthorsAtR) S3method(check_field,DescriptionClassification) S3method(check_field,DescriptionCollate) S3method(check_field,DescriptionCompression) S3method(check_field,DescriptionDate) S3method(check_field,DescriptionDependencyList) S3method(check_field,DescriptionDescription) S3method(check_field,DescriptionEncoding) S3method(check_field,DescriptionField) S3method(check_field,DescriptionFreeForm) S3method(check_field,DescriptionLanguage) S3method(check_field,DescriptionLicense) S3method(check_field,DescriptionLogical) S3method(check_field,DescriptionMaintainer) S3method(check_field,DescriptionOSType) S3method(check_field,DescriptionPackage) S3method(check_field,DescriptionPackageList) S3method(check_field,DescriptionPriority) S3method(check_field,DescriptionRemotes) S3method(check_field,DescriptionRepoList) S3method(check_field,DescriptionRepository) S3method(check_field,DescriptionTitle) S3method(check_field,DescriptionType) S3method(check_field,DescriptionURL) S3method(check_field,DescriptionURLList) S3method(check_field,DescriptionVersion) S3method(format,DescriptionAuthorsAtR) S3method(format,DescriptionCollate) S3method(format,DescriptionDependencyList) S3method(format,DescriptionField) S3method(format,DescriptionPackageList) S3method(format,DescriptionRemotes) S3method(toLatex,DescriptionAuthorsAtR) S3method(toLatex,DescriptionCollate) S3method(toLatex,DescriptionField) S3method(toLatex,DescriptionURL) S3method(toLatex,DescriptionURLList) S3method(toLatex,character) S3method(toLatex,person) export(check_field) export(cran_ascii_fields) export(cran_valid_fields) export(dep_types) export(desc) export(desc_add_author) export(desc_add_me) export(desc_add_remotes) export(desc_add_role) export(desc_add_to_collate) export(desc_add_urls) export(desc_bump_version) export(desc_change_maintainer) export(desc_clear_remotes) export(desc_clear_urls) export(desc_del) export(desc_del_author) export(desc_del_collate) export(desc_del_dep) export(desc_del_deps) export(desc_del_from_collate) export(desc_del_remotes) export(desc_del_role) export(desc_del_urls) export(desc_fields) export(desc_get) export(desc_get_author) export(desc_get_authors) export(desc_get_built) export(desc_get_collate) export(desc_get_deps) export(desc_get_field) export(desc_get_maintainer) export(desc_get_or_fail) export(desc_get_remotes) export(desc_get_urls) export(desc_get_version) export(desc_has_dep) export(desc_has_fields) export(desc_normalize) export(desc_print) export(desc_reformat_fields) export(desc_reorder_fields) export(desc_set) export(desc_set_authors) export(desc_set_collate) export(desc_set_dep) export(desc_set_deps) export(desc_set_remotes) export(desc_set_urls) export(desc_set_version) export(desc_to_latex) export(desc_validate) export(description) importFrom(R6,R6Class) importFrom(assertthat,"on_failure<-") importFrom(assertthat,assert_that) importFrom(crayon,blue) importFrom(crayon,red) importFrom(crayon,strip_style) importFrom(rprojroot,find_root) importFrom(rprojroot,is_r_package) importFrom(utils,as.person) importFrom(utils,packageName) importFrom(utils,person) importFrom(utils,tail) importFrom(utils,toLatex) importFrom(utils,untar) importFrom(utils,unzip) desc/NEWS.md0000644000176200001440000000263213272041260012266 0ustar liggesusers # 1.2.0 * Add `get_field()` method, with easier to use failure and fallback semantics (#62) * Use the `Encoding` field to read and write DESCRIPTION with the corect encoding. UTF-8 is always used internall by desc. (#52, #53) * Add `get_built()` function to parse the Built field used in package binaries. (#48, @jimhester) * `get_deps()` (and `desc_get_deps()`) return a zero-row data frame instead of `NULL` for packages without any dependencies, for consistency. * Empty `DESCRIPTION` files are handled more gracefully, as are querying no fields with `desc_get()` * `Remotes`, `VignetteBuilder` and `RdMacros` fields are syntax checked. (#59, @krlmlr) * Account for non-URL content in the `URL` field (#57, @jennybc) * Allow for IETF region subtag in `Language` field (#55, @jeroen) * Fix continuation lines in output * `get_deps()` returns empty data frame if no dependencies, instead of `NULL` # 1.1.1 * Relax the R >= 3.2.0 dependency, R 3.1.0 is enough now. # 1.1.0 * Fix bug when adding authors and there is no `Authors@R` field * Get `DESCRIPTION` from package archives (#40) * Fix but in `del_dep()` and `has_dep()`, they only worked if the package was attached. # 1.0.1 * Fix formatting of `Collate` fields, they always start at a new line now. * Fix formatting of `Authors@R` fields, when changed. * Keep trailing space after the `:` character, see #14 # 1.0.0 First public release. desc/R/0000755000176200001440000000000013272145552011377 5ustar liggesusersdesc/R/classes.R0000644000176200001440000000405113244347461013161 0ustar liggesusers collate_fields <- c( main = "Collate", windows = "Collate.windows", unix = "Collate.unix" ) field_classes <- list( Package = "Package", Version = "Version", License = "License", Description = "Description", Title = "Title", Maintainer = "Maintainer", AuthorsAtR = "Authors@R", DependencyList = c("Imports", "Suggests", "Depends", "Enhances", "LinkingTo"), PackageList = c("VignetteBuilder", "RdMacros"), Remotes = "Remotes", RepoList = "Additional_repositories", URL = "BugReports", URLList = "URL", Priority = "Priority", Collate = unname(collate_fields), Logical = c("LazyData", "KeepSource", "ByteCompile", "ZipData", "Biarch", "BuildVignettes", "NeedsCompilation", "License_is_FOSS", "License_restricts_use", "BuildKeepEmpty", "BuildManual", "BuildResaveData", "LazyLoad"), Encoding = "Encoding", OSType = "OS_type", Type = "Type", Classification = c("Classification/ACM", "Classification/ACM-2012", "Classification/JEL", "Classification/MSC", "Classification/MSC-2010"), Language = "Language", Date = "Date", Compression = c("LazyDataCompression", "SysDataCompression"), Repository = "Repository", FreeForm = c("Author", "SystemRequirements", "Archs", "Contact", "Copyright", "MailingList", "Note", "Path", "LastChangedDate", "LastChangedRevision", "Revision", "RcmdrModels", "RcppModules", "Roxygen", "Acknowledgements", "Acknowledgments", "biocViews"), AddedByRCMD = c("Built", "Packaged", "MD5sum", "Date/Publication") ) field_classes$FreeForm <- c( field_classes$FreeForm, paste0(unlist(field_classes), "Note") ) create_fields <- function(keys, values) { mapply(keys, values, SIMPLIFY = FALSE, FUN = create_field) } create_field <- function(key, value) { f <- structure(list(key = key, value = value), class = "DescriptionField") if (key %in% unlist(field_classes)) { cl <- paste0("Description", find_field_class(key)) class(f) <- c(cl, class(f)) } f } find_field_class <- function(k) { names(which(vapply(field_classes, `%in%`, logical(1), x = k))) } desc/R/utils.R0000644000176200001440000000527713260674226012677 0ustar liggesusers `%||%` <- function(l, r) if (is.null(l)) r else l str_trim <- function(x) { sub("^\\s+", "", sub("\\s+$", "", x)) } is_ascii <- function(x) { vapply( as.character(x), function(txt) all(charToRaw(txt) <= as.raw(127)), TRUE, USE.NAMES = FALSE ) } ## This is from tools/R/QC.R ## We do not calculate code coverage for this, as ## it is run at install time ## ## nocov start RFC_2822_email_regexp <- (function() { ## Local part consists of ASCII letters and digits, the characters ## ! # $ % * / ? | ^ { } ` ~ & ' + = _ - ## and . provided it is not leading or trailing or repeated, or must ## be a quoted string. ## Domain part consists of dot-separated elements consisting of ## ASCII letters, digits and hyphen. ## We could also check that the local and domain parts are no longer ## than 64 and 255 characters, respectively. ## See http://en.wikipedia.org/wiki/Email_address. ASCII_letters_and_digits <- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" l <- sprintf("[%s%s]", ASCII_letters_and_digits, "!#$%*/?|^{}`~&'+=_-") d <- sprintf("[%s%s]", ASCII_letters_and_digits, "-") ## Be careful to arrange the hyphens to come last in the range spec. sprintf("(\\\".+\\\"|(%s+\\.)*%s+)@(%s+\\.)*%s+", l, l, d, d) })() ## nocov end is_url <- function(x) { grepl("^(https?|ftp)://\\S+$", str_trim(x)) } is_url_list <- function(x) { xx <- parse_url_list(x) all(vapply(xx, is_url, TRUE)) } parse_url_list <- function(x) { xx <- strsplit(x, ",", fixed = TRUE)[[1]] str_trim(xx) } all_true <- function(x) { all(vapply(x, identical, TRUE, TRUE)) } flatten <- function(x) { if (is.list(x)) { x <- lapply( x, function(e) if (is.null(e)) "" else paste(e, collapse = ",") ) x <- unlist(x) } x } ngrepl <- function(pattern, x, ...) { if (is.null(pattern)) pattern <- "" x <- flatten(x) grepl(pattern, x, ...) } check_for_package <- function(pkg, msg = paste0("Package '", pkg, "' is needed.")) { has <- requireNamespace(pkg, quietly = TRUE) if (!has) stop(msg, call. = FALSE) has } is_dir <- function(path) { file.info(path)$isdir } postprocess_trailing_ws <- function(file, notws) { lines <- readLines(file) for (n in notws) { lines <- sub(paste0("^", n, ": "), paste0(n, ":"), lines) } writeLines(lines, file) } #' @importFrom rprojroot find_root is_r_package find_description <- function(dir) { pkg_root <- find_root(is_r_package, dir) file.path(pkg_root, "DESCRIPTION") } mark_continuation_lines <- function(x) { x <- gsub("\n[ \t]*\n", "\n .\n ", x, perl = TRUE, useBytes = TRUE) gsub("\n \\.([^\n])", "\n .\\1", x, perl = TRUE, useBytes = TRUE) } desc/R/version.R0000644000176200001440000000266013140567212013206 0ustar liggesusers idesc_get_version <- function(self, private) { ver <- unname(self$get("Version")) if (is.na(ver)) stop("No ", sQuote('Version'), " field found") package_version(ver) } idesc_set_version <- function(self, private, version) { assert_that(is_package_version(version)) self$set(Version = as.character(version)) } idesc_bump_version <- function(self, private, which) { assert_that(is_version_component(which)) if (is.character(which)) { which <- match(which, c("major", "minor", "patch", "dev")) } ver_str <- self$get_version() ver <- get_version_components(ver_str) ## Special dev version inc <- if (which == 4 && length(ver) < 4) 9000 else 1 ## Missing components are equivalent to zero if (which > length(ver)) ver <- c(ver, rep(0, which - length(ver))) ## Bump selected component ver[which] <- ver[which] + inc ## Zero out everything after if (which < length(ver)) ver[(which+1):length(ver)] <- 0 ## Keep at most three components if they are zero if (length(ver) > 3 && all(ver[4:length(ver)] == 0)) { ver <- ver[1:3] } ## Set the new version new_ver <- package_version(paste(ver, collapse = ".")) self$set_version(new_ver) ## Give a message message( "Package version bumped from ", sQuote(ver_str), " to ", sQuote(new_ver) ) invisible(self) } ## Note that this is not vectorized get_version_components <- function(x) { as.numeric(strsplit(format(x), "[-\\.]")[[1]]) } desc/R/remotes.R0000644000176200001440000000231013244347461013176 0ustar liggesusers parse_remotes <- function(remotes) { str_trim(strsplit(remotes, "\\s*,\\s*", perl = TRUE)[[1]]) } deparse_remotes <- function(remotes) { paste0(" \n ", paste(str_trim(remotes), collapse = ",\n ")) } idesc_get_remotes <- function(self, private) { remotes <- self$get("Remotes") if (is.na(remotes)) { character() } else { parse_remotes(remotes) } } idesc_set_remotes <- function(self, private, remotes) { assert_that(is.character(remotes)) self$set(Remotes = deparse_remotes(remotes)) invisible(self) } idesc_add_remotes <- function(self, private, remotes) { assert_that(is.character(remotes)) remotes <- unique(c(self$get_remotes(), remotes)) self$set(Remotes = deparse_remotes(remotes)) invisible(self) } idesc_del_remotes <- function(self, private, pattern) { assert_that(is_string(pattern)) remotes <- self$get_remotes() if (length(remotes) == 0) return(invisible(self)) filt <- grep(pattern, remotes, invert = TRUE, value = TRUE, perl = TRUE) if (length(filt) > 0) { self$set(Remotes = deparse_remotes(filt)) } else { self$del("Remotes") } invisible(self) } idesc_clear_remotes <- function(self, private) { self$del("Remotes") invisible(self) } desc/R/deps.R0000644000176200001440000000656513174051670012467 0ustar liggesusers idesc_set_dep <- function(self, private, package, type, version) { assert_that(is_string(package), is_string(version)) deps <- self$get_deps() has <- which(deps$package == package & deps$type == type) if (length(has)) { deps[ has, "version" ] <- version } else { deps <- rbind( deps, data.frame( stringsAsFactors = FALSE, type = type, package = package, version = version ) ) } idesc_set_deps(self, private, deps) } idesc_set_deps <- function(self, private, deps) { assert_that(is_deps_df(deps)) depdeps <- deparse_deps(deps) for (d in names(depdeps)) { if (! same_deps(depdeps[[d]], private$data[[d]]$value)) { self$set(d, depdeps[[d]]) } } deldeps <- setdiff(dep_types, names(depdeps)) self$del(deldeps) invisible(self) } same_deps <- function(d1, d2) { if (is.null(d1) + is.null(d2) == 1) return(FALSE) d1 <- parse_deps("foo", d1) d2 <- parse_deps("foo", d2) d1 <- d1[ order(d1$type, d1$package, d1$version), ] d2 <- d2[ order(d2$type, d2$package, d2$version), ] nrow(d1) == nrow(d2) && all(d1$type == d2$type) && all(d1$package == d2$package) && all(d1$version == d2$version) } #' Get dependencies #' #' In case the package has no dependencies at all, we `rbind` the #' list of data frames with the various dependency types, with an #' empty data frame. This ensures that we don't get `NULL` for the edge #' case, but a nice data frame with zero rows. #' #' @param self self #' @param private private self #' @return data frame of dependencies #' #' @keywords internal #' @noRd idesc_get_deps <- function(self, private) { types <- intersect(names(private$data), dep_types) res <- lapply(types, function(type) parse_deps(type, private$data[[type]]$value)) empty <- data.frame( stringsAsFactors = FALSE, type = character(), package = character(), version = character() ) do.call(rbind, c(list(empty), res)) } parse_deps <- function(type, deps) { deps <- str_trim(strsplit(deps, ",")[[1]]) deps <- lapply(strsplit(deps, "\\("), str_trim) deps <- lapply(deps, sub, pattern = "\\)$", replacement = "") res <- data.frame( stringsAsFactors = FALSE, type = if (length(deps)) type else character(), package = vapply(deps, "[", "", 1), version = vapply(deps, "[", "", 2) ) res [ is.na(res) ] <- "*" res } deparse_deps <- function(deps) { tapply(seq_len(nrow(deps)), deps$type, function(x) { pkgs <- paste0( " ", deps$package[x], ifelse( deps$version[x] == "*", "", paste0(" (", deps$version[x], ")") ), collapse = ",\n" ) paste0("\n", pkgs) }) } idesc_del_dep <- function(self, private, package, type) { assert_that(is_string(package)) deps <- self$get_deps() if (type == "all") { has <- which(deps$package == package) } else { has <- which(deps$package == package & deps$type == type) } if (length(has)) { deps <- deps[-has, ] idesc_set_deps(self, private, deps) } else { invisible(self) } } idesc_del_deps <- function(self, private) { self$del(dep_types) } idesc_has_dep <- function(self, private, package, type) { assert_that(is_string(package)) deps <- self$get_deps() if (type == "any") { package %in% deps$package } else { package %in% deps$package && type %in% deps[match(package, deps$package), "type"] } } desc/R/collate.R0000644000176200001440000000530513140567212013143 0ustar liggesusers which_collate <- function(x) { collate_fields[x] } idesc_set_collate <- function(self, private, files, which) { assert_that(is.character(files), is_collate_field(which)) if (length(files) == 0) warning("No files in 'Collate' field") idesc_really_set_collate(self, private, files, which_collate(which)) } idesc_really_set_collate <- function(self, private, files, field) { if (!identical(self$get_collate(), files)) { self$set(field, deparse_collate(files)) } } idesc_get_collate <- function(self, private, which) { assert_that(is_collate_field(which)) coll <- unname(self$get(which_collate(which))) if (identical(coll, NA_character_)) character() else parse_collate(coll) } idesc_del_collate <- function(self, private, which) { assert_that(is_collate_field_or_all(which)) if (which == "all") { self$del(collate_fields) } else { self$del(collate_fields[which]) } invisible(self) } idesc_add_to_collate <- function(self, private, files, which) { assert_that(is.character(files), is_collate_field_or_all_or_default(which)) if (which == "default") { ex_coll <- intersect(collate_fields, self$fields()) if (length(ex_coll) == 0) { real_add_to_collate(self, private, which_collate("main"), files) } else { for (ex in ex_coll) real_add_to_collate(self, private, ex, files) } } else if (which == "all") { for (coll in collate_fields) { real_add_to_collate(self, private, coll, files) } } else { real_add_to_collate(self, private, which_collate(which), files) } } ## TODO: better order, and support dependencies real_add_to_collate <- function(self, private, field, files) { ex <- if (!self$has_fields(field)) { character() } else { parse_collate(self$get(field)) } files <- unique(c(ex, files)) idesc_really_set_collate(self, private, files, field) } idesc_del_from_collate <- function(self, private, files, which) { assert_that(is.character(files), is_collate_field_or_all(which)) if (which == "all") { for (coll in collate_fields) { real_del_from_collate(self, private, coll, files) } } else { real_del_from_collate(self, private, which_collate(which), files) } } real_del_from_collate <- function(self, private, field, files) { if (self$has_fields(field)) { coll <- setdiff(parse_collate(self$get(field)), files) idesc_really_set_collate(self, private, coll, field) } else { invisible(self) } } parse_collate <- function(str) { scan( text = gsub("\n", " ", str), what = "", strip.white = TRUE, quiet = TRUE ) } deparse_collate <- function(list) { paste0( "\n", paste0( " '", list, "'", collapse = "\n" ) ) } desc/R/encoding.R0000644000176200001440000000165113272047150013306 0ustar liggesusers #' Check encoding of new or existing fields #' #' If \code{new_fields} is \code{NULL}, then the existing #' fields are checked. Otherwise \code{new_fields} are checked. #' #' Warnings are given for non-ascii fields, if the \code{Encoding} #' field is not set. #' #' @param self Object. #' @param private Private env. #' @param new_fields New fields, or \code{NULL} to check existing fields. #' @return Object, invisibly. #' #' @keywords internal check_encoding <- function(self, private, new_fields) { if (!is.na(self$get('Encoding'))) return(invisible(self)) fields <- if (is.null(new_fields)) { as.list(self$get(self$fields())) } else { new_fields } nonascii <- !vapply(fields, is_ascii, TRUE) if (any(nonascii)) { warning( "Consider adding an Encoding field to DESCRIPTION,\n", "Non-ASCII character(s) in ", paste(names(fields)[nonascii], collapse = ", ") ) } invisible(self) } desc/R/assertions.R0000644000176200001440000000677513160676023013731 0ustar liggesusers as_string <- function(x) { x <- as.character(x) if (length(x) != 1) stop("Value must be a scalar") x } #' @importFrom assertthat assert_that on_failure<- is_string <- function(x) { is.character(x) && length(x) == 1 && ! is.na(x) } on_failure(is_string) <- function(call, env) { paste0(deparse(call$x), " is not a string") } is_constructor_cmd <- function(x) { is_string(x) && substring(x, 1, 1) == "!" } on_failure(is_constructor_cmd) <- function(call, env) { paste0(deparse(call$x), " is not a string that starts with '!'") } is_path <- function(x) { is_string(x) } on_failure(is_path) <- function(call, env) { paste0(eval(call$x, env), " is not a path") } is_existing_file <- function(x) { is_path(x) && file.exists(x) } on_failure(is_existing_file) <- function(call, env) { paste0("File `", eval(call$x, env), "' does not exist") } has_no_na <- function(x) { !any(is.na(x)) } on_failure(has_no_na) <- function(call, env) { paste0(deparse(call$x), " must not contain NAs") } is_flag <- function(x) { is.logical(x) && length(x) == 1 && !is.na(x) } on_failure(is_flag) <- function(call, env) { paste0(deparse(call$x), " is not a flag (length 1 logical)") } is_authors <- function(x) { inherits(x, "person") } on_failure(is_authors) <- function(call, env) { paste0(deparse(call$x), " must be a person object") } is_string_or_null <- function(x) { is_string(x) || is.null(x) } on_failure(is_string_or_null) <- function(call, env) { paste0(deparse(call$x), " must be a string or NULL") } is_collate_field <- function(x) { is_string(x) && x %in% names(collate_fields) } on_failure(is_collate_field) <- function(call, env) { fields <- paste(sQuote(names(collate_fields)), collapse = ", ") paste0(deparse(call$x), " must be one of ", fields) } is_collate_field_or_all <- function(x) { is_string(x) && (x %in% names(collate_fields) || x == "all") } on_failure(is_collate_field) <- function(call, env) { fields <- paste(sQuote(c(names(collate_fields), "all")), collapse = ", ") paste0(deparse(call$x), " must be one of ", fields) } is_collate_field_or_all_or_default <- function(x) { is_string(x) && (x %in% names(collate_fields) || x == "all" || x == "default") } on_failure(is_collate_field) <- function(call, env) { fields <- paste( sQuote(c(names(collate_fields), "all", "default")), collapse = ", " ) paste0(deparse(call$x), " must be one of ", fields) } is_deps_df <- function(x) { is.data.frame(x) && identical(sort(names(x)), sort(c("type", "package", "version"))) && all(sapply(x, is.character) | sapply(x, is.factor)) } on_failure(is_deps_df) <- function(call, env) { cols <- paste(sQuote(c("type", "package", "version")), collapse = ", ") paste0( deparse(call$x), " must be a data frame with character columns ", cols ) } is_package_version <- function(x) { tryCatch( { length(package_version(x)) == 1 }, error = function(e) FALSE ) } on_failure(is_package_version) <- function(call, env) { paste0(deparse(call$x), " is an invalid version number") } is_version_component <- function(x) { (is_string(x) && x %in% c("major", "minor", "patch", "dev")) || (is_count(x) && x <= 5) } on_failure(is_version_component) <- function(call, env) { paste0(deparse(call$x), " is not a version number component (see docs)") } is_count <- function(x) { is.numeric(x) && length(x) == 1 && !is.na(x) && as.integer(x) == x } on_failure(is_count) <- function(call, env) { paste0(deparse(call$x), " is not a count (length 1 integer)") } desc/R/authors-at-r.R0000644000176200001440000001432413140567212014047 0ustar liggesusers #' @importFrom utils as.person parse_authors_at_r <- function(x) { if (is.null(x) || is.na(x)) return(NULL) out <- tryCatch( eval(parse(text = x)), error = identity ) if (inherits(out, "error")) NULL else out } deparse_authors_at_r <- function(x) { fmt <- lapply(unclass(x), deparse_author_at_r) if (length(fmt) == 1) { paste0("\n", paste0(" ", fmt[[1]], collapse = "\n")) } else { for (i in seq_along(fmt)) { fmt[[i]] <- paste0(" ", fmt[[i]]) fmt[[i]][[length(fmt[[i]])]] <- paste0(fmt[[i]][[length(fmt[[i]])]], ",") } fmt[[1]][[1]] <- sub("^ ", "c(", fmt[[1]][[1]]) n <- length(fmt) fmt[[n]][[length(fmt[[n]])]] <- sub(",$", ")", fmt[[n]][[length(fmt[[n]])]]) paste0("\n", paste0(" ", unlist(fmt), collapse = "\n")) } } deparse_author_at_r <- function(x1) { x1 <- x1[! vapply(x1, is.null, TRUE)] paste0( c("person(", rep(" ", length(x1) - 1)), names(x1), " = ", vapply(x1, deparse, ""), c(rep(",", length(x1) - 1), ")") ) } set_author_field <- function(authors, which, field, value) { rval <- unclass(authors) for (w in which) rval[[w]][[field]] <- value class(rval) <- class(authors) rval } ensure_authors_at_r <- function(obj) { if (! obj$has_fields("Authors@R")) { stop("No 'Authors@R' field!\n", "You can create one with $add_author") } } ## Find an author in the Authors@R field, based on a partical ## specification. E.g. it is enough to give the first name. search_for_author <- function(authors, given = NULL, family = NULL, email = NULL, role = NULL, comment = NULL) { matching <- ngrepl(given, authors$given) & ngrepl(family, authors$family) & ngrepl(email, authors$email) & ngrepl(role, authors$role) & ngrepl(comment, authors$comment) list(index = which(matching), authors = authors[matching]) } idesc_get_authors <- function(self, private, ensure = TRUE) { assert_that(is_flag(ensure)) if (ensure) ensure_authors_at_r(self) parse_authors_at_r(self$get("Authors@R")) } idesc_get_author <- function(self, private, role) { assert_that(is_string(role)) if (self$has_fields("Authors@R")) { aut <- self$get_authors() roles <- aut$role ## Broken person() API, vector for 1 author, list otherwise... if (!is.list(roles)) roles <- list(roles) selected <- vapply(roles, function(r) all(role %in% r), TRUE) aut[selected] } else { NULL } } idesc_set_authors <- function(self, private, authors) { assert_that(is_authors(authors)) self$set("Authors@R", deparse_authors_at_r(authors)) } check_author_args <- function(given = NULL, family = NULL, email = NULL, role = NULL, comment = NULL) { assert_that( is_string_or_null(given), is_string_or_null(family), is_string_or_null(email), is_string_or_null(role), is_string_or_null(comment) ) } #' @importFrom utils person idesc_add_author <- function(self, private, given, family, email, role, comment) { check_author_args(given, family, email, role, comment) orig <- idesc_get_authors(self, private, ensure = FALSE) newp <- person(given = given, family = family, email = email, role = role, comment = comment) new_authors <- if (is.null(orig)) newp else c(orig, newp) self$set_authors(new_authors) } idesc_add_role <- function(self, private, role, given, family, email, comment) { assert_that(is.character(role)) check_author_args(given, family, email, comment = comment) orig <- idesc_get_authors(self, private, ensure = FALSE) wh <- search_for_author( orig, given = given, family = family, email = email, comment = comment, role = NULL ) for (w in wh$index) { orig <- set_author_field( orig, w, "role", unique(c(orig[[w]]$role, role)) ) } self$set_authors(orig) } idesc_del_author <- function(self, private, given, family, email, role, comment) { check_author_args(given, family, email, role, comment) orig <- idesc_get_authors(self, private, ensure = FALSE) wh <- search_for_author( orig, given = given, family = family, email = email, comment = comment ) if (length(wh$index) == 0) { message("Could not find author to remove.") } else { au <- if (length(wh$index) == 1) "Author" else "Authors" message( au, "removed: ", paste(wh$authors$given, wh$authors$family, collapse = ", "), "." ) self$set_authors(orig[-wh$index]) } invisible(self) } idesc_del_role <- function(self, private, role, given, family, email, comment) { assert_that(is.character(role)) check_author_args(given, family, email, role = NULL, comment) orig <- idesc_get_authors(self, private, ensure = FALSE) wh <- search_for_author( orig, given = given, family = family, email = email, comment = comment, role = NULL ) for (w in wh$index) { orig <- set_author_field( orig, w, "role", setdiff(orig[[w]]$role, role) ) } self$set_authors(orig) } idesc_change_maintainer <- function(self, private, given, family, email, comment) { check_author_args(given, family, email, role = NULL, comment) ensure_authors_at_r(self) self$del_role(role = "cre") self$add_role(role = "cre", given = given, family = family, email = email, comment = comment) } #' @importFrom utils tail idesc_add_me <- function(self, private, role, comment) { assert_that(is_string_or_null(role)) assert_that(is_string_or_null(comment)) check_for_package("whoami", "$add_me needs the 'whoami' package") fn <- strsplit(whoami::fullname(), "[ ]+")[[1]] family <- tail(fn, 1) given <- paste(fn[-length(fn)], collapse = " ") email <- whoami::email_address() self$add_author(given = given, family = family, email = email, comment = comment, role = role) } idesc_get_maintainer <- function(self, private) { if (self$has_fields("Maintainer")) { unname(self$get("Maintainer")) } else if (self$has_fields("Authors@R")) { format( self$get_author(role = "cre"), include = c("given", "family", "email") ) } else { NA_character_ } } desc/R/built.R0000644000176200001440000000064413160675307012647 0ustar liggesusers idesc_get_built <- function(self, private) { built <- unname(self$get("Built")) if (is.na(built)) stop("No ", sQuote('Built'), " field found") built <- as.list(strsplit(built, "; ")[[1L]]) if (length(built) != 4L) { stop(sQuote('Built'), " field is corrupted") } names(built) <- c("R", "Platform", "Date", "OStype") built[["R"]] <- R_system_version(sub("^R ([0-9.]+)", "\\1", built[["R"]])) built } desc/R/description.R0000644000176200001440000007370313272145403014052 0ustar liggesusers #' Read a DESCRIPTION file #' #' This is a convenience wrapper for \code{description$new()}. #' Very often you want to read an existing \code{DESCRIPTION} #' file, and to do this you can just supply the path to the file or its #' directory to \code{desc()}. #' #' @param cmd A command to create a description from scratch. #' Currently only \code{"!new"} is implemented. If it does not start #' with an exclamation mark, it will be interpreted as the \sQuote{file} #' argument. #' @param file Name of the \code{DESCRIPTION} file to load. If all of #' \sQuote{cmd}, \sQuote{file} and \sQuote{text} are \code{NULL} (the #' default), then the \code{DESCRIPTION} file in the current working #' directory is used. The file can also be an R package (source, or #' binary), in which case the DESCRIPTION file is extracted from it, but #' note that in this case \code{$write()} cannot write the file back in #' the package archive. #' @param text A character scalar containing the full DESCRIPTION. #' Character vectors are collapsed into a character scalar, with #' newline as the separator. #' @param package If not NULL, then the name of an installed package #' and the DESCRIPTION file of this package will be loaded. #' #' @export #' @examples #' desc(package = "desc") #' DESCRIPTION <- system.file("DESCRIPTION", package = "desc") #' desc(DESCRIPTION) desc <- function(cmd = NULL, file = NULL, text = NULL, package = NULL) { description$new(cmd, file, text, package) } #' Read, write, update, validate DESCRIPTION files #' #' @section Constructors: #' #' There are two ways of creating a description object. The first #' is reading an already existing \code{DESCRIPTION} file; simply give #' the name of the file as an argument. The default is #' \code{DESCRIPTION}: \preformatted{ x <- description$new() #' x2 <- description$new("path/to/DESCRIPTION")} #' #' The second way is creating a description object from scratch, #' supply \code{"!new"} as an argument to do this. #' \preformatted{ x3 <- description$new("!new")} #' #' The complete API reference: #' \preformatted{description$new(cmd = NULL, file = NULL, text = NULL, #' package = NULL)} #' \describe{ #' \item{cmd:}{A command to create a description from scratch. #' Currently only \code{"!new"} is implemented. If it does not start #' with an exclamation mark, it will be interpreted as a \sQuote{file} #' argument.} #' \item{file:}{Name of the \code{DESCRIPTION} file to load. If it is #' a directory, then we assume that it is inside an R package and #' conduct a search for the package root directory, i.e. the first #' directory up the tree that contains a \code{DESCRIPTION} file. #' If \sQuote{cmd}, \sQuote{file}, \sQuote{text} and \sQuote{package} #' are all \code{NULL} (the default), then the search is started from #' the working directory. The file can also be an R package (source, or #' binary), in which case the DESCRIPTION file is extracted from it, #' but note that in this case \code{$write()} cannot write the file #' back in the package archive.} #' \item{text:}{A character scalar containing the full DESCRIPTION. #' Character vectors are collapsed into a character scalar, with #' newline as the separator.} #' \item{package}{If not NULL, then the name of an installed package #' and the DESCRIPTION file of this package will be loaded.} #' } #' #' @section Setting and Querying fields: #' Set a field with \code{$set} and query it with \code{$get}: #' \preformatted{ x <- description$new("!new") #' x$get("Package) #' x$set("Package", "foobar") #' x$set(Title = "Example Package for 'description'") #' x$get("Package")} #' Note that \code{$set} has two forms. You can either give the field name #' and new value as two arguments; or you can use a single named argument, #' the argument name is the field name, the argument value is the field #' value. #' #' The \code{$fields} method simply lists the fields in the object: #' \preformatted{ x$fields()} #' #' The \code{$has_fields} method checks if one or multiple fields are #' present in a description object: \preformatted{ x$has_fields("Package") #' x$has_fields(c("Title", "foobar"))} #' #' The \code{$del} method removes the specified fields: #' \preformatted{ x$set(foo = "bar") #' x$del("foo")} #' #' \code{$get_field} is similar to \code{$get}, but it queries a single #' field, it returns an unnamed vector if found, and returns the #' specified \code{default} value if not. By default it throws an error #' if the field is not found. #' #' The complete API reference: #' \preformatted{ description$get(keys) #' description$get_field(key, default, trim_ws = TRUE) #' description$set(...) #' description$fields() #' description$has_fields(keys) #' description$del(keys)} #' \describe{ #' \item{key:}{A character string (length one), the key to query.} #' \item{default:}{If specified and \code{key} is missing, this value #' is returned. If not specified, an error is thrown.} #' \item{trim_ws:}{Whether to trim leading and trailing whitespace #' from the returned value.} #' \item{keys:}{A character vector of keys to query, check or delete.} #' \item{...:}{This must be either two unnamed arguments, the key and #' and the value to set; or an arbitrary number of named arguments, #' names are used as keys, values as values to set.} #' } #' #' @section Normalizing: #' Format DESCRIPTION in a standard way. \code{$str} formats each #' field in a standard way and returns them (it does not change the #' object itself), \code{$print} is used to print it to the #' screen. The \code{$normalize} function normalizes each field (i.e. #' it changes the object). Normalization means reformatting the fields, #' via \code{$reformat_fields()} and also reordering them via #' \code{$reorder_fields()}. The format of the various fields is #' opinionated and you might like it or not. Note that \code{desc} only #' re-formats fields that it updates, and only on demand, so if your #' formatting preferences differ, you can still manually edit #' \code{DESCRIPTION} and \code{desc} will respect your edits. #' #' \preformatted{ description$str(by_field = FALSE, normalize = TRUE, #' mode = c("file", "screen")) #' description$normalize() #' description$reformat_fields() #' description$reorder_fields() #' description$print() #' } #' \describe{ #' \item{by_field:}{Whether to return the normalized format #' by field, or collapsed into a character scalar.} #' \item{normalize:}{Whether to reorder and reformat the fields.} #' \item{mode:}{\sQuote{file} mode formats the fields as they are #' written to a file with the \code{write} method. \sQuote{screen} #' mode adds extra markup to some fields, e.g. formats the #' \code{Authors@R} field in a readable way.} #' } #' #' @section Writing it to file: #' The \code{$write} method writes the description to a file. #' By default it writes it to the file it was created from, if it was #' created from a file. Otherwise giving a file name is compulsory: #' \preformatted{ x$write(file = "DESCRIPTION")} #' #' The \code{normalize} argument controls whether the fields are #' reformatted according to a standard style. By default they are not. #' #' The API: #' \preformatted{ description$write(file = NULL, normalize = NULL)} #' \describe{ #' \item{file:}{Path to write the description to. If it was created #' from a file in the first place, then it is written to the same #' file. Otherwise this argument must be specified.} #' \item{normalize:}{Whether to reformat the fields in a standard way.} #' } #' #' @section Version numbers: #' #' \preformatted{ description$get_version() #' description$set_version(version) #' description$bump_version(which = c("patch", "minor", "major", "dev")) #' } #' #' \describe{ #' \item{version:}{A string or a \code{\link[base]{package_version}} #' object.} #' \item{which:}{Which component of the version number to increase. #' See details just below.} #' } #' #' These functions are simple helpers to make it easier to query, set and #' increase the version number of a package. #' #' \code{$get_version()} returns the version number as a #' \code{\link[base]{package_version}} object. It throws an error if the #' package does not have a \sQuote{Version} field. #' #' \code{$set_version()} takes a string or a #' \code{\link[base]{package_version}} object and sets the \sQuote{Version} #' field to it. #' #' \code{$bump_version()} increases the version number. The \code{which} #' parameter specifies which component to increase. #' It can be a string referring to a component: \sQuote{major}, #' \sQuote{minor}, \sQuote{patch} or \sQuote{dev}, or an integer #' scalar, for the latter components are counted from one, and the #' beginning. I.e. component one is equivalent to \sQuote{major}. #' #' If a component is bumped, then the ones after it are zeroed out. #' Trailing zero components are omitted from the new version number, #' but if the old version number had at least two or three components, then #' the one will also have two or three. #' #' The bumping of the \sQuote{dev} version (the fourth component) is #' special: if the original version number had less than four components, #' and the \sQuote{dev} version is bumped, then it is set to \code{9000} #' instead of \code{1}. This is a convention often used by R developers, #' it was originally invented by Winston Chang. #' #' Both \code{$set_version()} and \code{$bump_version()} use dots to #' separate the version number components. #' #' @section Dependencies: #' These functions handle the fields that define how the R package #' uses another R packages. See \code{\link{dep_types}} for the #' list of fields in this group. #' #' The \code{$get_deps} method returns all declared dependencies, in a #' data frame with columns: \code{type}, \code{package} and \code{version}. #' \code{type} is the name of the dependency field, \code{package} is the #' name of the R package, and \code{version} is the required version. If #' no specific versions are required, then this is a \code{"\*"}. #' #' The \code{$set_deps} method is the opposite of \code{$get_deps} and #' it sets all dependencies. The input is a data frame, with the same #' structure as the return value of \code{$get_deps}. #' #' The \code{$has_dep} method checks if a package is included in the #' dependencies. It returns a logical scalar. If \code{type} is not #' \sQuote{any}, then it has to match as well. #' #' The \code{$del_deps} method removes all declared dependencies. #' #' The \code{$set_dep} method adds or updates a single dependency. By #' default it adds the package to the \code{Imports} field. #' #' The API: #' \preformatted{ description$set_dep(package, type = dep_types, version = "\*") #' description$set_deps(deps) #' description$get_deps() #' description$has_dep(package, type = c("any", dep_types)) #' description$del_dep(package, type = c("all", dep_types)) #' description$del_deps() #' } #' \describe{ #' \item{package:}{Name of the package to add to or remove from the #' dependencies.} #' \item{type:}{Dependency type, see \code{\link{dep_types}}. For #' \code{$del_dep} it may also be \code{"all"}, and then the package #' will be deleted from all dependency types.} #' \item{version:}{Required version. Defaults to \code{"\*"}, which means #' no explicit version requirements.} #' \item{deps:}{A data frame with columns \code{type}, \code{package} and #' \code{version}. \code{$get_deps} returns the same format.} #' } #' #' @section Collate fields: #' Collate fields contain lists of file names with R source code, #' and the package has a separate API for them. In brief, you can #' use \code{$add_to_collate} to add one or more files to the main or #' other collate field. You can use \code{$del_from_collate} to remove #' it from there. #' #' The API: #' \preformatted{ description$set_collate(files, which = c("main", "windows", "unix")) #' description$get_collate(which = c("main", "windows", "unix")) #' description$del_collate(which = c("all", "main", "windows", "unix")) #' description$add_to_collate(files, which = c("default", "all", "main", #' "windows", "unix")) #' description$del_from_collate(files, which = c("all", "main", #' "windows", "unix")) #' } #' \describe{ #' \item{files:}{The files to add or remove, in a character vector.} #' \item{which:}{Which collate field to manipulate. \code{"default"} for #' \code{$add_to_collate} means all existing collate fields, or the #' main one if none exist.} #' } #' #' @section Authors: #' There is a specialized API for the \code{Authors@R} field, #' to add and remove authors, update their roles, change the maintainer, #' etc. #' #' The API: #' \preformatted{ description$get_authors() #' description$set_authors(authors) #' description$get_author(role) #' description$get_maintainer() #' } #' \describe{ #' \item{authors:}{A \code{person} object, a list of authors.} #' \item{role:}{The role to query. See \code{person} for details.} #' } #' \code{$get_authors} returns a \code{person} object, the parsed #' authors. See \code{\link[utils]{person}} for details. #' #' \code{$get_author} returns a \code{person} object, all authors with #' the specified role. #' #' \code{$get_maintainer} returns the maintainer of the package. It works #' with \code{Authors@R} fields and with traditional \code{Maintainer} #' fields as well. #' #' \preformatted{ description$add_author(given = NULL, family = NULL, email = NULL, #' role = NULL, comment = NULL) #' description$add_me(role = "ctb", comment = NULL) #' } #' Add a new author. The arguments correspond to the arguments of the #' \code{\link[utils]{person}} function. \code{add_me} is a convenience #' function, it adds the current user as an author, and it needs the #' \code{whoami} package to be installed. #' #' \preformatted{ description$del_author(given = NULL, family = NULL, email = NULL, #' role = NULL, comment = NULL) #' } #' Remove an author, or multiple authors. The author(s) to be removed #' can be specified via any field(s). All authors matching all #' specifications will be removed. E.g. if only \code{given = "Joe"} #' is supplied, then all authors whole given name matches \code{Joe} will #' be removed. The specifications can be (PCRE) regular expressions. #' #' \preformatted{ description$add_role(role, given = NULL, family = NULL, email = NULL, #' comment = NULL) #' description$del_role(role, given = NULL, family = NULL, email = NULL, #' comment = NULL) #' description$change_maintainer(given = NULL, family = NULL, #' email = NULL, comment = NULL) #' } #' \code{role} is the role to add or delete. The other arguments #' are used to select a subset of the authors, on which the operation #' is performed, similarly to \code{$del_author}. #' #' @section URLs: #' #' We provide helper functions for manipulating URLs in the \code{URL} #' field: #' #' \preformatted{ description$get_urls() #' description$set_urls(urls) #' description$add_urls(urls) #' description$del_urls(pattern) #' description$clear_urls() #' } #' \describe{ #' \item{urls:}{Character vector of URLs to set or add.} #' \item{pattern:}{Perl compatible regular expression to specify the #' URLs to be removed.} #' } #' \code{$get_urls()} returns all urls in a character vector. If no URL #' fields are present, a zero length vector is returned. #' #' \code{$set_urls()} sets the URL field to the URLs specified in the #' character vector argument. #' #' \code{$add_urls()} appends the specified URLs to the URL field. It #' creates the field if it does not exists. Duplicate URLs are removed. #' #' \code{$del_urls()} deletes the URLs that match the specified pattern. #' #' \code{$clear_urls()} deletes all URLs. #' #' @section Remotes: #' #' \code{devtools}, \code{remotes} and some other packages support the #' non-standard \code{Remotes} field in \code{DESCRIPTION}. This field #' can be used to specify locations of dependent packages: GitHub or #' BitBucket repositories, generic git repositories, etc. Please see the #' \sQuote{Package remotes} vignette in the \code{devtools} package. #' #' \code{desc} has helper functions for manipulating the \code{Remotes} #' field: #' #' \preformatted{ description$get_remotes() #' description$get_remotes() #' description$set_remotes(remotes) #' description$add_remotes(remotes) #' description$del_remotes(pattern) #' description$clear_remotes() #' } #' \describe{ #' \item{remotes:}{Character vector of remote dependency locations to #' set or add.} #' \item{pattern:}{Perl compatible regular expression to specify the #' remote dependency locations to remove.} #' } #' \code{$get_remotes()} returns all remotes in a character vector. #' If no URL fields are present, a zero length vector is returned. #' #' \code{$set_remotes()} sets the URL field to the Remotes specified in the #' character vector argument. #' #' \code{$add_remotes()} appends the specified remotes to the #' \code{Remotes} field. It creates the field if it does not exists. #' Duplicate remotes are removed. #' #' \code{$del_remotes()} deletes the remotes that match the specified #' pattern. #' #' \code{$clear_remotes()} deletes all remotes. #' #' @section Built: #' #' The \sQuote{Built} field is used in binary packages to store information #' about when and how a binary package was built. #' #' \code{$get_built()} returns the built information as a list with fields #' \sQuote{R}, \sQuote{Platform}, \sQuote{Date}, \sQuote{OStype}. It throws an #' error if the package does not have a \sQuote{Built} field. #' #' @section Encodings: #' When creating a `description` object, `desc` observes the `Encoding` #' field, if present, and uses the specified encoding to parse the file. #' Internally, it converts all fields to UTF-8. #' #' When writing a `description` object to a file, `desc` uses the #' `Encoding` field (if present), and converts all fields to the specified #' encoding. #' #' We suggest that whenever you need to use non-ASCII characters in your #' package, you use the UTF-8 encoding, for maximum portability. #' #' @export #' @importFrom R6 R6Class #' @docType class #' @format An R6 class. #' #' @examples #' ## Create a template #' desc <- description$new("!new") #' desc #' #' ## Read a file #' desc2 <- description$new(file = system.file("DESCRIPTION", #' package = "desc")) #' desc2 #' #' ## Remove a field #' desc2$del("LazyData") #' #' ## Add another one #' desc2$set(VignetteBuilder = "knitr") #' desc2$get("VignetteBuilder") #' desc2 description <- R6Class("description", public = list( ## Either from a file, or from a character vector initialize = function(cmd = NULL, file = NULL, text = NULL, package = NULL) idesc_create(self, private, cmd, file, text, package), write = function(file = NULL) idesc_write(self, private, file), fields = function() idesc_fields(self, private), has_fields = function(keys) idesc_has_fields(self, private, keys), get = function(keys) idesc_get(self, private, keys), get_field = function(key, default = stop("Field '", key, "' not found"), trim_ws = TRUE) idesc_get_field(self, private, key, default, trim_ws), get_or_fail = function(keys) idesc_get_or_fail(self, private, keys), set = function(...) idesc_set(self, private, ...), del = function(keys) idesc_del(self, private, keys), validate = function() idesc_validate(self, private), print = function() idesc_print(self, private), str = function(by_field = FALSE, normalize = TRUE, mode = c("file", "screen")) idesc_str(self, private, by_field, normalize, mode), to_latex = function() idesc_to_latex(self, private), normalize = function() idesc_normalize(self, private), reformat_fields = function() idesc_reformat_fields(self, private), reorder_fields = function() idesc_reorder_fields(self, private), ## ----------------------------------------------------------------- ## Version numbers get_version = function() idesc_get_version(self, private), set_version = function(version) idesc_set_version(self, private, version), bump_version = function(which) idesc_bump_version(self, private, which), ## ----------------------------------------------------------------- ## Package dependencies set_dep = function(package, type = desc::dep_types, version = "*") idesc_set_dep(self, private, package, match.arg(type), version), set_deps = function(deps) idesc_set_deps(self, private, deps), get_deps = function() idesc_get_deps(self, private), del_dep = function(package, type = c("all", desc::dep_types)) idesc_del_dep(self, private, package, match.arg(type)), del_deps = function() idesc_del_deps(self, private), has_dep = function(package, type = c("any", desc::dep_types)) idesc_has_dep(self, private, package, match.arg(type)), ## ----------------------------------------------------------------- ## Collate fields set_collate = function(files, which = c("main", "windows", "unix")) idesc_set_collate(self, private, files, match.arg(which)), get_collate = function(which = c("main", "windows", "unix")) idesc_get_collate(self, private, match.arg(which)), del_collate = function(which = c("all", "main", "windows", "unix")) idesc_del_collate(self, private, match.arg(which)), add_to_collate = function(files, which = c("default", "all", "main", "windows", "unix")) idesc_add_to_collate(self, private, files, match.arg(which)), del_from_collate = function(files, which = c("all", "main", "windows", "unix")) idesc_del_from_collate(self, private, files, match.arg(which)), ## ----------------------------------------------------------------- ## Authors@R get_authors = function() idesc_get_authors(self, private), get_author = function(role = "cre") idesc_get_author(self, private, role), set_authors = function(authors) idesc_set_authors(self, private, authors), add_author = function(given = NULL, family = NULL, email = NULL, role = NULL, comment = NULL) idesc_add_author(self, private, given, family, email, role, comment), add_role = function(role, given = NULL, family = NULL, email = NULL, comment = NULL) idesc_add_role(self, private, role, given, family, email, comment), del_author = function(given = NULL, family = NULL, email = NULL, role = NULL, comment = NULL) idesc_del_author(self, private, given, family, email, role, comment), del_role = function(role, given = NULL, family = NULL, email = NULL, comment = NULL) idesc_del_role(self, private, role, given, family, email, comment), change_maintainer = function(given = NULL, family = NULL, email = NULL, comment = NULL) idesc_change_maintainer(self, private, given, family, email, comment), add_me = function(role = "ctb", comment = NULL) idesc_add_me(self, private, role, comment), get_maintainer = function() idesc_get_maintainer(self, private), ## ----------------------------------------------------------------- ## URL get_urls = function() idesc_get_urls(self, private), set_urls = function(urls) idesc_set_urls(self, private, urls), add_urls = function(urls) idesc_add_urls(self, private, urls), del_urls = function(pattern) idesc_del_urls(self, private, pattern), clear_urls = function() idesc_clear_urls(self, private), ## ----------------------------------------------------------------- ## Remotes get_remotes = function() idesc_get_remotes(self, private), set_remotes = function(remotes) idesc_set_remotes(self, private, remotes), add_remotes = function(remotes) idesc_add_remotes(self, private, remotes), del_remotes = function(pattern) idesc_del_remotes(self, private, pattern), clear_remotes = function() idesc_clear_remotes(self, private), ## ----------------------------------------------------------------- ## Built get_built = function() idesc_get_built(self, private) ), private = list( data = NULL, path = NULL, notws = character() # entries without trailing ws ) ) idesc_create <- function(self, private, cmd, file, text, package) { if (!is.null(cmd) && substring(cmd, 1, 1) != "!") { file <- cmd cmd <- NULL } if (!is.null(cmd)) { if (!is.null(file)) warning("file argument ignored") if (!is.null(text)) warning("text argument ignored") if (!is.null(package)) warning("package argument ignored") idesc_create_cmd(self, private, cmd) } else if (is.null(cmd) && is.null(file) && is.null(text) && is.null(package)) { idesc_create_file(self, private, ".") } else if (!is.null(file)) { if (!is.null(text)) warning("text argument ignored") if (!is.null(package)) warning("package argument ignored") idesc_create_file(self, private, file) } else if (!is.null(text)) { if (!is.null(package)) warning("package argument ignored") idesc_create_text(self, private, text) } else { idesc_create_package(self, private, package) } invisible(self) } idesc_create_cmd <- function(self, private, cmd = c("new")) { assert_that(is_constructor_cmd(cmd)) if (cmd == "!new") { idesc_create_text(self, private, text = 'Package: {{ Package }} Title: {{ Title }} Version: 1.0.0 Authors@R: c(person(given = "Jo", family = "Doe", email = "jodoe@dom.ain", role = c("aut", "cre"))) Maintainer: {{ Maintainer }} Description: {{ Description }} License: {{ License }} LazyData: true URL: {{ URL }} BugReports: {{ BugReports }} Encoding: UTF-8 ') } invisible(self) } idesc_create_file <- function(self, private, file) { assert_that(is_path(file)) if (file.exists(file) && is_dir(file)) file <- find_description(file) assert_that(is_existing_file(file)) if (is_package_archive(file)) { file <- get_description_from_package(file) } else { private$path <- normalizePath(file) } tryCatch( lines <- readLines(file), error = function(e) stop("Cannot read ", file, ": ", e$message) ) idesc_create_text(self, private, lines) } idesc_create_text <- function(self, private, text) { assert_that(is.character(text)) con <- textConnection(text, local = TRUE) on.exit(close(con), add = TRUE) dcf <- read_dcf(con) private$notws <- dcf$notws private$data <- dcf$dcf check_encoding(self, private, NULL) } idesc_create_package <- function(self, private, package) { assert_that(is_string(package)) path <- system.file(package = package, "DESCRIPTION") if (path == "") { stop("Cannot find DESCRIPTION for installed package ", package) } idesc_create_file(self, private, path) } #' @importFrom crayon strip_style idesc_write <- function(self, private, file) { if (is.null(file)) file <- private$path if (is.null(file)) { stop("Cannot write back DESCRIPTION. Note that it is not possible to update DESCRIPTION files within package archives") } mat <- idesc_as_matrix(private$data) if ("Encoding" %in% colnames(mat)) { encoding <- mat[, "Encoding"] mat[] <- iconv(mat[], from = "UTF-8", to = encoding) Encoding(mat) <- encoding } else { encoding <- "" } ## Need to write to a temp file first, to preserve absense of trailing ws tmp <- tempfile() on.exit(unlink(tmp), add = TRUE) write.dcf(mat, file = tmp, keep.white = names(private$data)) removed <- ! names(private$notws) %in% colnames(mat) if (any(removed)) private$notws <- private$notws[! removed] postprocess_trailing_ws(tmp, names(private$notws)) if (file.exists(file) && is_dir(file)) file <- find_description(file) ofile <- file(file, encoding = encoding, open = "w+") on.exit(close(ofile), add = TRUE) writeLines(readLines(tmp), ofile) invisible(self) } idesc_fields <- function(self, private) { names(private$data) } idesc_has_fields <- function(self, private, keys) { assert_that(is.character(keys), has_no_na(keys)) keys %in% self$fields() } idesc_as_matrix <- function(data) { matrix( vapply(data, "[[", "", "value"), nrow = 1, dimnames = list(NULL, names(data)) ) } idesc_get <- function(self, private, keys) { assert_that(is.character(keys), has_no_na(keys)) res <- lapply(private$data[keys], "[[", "value") res[vapply(res, is.null, logical(1))] <- NA_character_ res <- as.character(unlist(res)) names(res) <- keys res } idesc_get_field <- function(self, private, key, default, trim_ws) { assert_that(is_string(key)) assert_that(is_flag(trim_ws)) val <- private$data[[key]]$value if (trim_ws && !is.null(val)) val <- str_trim(val) val %||% default } idesc_get_or_fail <- function(self, private, keys) { assert_that(is.character(keys), has_no_na(keys)) res <- self$get(keys) if (any(is.na(res))) { w <- is.na(res) msg <- paste0( "Could not find DESCRIPTION ", if (sum(w) == 1) "field: " else "fields: ", paste(sQuote(keys[w]), collapse = ", "), "." ) stop(msg, call. = FALSE) } res } ## ... are either ## - two unnamed arguments, key and value, or ## - an arbitrary number of named arguments, the names are the keys, ## the values are the values idesc_set <- function(self, private, ...) { args <- list(...) if (is.null(names(args)) && length(args) == 2) { keys <- as_string(args[[1]]) values <- as_string(args[[2]]) } else if (!is.null(names(args)) && all(names(args) != "")) { keys <- names(args) values <- unlist(args) } else { stop("$set needs two unnamed args, or all named args, see docs") } fields <- create_fields(keys, enc2utf8(values)) lapply(fields, check_field, warn = TRUE) check_encoding(self, private, lapply(fields, "[[", "value")) private$data[keys] <- fields invisible(self) } idesc_del <- function(self, private, keys) { assert_that(is.character(keys), has_no_na(keys)) private$data <- private$data[setdiff(names(private$data), keys)] invisible(self) } desc/R/latex.R0000644000176200001440000000367513140567212012645 0ustar liggesusersidesc_to_latex <- function(self, private) { cols <- field_order(names(private$data)) col_str <- unlist(lapply( cols, FUN = function(col) { toLatex(private$data[[col]]) })) structure( c( "\\begin{description}", " \\raggedright{}", paste0(" ", col_str, collapse = "\n"), "\\end{description}" ), class = "Latex" ) } #' @importFrom utils toLatex NULL #' @export toLatex.character <- function(object, ...) { object <- gsub("'([^ ']*)'", "`\\1'", object, useBytes = TRUE) object <- gsub("\"([^\"]*)\"", "``\\1''", object, useBytes = TRUE) object <- gsub("\\", "\\textbackslash ", object, fixed = TRUE, useBytes = TRUE) object <- gsub("([{}$#_^%])", "\\\\\\1", object, useBytes = TRUE) object } #' @export toLatex.DescriptionField <- function(object, ...) { paste0("\\item[", object$key, "] ", toLatex(object$value)) } #' @export toLatex.DescriptionCollate <- function(object, ...) { invisible(NULL) } #' @export toLatex.DescriptionURLList <- function(object, ...) { paste0("\\item[", object$key, "] ", format_url(parse_url_list(object$value))) } #' @export toLatex.DescriptionURL <- function(object, ...) { paste0("\\item[", object$key, "] ", format_url(object$value)) } #' @export toLatex.DescriptionAuthorsAtR <- function(object, ...) { xx <- parse_authors_at_r(object$value) c( "\\item[Authors@R] ~\\\\", " \\begin{description}", paste0(" ", vapply(xx, toLatex, character(1L)), collapse = "\n"), " \\end{description}" ) } #' @export toLatex.person <- function(object, ...) { paste0( "\\item", format(object, include = c("role")), " ", format(object, include = c("given", "family")), " ", if (!is.null(object$email)) paste0("<\\href{mailto:", object$email, "}{", object$email, "}>"), format(object, include = c("comment")) ) } format_url <- function(object) { paste0("\\url{", object, "}", collapse = ", ") } desc/R/str.R0000644000176200001440000000660713244347461012345 0ustar liggesusers ## TODO: continuation lines idesc_str <- function(self, private, by_field, normalize = TRUE, mode = c("file", "screen")) { assert_that(is_flag(by_field)) mode <- match.arg(mode) cols <- names(private$data) if (normalize) cols <- field_order(cols) col_str <- vapply( cols, FUN.VALUE = "", FUN = function(col) { if (normalize) { format(private$data[[col]], mode = mode) } else { paste0( private$data[[col]]$key, ": ", mark_continuation_lines(private$data[[col]]$value) ) } }) if (by_field) col_str else paste(col_str, collapse = "\n") } field_order <- function(fields) { first <- c( "Type", "Package", "Title", "Version", "Date", "Authors@R", "Author", "Maintainer", "Description", "License", "URL", "BugReports", "Depends", setdiff(dep_types, "Depends"), "VignetteBuilder", "RdMacros", "Remotes" ) last <- collate_fields c( intersect(first, fields), sort(setdiff(fields, c(first, last))), intersect(last, fields) ) } #' @importFrom crayon red color_bad <- function(x) { if (identical(check_field(x), TRUE)) x$value else red(x$value) } #' @export #' @importFrom crayon blue #' @method format DescriptionField format.DescriptionField <- function(x, ..., width = 75) { mark_continuation_lines(paste( strwrap(paste0(blue(x$key), ": ", color_bad(x)), exdent = 4, width = width), collapse = "\n" )) } #' @export #' @importFrom crayon blue #' @method format DescriptionDependencyList format.DescriptionDependencyList <- function(x, ...) { paste0( blue(x$key), ":\n", paste0( " ", str_trim(strsplit(color_bad(x), ",", fixed = TRUE)[[1]]), collapse = ",\n" ) ) } #' @export #' @method format DescriptionPackageList format.DescriptionPackageList <- format.DescriptionDependencyList #' @export #' @method format DescriptionRemotes format.DescriptionRemotes <- format.DescriptionDependencyList #' @export #' @importFrom crayon blue #' @method format DescriptionCollate format.DescriptionCollate <- function(x, ...) { paste0( blue(x$key), ":", deparse_collate(parse_collate(color_bad(x))) ) } #' @export #' @importFrom crayon blue red #' @method format DescriptionAuthorsAtR format.DescriptionAuthorsAtR <- function(x, mode = c("file", "screen"), ...) { xx <- parse_authors_at_r(x$value) if (mode == "screen") { good <- check_field(x) xxx <- if (good) xx else red(xx) paste0( blue(x$key), " (parsed):\n", paste0(" * ", format(xxx), collapse = "\n") ) } else { paste0( x$key, ":", sub("\n$", "", deparse_authors_at_r(xx)) ) } } idesc_print <- function(self, private) { cat( idesc_str(self, private, by_field = FALSE, mode = "screen"), sep = "", "\n" ) invisible(self) } idesc_normalize <- function(self, private) { self$reformat_fields() self$reorder_fields() invisible(self) } #' @importFrom crayon strip_style idesc_reformat_fields <- function(self, private) { norm_fields <- strip_style(idesc_str(self, private, by_field = TRUE)) for (f in names(norm_fields)) { private$data[[f]]$value <- sub(paste0(f, ":[ ]?"), "", norm_fields[[f]]) } invisible(self) } idesc_reorder_fields <- function(self, private) { private$data <- private$data[field_order(names(private$data))] invisible(self) } desc/R/syntax_checks.R0000644000176200001440000002345513244347461014403 0ustar liggesusers chk <- function(msg, check) { if (check) TRUE else msg } chks <- function(..., x, warn) { results <- list(...) results <- unlist(setdiff(results, TRUE)) results <- if (length(results) == 0) TRUE else results if (! identical(results, TRUE) && warn) { warning( call. = FALSE, "'", x$key, "'", paste0( if (length(results) == 1) " " else "\n * ", strwrap(results, indent = 0, exdent = 6) ) ) } results } #' Syntactical check of a DESCRIPTION field #' #' @param x The field. #' @param warn Whether to generate a warning if the syntax check fails. #' @param ... Additional arguments, they might be used in the future. #' @return \code{TRUE} if the field is syntactically correct, #' otherwise a character vector, containing one or multiple #' error messages. #' #' @export check_field <- function(x, warn = FALSE, ...) UseMethod("check_field") #' @export #' @method check_field DescriptionField check_field.DescriptionField <- function(x, warn = FALSE, ...) TRUE ##' @export ##' @method check_field DescriptionPackage check_field.DescriptionPackage <- function(x, warn = FALSE, R = FALSE, ...) { ## In Depends, we can depend on certain 'R' versions if (R && x$value == "R") return(TRUE) chks( x = x, warn = warn, chk("must only contain ASCII letters, numbers, dots", grepl("^[a-zA-Z0-9\\.]*$", x$value)), chk("must be at least two characters long", nchar(x$value) >= 2), chk("must start with a letter", grepl("^[a-zA-Z]", x$value)), chk("must not end with a dot", !grepl("\\.$", x$value)) ) } valid_packagename_regexp <- "[[:alpha:]][[:alnum:].]*[[:alnum:]]" valid_version_regexp <- "[0-9]+[-\\.][0-9]+([-\\.][0-9]+)*" valid_package_archive_name <- paste0( "^", valid_packagename_regexp, "_", valid_version_regexp, "(.*)?", "(\\.tar\\.gz|\\.tgz|\\.zip)", "$" ) ##' @export ##' @method check_field DescriptionVersion check_field.DescriptionVersion <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk(paste("must be a sequence of at least two (usually three)", " non-negative integers separated by a single dot or dash", " character"), grepl(paste0("^", valid_version_regexp, "$"), x$value)) ) } ## TODO: It also must be a license R CMD check recognizes ## ##' @export ##' @method check_field DescriptionLicense check_field.DescriptionLicense <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must contain only ASCII characters", is_ascii(x$value)), chk("must not be empty", str_trim(x$value) != "") ) } ##' @export ##' @method check_field DescriptionDescription check_field.DescriptionDescription <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must not be empty", str_trim(x$value) != ""), chk("must contain one or more complete sentences", grepl("[.!?]['\")]?$", str_trim(x$value))), chk("must not start with 'The package', 'This Package, 'A package'", !grepl("^(The|This|A|In this|In the) package", x$value)), chk("must start with a capital letter", grepl("^['\"]?[[:upper:]]", x$value)) ) } ##' @export ##' @method check_field DescriptionTitle check_field.DescriptionTitle <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must not be empty", str_trim(x$value) != ""), chk("must not end with a period", !grepl("[.]$", str_trim(x$value)) || grepl("[[:space:]][.][.][.]|et[[:space:]]al[.]", str_trim(x$value))) ) } ##' @export ##' @method check_field DescriptionMaintainer check_field.DescriptionMaintainer <- function(x, warn = FALSE, ...) { re_maint <- paste0( "^[[:space:]]*(.*<", RFC_2822_email_regexp, ">|ORPHANED)[[:space:]]*$" ) chks( x = x, warn = warn, chk("must not be empty", str_trim(x$value) != ""), chk("must contain an email address", grepl(re_maint, x$value)) ) } ## TODO ##' @export ##' @method check_field DescriptionAuthorsAtR check_field.DescriptionAuthorsAtR <- function(x, warn = FALSE, ...) { TRUE } ##' @export ##' @method check_field DescriptionDependencyList check_field.DescriptionDependencyList <- function(x, warn = FALSE, ...) { deps <- parse_deps(x$key, x$value) is_package_list <- function(xx) { p <- lapply(xx, function(pc) check_field.DescriptionPackage( list(key = "Package", value = pc), R = x$key[1] == "Depends" ) ) all_true(p) } is_version_req <- function(x) { x <- str_trim(x) if (x == "*") return(TRUE) re <- paste0( "^(<=|>=|<|>|==|!=)\\s*", valid_version_regexp, "$" ) grepl(re, x) } is_version_req_list <- function(x) { all_true(vapply(x, is_version_req, TRUE)) } chks( x = x, warn = warn, chk("must contain valid package names", is_package_list(deps$package)), chk("must contain valid version requirements", is_version_req_list(deps$version)) ) } ##' @export ##' @method check_field DescriptionRemotes check_field.DescriptionRemotes <- function(x, warn = FALSE, ...) { is_remote <- function(x) { xx <- str_trim(strsplit(x, ",", fixed = TRUE)[[1]]) p <- grepl("^[^[:space:]]+$", xx) all_true(p) } chks( x = x, warn = warn, chk("must be a comma separated list of remotes", is_remote(x$value)) ) } ##' @export ##' @method check_field DescriptionPackageList check_field.DescriptionPackageList <- function(x, warn = FALSE, ...) { is_package_list <- function(x) { xx <- str_trim(strsplit(x, ",", fixed = TRUE)[[1]]) p <- lapply(xx, function(pc) check_field.DescriptionPackage(list(key = "Package", value = pc))) all_true(p) } chks( x = x, warn = warn, chk("must be a comma separated list of package names", is_package_list(x$value)) ) } ##' @export ##' @method check_field DescriptionRepoList check_field.DescriptionRepoList <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must be a comma separated list repository URLs", is_url_list(x$value)) ) } ##' @export ##' @method check_field DescriptionURL check_field.DescriptionURL <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must be a http, https or ftp URL", is_url(x$value)) ) } ##' @export ##' @method check_field DescriptionURLList check_field.DescriptionURLList <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must be a comma separated list of http, https or ftp URLs", is_url_list(x$value)) ) } ##' @export ##' @method check_field DescriptionPriority check_field.DescriptionPriority <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must be one of 'base', 'recommended' or 'defunct-base'", str_trim(x$value) %in% c("base", "recommended", "defunct-base")) ) } ##' @export ##' @method check_field DescriptionCollate check_field.DescriptionCollate <- function(x, warn = FALSE, ...) { coll <- tolower(parse_collate(x$value)) chks( x = x, warn = warn, chk("must contain a list of .R files", all(grepl("[.]r$", coll))) ) } ##' @export ##' @method check_field DescriptionLogical check_field.DescriptionLogical <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must be one of 'true', 'false', 'yes' or 'no' (case insensitive)", str_trim(tolower(x$value)) %in% c("true", "false", "yes", "no")) ) } ##' @export ##' @method check_field DescriptionEncoding check_field.DescriptionEncoding <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must be one of 'latin1', 'latin2' and 'UTF-8'", x$value %in% c("latin1", "latin2", "UTF-8")) ) } ##' @export ##' @method check_field DescriptionOSType check_field.DescriptionOSType <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must be one of 'unix' and 'windows'", x$value %in% c("unix", "windows")) ) } ##' @export ##' @method check_field DescriptionType check_field.DescriptionType <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must be either 'Package' or 'Translation'", x$value %in% c("Package", "Translation")) ) } ##' @export ##' @method check_field DescriptionClassification check_field.DescriptionClassification <- function(x, warn = FALSE, ...) { TRUE } ##' @export ##' @method check_field DescriptionLanguage check_field.DescriptionLanguage <- function(x, warn = FALSE, ...) { is_language_list <- function(x) { x <- str_trim(strsplit(x, ",", fixed = TRUE)[[1]]) all(grepl("^[a-z][a-z][a-z]?(-[A-Z]+)?$", x)) } chks( x = x, warn = warn, chk("must be a list of IETF language codes defined by RFC 5646", is_language_list(x$value)) ) } ##' @export ##' @method check_field DescriptionDate check_field.DescriptionDate <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk( paste0( "must be an ISO date: yyyy-mm-dd, but it is actually better\n", "to leave this field out completely. It is not required."), grepl("^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$", x$value) ) ) } ##' @export ##' @method check_field DescriptionCompression check_field.DescriptionCompression <- function(x, warn = FALSE, ...) { chks( x = x, warn = warn, chk("must be one of 'bzip2', 'xz', 'gzip'", x$value %in% c("bzip2", "xz", "gzip")) ) } ##' @export ##' @method check_field DescriptionRepository check_field.DescriptionRepository <- function(x, warn = FALSE, ...) { TRUE } ##' @export ##' @method check_field DescriptionFreeForm check_field.DescriptionFreeForm <- function(x, warn = FALSE, ...) { TRUE } ##' @export ##' @method check_field DescriptionAddedByRCMD check_field.DescriptionAddedByRCMD <- function(x, warn = FALSE, ...) { TRUE } desc/R/urls.R0000644000176200001440000000206613244347461012515 0ustar liggesusers parse_urls <- function(urls) { out <- str_trim(strsplit(str_trim(urls), "[,\\s]+", perl = TRUE)[[1]]) grep("^http", out, value = TRUE) } deparse_urls <- function(urls) { paste(urls, collapse = ",\n ") } idesc_get_urls <- function(self, private) { urls <- self$get("URL") if (is.na(urls)) { character() } else { parse_urls(urls) } } idesc_set_urls <- function(self, private, urls) { assert_that(is.character(urls)) self$set(URL = deparse_urls(urls)) invisible(self) } idesc_add_urls <- function(self, private, urls) { assert_that(is.character(urls)) urls <- unique(c(self$get_urls(), urls)) self$set(URL = deparse_urls(urls)) invisible(self) } idesc_del_urls <- function(self, private, pattern) { assert_that(is_string(pattern)) urls <- self$get_urls() filt <- grep(pattern, urls, invert = TRUE, value = TRUE, perl = TRUE) if (length(filt) > 0) { self$set(URL = deparse_urls(filt)) } else { self$del("URL") } invisible(self) } idesc_clear_urls <- function(self, private) { self$del("URL") invisible(self) } desc/R/constants.R0000644000176200001440000000376013140567212013537 0ustar liggesusers #' DESCRIPTION fields that denote package dependencies #' #' Currently it has the following ones: Imports, Depends, #' Suggests, Enhances and LinkingTo. See the \emph{Writing R Extensions} #' manual for when to use which. #' #' @family field types #' @export dep_types <- c("Imports", "Depends", "Suggests", "Enhances", "LinkingTo") standard_fields <- c( "Additional_repositories", "Author", "Authors@R", "Biarch", "BugReports", "BuildKeepEmpty", "BuildManual", "BuildResaveData", "BuildVignettes", "Built", "ByteCompile", "Classification/ACM", "Classification/ACM-2012", "Classification/JEL", "Classification/MSC", "Classification/MSC-2010", "Collate", "Collate.unix", "Collate.windows", "Contact", "Copyright", "Date", "Depends", "Description", "Encoding", "Enhances", "Imports", "KeepSource", "Language", "LazyData", "LazyDataCompression", "LazyLoad", "License", "LinkingTo", "MailingList", "Maintainer", "Note", "OS_type", "Package", "Packaged", "Priority", "Suggests", "SysDataCompression", "SystemRequirements", "Title", "Type", "URL", "Version", "VignetteBuilder", "ZipData", "Repository", "Path", "Date/Publication", "LastChangedDate", "LastChangedRevision", "Revision", "RcmdrModels", "RcppModules", "Roxygen", "Acknowledgements", "Acknowledgments", # USA/Canadian usage. "biocViews" ) #' A list of DESCRIPTION fields that are valid according to the CRAN checks #' #' @family field types #' @export cran_valid_fields <- c( standard_fields, "^(?:X-CRAN|Repository/R-Forge)", paste0(standard_fields, "Note") ) #' The DESCRIPTION fields that are supposed to be in plain ASCII encoding #' #' @family field types #' @export cran_ascii_fields <- c( "Package", "Version", "Priority", "Depends", "Imports", "LinkingTo", "Suggests", "Enhances", "License", "License_is_FOSS", "License_restricts_use", "OS_type", "Archs", "MD5sum", "NeedsCompilation", "Encoding" ) desc/R/read.R0000644000176200001440000000212613272145552012436 0ustar liggesusers ## TODO: handle empty files read_dcf <- function(file) { lines <- readLines(file) con <- textConnection(lines, local = TRUE) fields <- colnames(read.dcf(con)) close(con) if (!length(fields)) { return(list( dcf = create_fields(character(), character()), notws = character() )) } con <- textConnection(lines, local = TRUE) res <- read.dcf(con, keep.white = fields) close(con) con <- textConnection(lines, local = TRUE) res2 <- read.dcf(con, keep.white = fields, all = TRUE) close(con) if (any(mismatch <- res != res2)) { stop("Duplicate DESCRIPTION fields: ", paste(sQuote(colnames(res)[mismatch]), collapse = ", ")) } if ("Encoding" %in% colnames(res)) { encoding <- res[, "Encoding"] Encoding(res) <- encoding res[] <- enc2utf8(res) Encoding(lines) <- encoding lines <- enc2utf8(lines) } no_tws_fields <- sub( ":$", "", grep("^[^\\s]+:$", lines, perl = TRUE, value = TRUE) ) notws <- res[1, match(no_tws_fields, fields)] list( dcf = create_fields(fields, res[1, ]), notws = notws ) } desc/R/validate.R0000644000176200001440000000014513140567212013306 0ustar liggesusers idesc_validate <- function(self, private) { warning("Validation is not implemented yet") TRUE } desc/R/non-oo-api.R0000644000176200001440000004211013272065535013476 0ustar liggesusers # No coverage calculating here, since this code # runs during install time only. # nocov start #' @include description.R #' @importFrom utils packageName generate_api <- function(member, self = TRUE, norm = TRUE, invisible = FALSE) { res <- function() { } func <- description$public_methods[[member]] ## Arguments xargs <- list(file = ".") if (self && norm) xargs <- c(xargs, list(normalize = FALSE)) formals(res) <- c(formals(func), xargs) ## Call to member function member_call <- substitute( desc[[`_member`]](), list(`_member` = member) ) argnames <- names(formals(func)) dargs <- structure(lapply(argnames, as.name), names = argnames) if (!is.null(formals(func))) { member_call[1 + 1:length(formals(func))] <- dargs } desc_call <- substitute( result <- `_member`, list(`_member` = member_call) ) ## Call to write, or just return the result write_call <- if (self && norm) { quote({ if (normalize) desc$normalize() desc$write(file = file) }) } else if (self) { quote(desc$write(file = file)) } ## Put together body(res) <- substitute( { `_read`; `_trans`; `_write`; `_return` }, list( `_read` = quote(desc <- description$new(file = file)), `_trans` = desc_call, `_write` = write_call, `_return` = if (invisible) quote(invisible(result)) else quote(result) ) ) environment(res) <- asNamespace(packageName()) res } ## ------------------------------------------------------------------- #' List all fields in a DESCRIPTION file #' #' @inheritParams desc_set #' @return Character vector of fields. #' #' @family simple queries #' @export desc_fields <- generate_api("fields", self = FALSE) #' Check if some fields are present in a DESCRIPTION file #' #' @param keys Character vector of keys to check. #' @inheritParams desc_set #' @return Logical vector. #' #' @family simple queries #' @export desc_has_fields <- generate_api("has_fields", self = FALSE) #' Get a field from a DESCRIPTION file #' #' @param keys Character vector of fields to get. #' @inheritParams desc_set #' @return Character vector, values of the specified keys. #' Non-existing keys return \code{NA}. #' #' @family simple queries #' @export desc_get <- generate_api("get", self = FALSE) #' Get a single field from a DESCRIPTION file, fail if not found #' #' @inheritParams desc_get #' @param key The field to query. #' @param default Value to return if \code{key} is not found. #' By default it throws an error. #' @param trim_ws Whether to trim leading and trailing whitespace #' from the value. Defaults to \code{TRUE}. #' @return Character string, the value of \code{key}, or \code{default} #' if \code{key} is not found and \code{default} is specified. #' #' @family simple queries #' @export desc_get_field <- generate_api("get_field", self = FALSE) #' @rdname desc_get_field #' @export desc_get_or_fail <- generate_api("get_or_fail", self = FALSE) #' Set one or more fields in a DESCRIPTION file #' #' @details #' \code{desc_set} supports two forms, the first is two unnamed #' arguments: the key and its value to set. #' #' The second form requires named arguments: names are used as keys #' and values as values to set. #' #' @param ... Values to set, see details below. #' @param file DESCRIPTION file to use. By default the DESCRIPTION #' file of the current package (i.e. the package the working directory #' is part of) is used. #' @param normalize Whether to normalize the write when writing back #' the result. See \code{\link{desc_normalize}}. #' #' @family simple queries #' @export desc_set <- generate_api("set") #' Remove fields from a DESCRIPTION file #' #' @param keys Character vector of keys to remove. #' @inheritParams desc_set #' #' @family simple queries #' @export desc_del <- generate_api("del") ## ------------------------------------------------------------------- #' Print the contents of a DESCRIPTION file to the screen #' #' @inheritParams desc_set #' @export desc_print <- generate_api("print", self = FALSE, invisible = TRUE) #' Converts a DESCRIPTION file to LaTeX #' #' Returns the contents of the DESCRIPTION in LaTeX format. #' #' @inheritParams desc_set #' @export desc_to_latex <- generate_api("to_latex", self = FALSE) #' Normalize a DESCRIPTION file #' #' Re-formats and re-orders fields in DESCRIPTION in a standard way. #' #' @inheritParams desc_set #' @family repair functions #' @export desc_normalize <- generate_api("normalize", self = TRUE, norm = FALSE) #' Reformat fields in a DESCRIPTION file #' #' Reformat the fields in DESCRIPTION in a standard way. #' #' @inheritParams desc_set #' @family repair functions #' @export desc_reformat_fields <- generate_api("reformat_fields", self = TRUE, norm = FALSE) #' Reorder fields in a DESCRIPTION file #' #' Reorder the fields in DESCRIPTION in a standard way. #' #' @inheritParams desc_set #' @family repair functions #' @export desc_reorder_fields <- generate_api("reorder_fields", self = TRUE, norm = FALSE) #' Validate a DESCRIPTION file #' #' This function is not implemented yet. #' #' @inheritParams desc_set #' #' @export desc_validate <- generate_api("validate", self = FALSE) ## ------------------------------------------------------------------- #' List all package dependencies from a DESCRIPTION file #' #' @inheritParams desc_set #' @return Data frame with columns: \code{type} (dependency type), #' \code{package}, and \code{version}. For non-versioned dependencies #' \code{version} is \code{*}. #' #' @family dependencies #' @export desc_get_deps <- generate_api("get_deps", self = FALSE) #' Add a package dependency to a DESCRIPTION file #' #' @param package Package to depend on. #' @param type Dependency type. #' @param version Version to depend on, for versioned dependencies. #' @inheritParams desc_set #' #' @family dependencies #' @export desc_set_dep <- generate_api("set_dep") #' Set all package dependencies in DESCRIPTION #' #' @param deps Package dependency data frame, in the same format #' returned by \code{\link{desc_get_deps}}. #' @inheritParams desc_set #' #' @family dependencies #' @export desc_set_deps <- generate_api("set_deps") #' Remove a package dependency from DESCRIPTION #' #' @param package Package dependency to remove. #' @param type Dependency type to remove. Sometimes a package is depended #' on via multiple dependency types, e.g. \code{LinkingTo} and #' \code{Imports}. Defaults to all types. #' @inheritParams desc_set #' #' @family dependencies #' @export desc_del_dep <- generate_api("del_dep") #' Remove all dependencies from DESCRIPTION #' #' @inheritParams desc_set #' #' @family dependencies #' @export desc_del_deps <- generate_api("del_deps") #' Check for a dependency #' #' @inheritParams desc_set #' @param package The package name. #' @param type A dependency type or \sQuote{any}. #' @return A logical scalar. #' #' @family dependencies #' @export desc_has_dep <- generate_api("has_dep", self = FALSE) ## ------------------------------------------------------------------- #' Set the Collate field in DESCRIPTION #' #' @param files Collate field to set, as a character vector. #' @param which Which collate field to use. Collate fields can #' be operating system type specific. #' @inheritParams desc_set #' #' @family Collate field #' @export desc_set_collate <- generate_api("set_collate") #' Query the Collate field in DESCRIPTION #' #' @inheritParams desc_set_collate #' @return Character vector of file names. #' #' @family Collate field #' @export desc_get_collate <- generate_api("get_collate", self = FALSE) #' Delete the Collate field from DESCRIPTION #' #' @inheritParams desc_set_collate #' #' @family Collate field #' @export desc_del_collate <- generate_api("del_collate") #' Add one or more files to the Collate field, in DESCRIPTION #' #' @param files Character vector, files to add. #' @inheritParams desc_set_collate #' #' @family Collate field #' @export desc_add_to_collate <- generate_api("add_to_collate") #' Remove files from the Collate field. #' #' @param files Files to remove from the Collate field. #' @inheritParams desc_set_collate #' #' @family Collate field #' @export desc_del_from_collate <- generate_api("del_from_collate") ## ------------------------------------------------------------------- #' Query all authors in Authors@R, in DESCRIPTION #' #' @inheritParams desc_set #' @return A \code{\link[utils]{person}} object. #' #' @family Authors@R #' @export desc_get_authors <- generate_api("get_authors", self = FALSE) #' Query authors by role in Authors@R, in DESCRIPTION #' #' @param role Role to query. Defaults to the package maintainer. #' @inheritParams desc_set #' @return A \code{\link[utils]{person}} object. #' #' @family Authors@R #' @export desc_get_author <- generate_api("get_author", self = FALSE) #' Set authors in Authors@R, in DESCRIPTION #' #' @param authors Authors, to set, a \code{\link[utils]{person}} object. #' @inheritParams desc_set #' #' @family Authors@R #' @export desc_set_authors <- generate_api("set_authors") #' Add an author to Authors@R in DESCRIPTION #' #' @param given Given name. #' @param family Family name. #' @param email Email address. #' @param role Role. #' @param comment Comment. #' @inheritParams desc_set #' #' @family Authors@R #' @export desc_add_author <- generate_api("add_author") #' Add a role to one or more authors in Authors@R, in DESCRIPTION #' #' The author(s) can be specified by a combination of the \code{given}, #' \code{family}, \code{email} and \code{comment} fields. If multiple #' filters are specified, then all must match to identify the author(s). #' #' @param role Role to add. #' @param given Given name to filter on. Regular expression. #' @param family Family name to filter on. Regular expression. #' @param email Email address to filter on. Regular expression. #' @param comment Comment field to filter on. Regular expression. #' @inheritParams desc_set #' #' @family Authors@R #' @export desc_add_role <- generate_api("add_role") #' Remove one or more authors from DESCRIPTION. #' #' It uses the Authors@R field. The author(s) to be removed #' can be specified via any field(s). All authors matching all #' specifications will be removed. E.g. if only \code{given = "Joe"} #' is supplied, then all authors whole given name matches \code{Joe} will #' be removed. The specifications can be (PCRE) regular expressions. #' #' @param role Role to filter on. Regular expression. #' @inheritParams desc_add_role #' #' @family Authors@R #' @export desc_del_author <- generate_api("del_author") #' Delete a role of an author, in DESCRIPTION #' #' The author(s) can be specified by a combination of the \code{given}, #' \code{family}, \code{email} and \code{comment} fields. If multiple #' filters are specified, then all must match to identify the author(s). #' #' @param role Role to remove. #' @inheritParams desc_add_role #' #' @family Authors@R #' @export desc_del_role <- generate_api("del_role") #' Change maintainer of the package, in DESCRIPTION #' #' Only works with the Authors@R field. #' #' The current maintainer is kept if they have at least another role. #' #' @inheritParams desc_add_author #' #' @family Authors@R #' @export desc_change_maintainer <- generate_api("change_maintainer") #' Add the current user as an author to DESCRIPTION #' #' Uses the Authors@R field. #' #' @param role Role to set for the user, defaults to contributor. #' @param comment Comment, empty by default. #' @inheritParams desc_set #' #' @family Authors@R #' @export desc_add_me <- generate_api("add_me") #' Query the package maintainer in DESCRIPTION #' #' Either from the \sQuote{Maintainer} or the \sQuote{Authors@R} field. #' @inheritParams desc_set #' @return A character scalar. #' #' @family Authors@R #' @export desc_get_maintainer <- generate_api("get_maintainer", self = FALSE) ## ------------------------------------------------------------------- #' Query the URL field in DESCRIPTION #' #' @inheritParams desc_set #' @return A character vectors or URLs. A length zero vector is returned #' if there is no URL field in the package. #' #' @export desc_get_urls <- generate_api("get_urls", self = FALSE) #' Set the URL field in DESCRIPTION #' #' The specified urls replace the current ones. The URL field is created #' if it does not exist currently. #' #' @param urls A character vector of urls to set. #' @inheritParams desc_set #' #' @export desc_set_urls <- generate_api("set_urls") #' Add URLs to the URL field in DESCRIPTION #' #' @param urls Character vector of URLs to add. Duplicate URLs are #' eliminated. #' @inheritParams desc_set #' #' @export desc_add_urls <- generate_api("add_urls") #' Delete URLs from the URL field in DESCRIPTION #' #' All URLs matching the specified pattern are deleted. #' #' @param pattern Perl-compatible regular expression, all URLs #' matching this expression will be deleted. #' @inheritParams desc_set #' #' @export desc_del_urls <- generate_api("del_urls") #' Remove all URLs from the URL field of DESCRIPTION #' #' @inheritParams desc_set #' #' @export desc_clear_urls <- generate_api("clear_urls") ## ------------------------------------------------------------------- #' List the locations in the Remotes field in DESCRIPTION #' #' @inheritParams desc_set #' @return A character vectors or remote locations. A length zero vector #' is returned if there is no Remotes field in the package. #' #' @export desc_get_remotes <- generate_api("get_remotes", self = FALSE) #' Set the Remotes field in DESCRIPTION #' #' The specified locations replace the current ones. The Remotes field is #' created if it does not exist currently. #' #' @param remotes A character vector of remote locations to set. #' @inheritParams desc_set #' #' @export desc_set_remotes <- generate_api("set_remotes") #' Add locations in the Remotes field in DESCRIPTION #' #' @param remotes Character vector of remote locations to add. #' Duplicate locations are eliminated. Note that existing locations #' are not updated, so if you want to \emph{change} a remote location #' of a package, you need to delete the old location first and then add #' the new one. #' @inheritParams desc_set #' #' @export desc_add_remotes <- generate_api("add_remotes") #' Delete locations from the Remotes field in DESCRIPTION #' #' All locations matching the specified pattern are deleted. #' #' @param pattern Perl-compatible regular expression, all locations #' matching this expression will be deleted. #' @inheritParams desc_set #' #' @export desc_del_remotes <- generate_api("del_remotes") #' Remove all locations from the Remotes field of DESCRIPTION #' #' This simply means that the field is deleted. #' #' @inheritParams desc_set #' #' @export desc_clear_remotes <- generate_api("clear_remotes") ## ------------------------------------------------------------------- #' Query the package version in DESCRIPTION #' #' If the file has no \code{Version} field, or it is an invalid #' version string, then it throws an error. #' #' @inheritParams desc_set #' @return A \code{\link[base]{package_version}} object. #' #' @export #' @family version numbers desc_get_version <- generate_api("get_version", self = FALSE) #' Set the package version in DESCRIPTION #' #' Both \code{$set_version()} and \code{$bump_version()} use dots to #' separate the version number components. #' #' @param version A string or a \code{\link[base]{package_version}} #' object. #' @inheritParams desc_set #' #' @export #' @family version numbers desc_set_version <- generate_api("set_version") #' Increase the version number in DESCRIPTION #' #' The \code{which} parameter specifies which component to increase. #' It can be a string referring to a component: \sQuote{major}, #' \sQuote{minor}, \sQuote{patch} or \sQuote{dev}, or an integer #' scalar, for the latter components are counted from one, and the #' beginning. I.e. component one is equivalent to \sQuote{major}. #' #' If a component is bumped, then the ones after it are zeroed out. #' Trailing zero components are omitted from the new version number, #' but if the old version number had at least two or three components, then #' the one will also have two or three. #' #' The bumping of the \sQuote{dev} version (the fourth component) is #' special: if the original version number had less than four components, #' and the \sQuote{dev} version is bumped, then it is set to \code{9000} #' instead of \code{1}. This is a convention often used by R developers, #' it was originally invented by Winston Chang. #' #' Both \code{$set_version()} and \code{$bump_version()} use dots to #' separate the version number components. #' #' @param which Which component to increase. See details below. #' @inheritParams desc_set #' #' @export #' @family version numbers desc_bump_version <- generate_api("bump_version") ## ------------------------------------------------------------------- #' Query the built field in DESCRIPTION #' #' If the file has no \code{Built} field then it throws an error. #' #' @inheritParams desc_set #' @return A list with fields \sQuote{R}, \sQuote{Platform}, \sQuote{Date}, #' \sQuote{OStype}. #' #' @export #' @family built desc_get_built <- generate_api("get_built") ## ------------------------------------------------------------------- # nocov end desc/R/package-archives.R0000644000176200001440000000345713272143775014735 0ustar liggesusers is_package_archive <- function(file) { (is_zip_file(file) || is_tar_gz_file(file)) && is_valid_package_file_name(file) } is_zip_file <- function(file) { buf <- readBin(file, what = "raw", n = 4) length(buf) == 4 && buf[1] == 0x50 && buf[2] == 0x4b && (buf[3] == 0x03 || buf[3] == 0x05 || buf[5] == 0x07) && (buf[4] == 0x04 || buf[4] == 0x06 || buf[4] == 0x08) } is_gz_file <- function(file) { buf <- readBin(file, what = "raw", n = 3) length(buf) == 3 && buf[1] == 0x1f && buf[2] == 0x8b && buf[3] == 0x08 } is_tar_gz_file <- function(file) { if (!is_gz_file(file)) return(FALSE) con <- gzfile(file, open = "rb") on.exit(close(con)) buf <- readBin(con, what = "raw", n = 262) length(buf) == 262 && buf[258] == 0x75 && buf[259] == 0x73 && buf[260] == 0x74 && buf[261] == 0x61 && buf[262] == 0x72 } is_valid_package_file_name <- function(filename) { grepl(valid_package_archive_name, basename(filename)) } #' @importFrom utils untar unzip con_unzip <- function(archive, pkgname) { filename <- paste0(pkgname, "/", "DESCRIPTION") con <- unz(archive, filename) on.exit(close(con), add = TRUE) tmp <- tempfile() writeLines(readLines(con), tmp) tmp } con_untar <- function(archive, pkgname) { filename <- paste0(pkgname, "/", "DESCRIPTION") tmp <- tempfile() suppressWarnings( untar(con <- gzfile(archive, open = "rb"), files = filename, exdir = tmp) ) on.exit(close(con), add = TRUE) file.path(tmp, pkgname, "DESCRIPTION") } get_description_from_package <- function(file) { package_name <- sub("_.*$", "", basename(file)) uncompress <- if (is_zip_file(file)) con_unzip else con_untar desc <- uncompress(file, package_name) if (!file.exists(desc)) { stop("Cannot extract DESCRIPTION from ", sQuote(file)) } desc } desc/MD50000644000176200001440000001600413272151205011477 0ustar liggesusersb86271dba4b90ee25813e1c5c7e536f8 *DESCRIPTION 025c0d2002ef2eee68d6efeb1b491b51 *LICENSE 715baa891960362031d64ec86b110ca1 *NAMESPACE b5981018fa32df8e17b6e0043195ce6d *NEWS.md ed8edaeaa6e6bd7d906b46d2abd40c2e *R/assertions.R babff9502088d0d0062c6cccbe86c3eb *R/authors-at-r.R bba09b2d368a760ad19678aea7cd01da *R/built.R 096d34520a30148d3deb1c601eeeaa98 *R/classes.R 39c3291961f1119871f8b3576aa06c4d *R/collate.R 418508ee6da0653620bfbf67f4dfdbd5 *R/constants.R bdd603cc30f00bf039dc26a631922dcf *R/deps.R c2dc1085cb1c1c5beeaefa9c80f3ed1d *R/description.R b9a33d75ba5e712dd3c9c1409b59051e *R/encoding.R 8b53a4c108f2cba9e3b2684b30b00df0 *R/latex.R 79f1c7b01e48cf5c016f12e83478fc75 *R/non-oo-api.R bb45ae84f88b75c2bdaa05189109dbed *R/package-archives.R adb8c13862492f89d09a5fa75de63934 *R/read.R 0e8ef07509564dec52c3a2d743782bc6 *R/remotes.R 868311c2ab965fe996b2e7231ee0c7fc *R/str.R ccaa0643890eea92ce55d8ae569c8c4c *R/syntax_checks.R d3ae60045e7c45fa38a1bcdc98dc3085 *R/urls.R 615ac8971db9a824283c6843bc78ee76 *R/utils.R 7609c65315c4ccc461b4312b88e44e62 *R/validate.R 9b3b1554e0ec41655574a6ba78f8a84a *R/version.R 3ba0ce861688512cabe7cf512952e4cc *inst/DESCRIPTION dcee715ad05f22f9ea9015c7b9b4b0fc *inst/DESCRIPTION2 b5981018fa32df8e17b6e0043195ce6d *inst/NEWS.md f5dd776d89269a77944793a332a22780 *inst/README.Rmd cc864f45caf0ed10cfe4af4e86e8286b *inst/README.md 01fb02223acdafc3781bf5ebfbbf2add *man/check_encoding.Rd 7e5ed2e9239d833fb6dfdb79cd33b4b4 *man/check_field.Rd c8dcee3f54cb515d8e515be96876f294 *man/cran_ascii_fields.Rd 6f07f0ebe6e974ec7b4c36605cd9578b *man/cran_valid_fields.Rd b5e628d0d438569a3af1ca8117d8bdc0 *man/dep_types.Rd 5ed873c0a4c47152d098f34e31abb773 *man/desc.Rd bc7485adab68f34cb5270fbb86ecc33b *man/desc_add_author.Rd 581e655b0931bf1f5f1c86da2ed1064e *man/desc_add_me.Rd 71706994e9b0be7f75c8b2e7eacbeedf *man/desc_add_remotes.Rd 6d4f9b9625a87e845499c9154447f4b6 *man/desc_add_role.Rd 7452c0ff3a0edcc6960999ed8cb28713 *man/desc_add_to_collate.Rd 891dc1dadafa3b454b0603d73e0d57aa *man/desc_add_urls.Rd 5c2b16f6acb60f785ff1be75b9f74ab9 *man/desc_bump_version.Rd 0b4b097b33ade83f1c1e6d3cefebb8b6 *man/desc_change_maintainer.Rd dc77c76d09b96aa30d0cca6a86debe40 *man/desc_clear_remotes.Rd a96c15eb21a62d796f73254995f0f44f *man/desc_clear_urls.Rd 9c49ac934dee96c920e227ccf0dbf7e6 *man/desc_del.Rd 902a5d2b44d1e0f0dc65a3b2a8fbf546 *man/desc_del_author.Rd 7b2c6ece367da3ecc13d1e27e2d810bd *man/desc_del_collate.Rd 7f1b5e2410953d0d7d7471eec6c94208 *man/desc_del_dep.Rd 122c796bda01afad3dd20660144961b7 *man/desc_del_deps.Rd be02617f9ed6d1ee302aeabaed5b73b2 *man/desc_del_from_collate.Rd bb28faf1c729437fb533c3fc4232178a *man/desc_del_remotes.Rd 2d36a78ba974e9fb893f94d0ce4c9f99 *man/desc_del_role.Rd c5aeee74741c9a60a52b6a6af11f343d *man/desc_del_urls.Rd 78b64b1b2180517419fae6a966ac43e0 *man/desc_fields.Rd 9a80e7efd0683761ae62452fbf33c5e5 *man/desc_get.Rd 6939bb9a44ea862b563bd87e8e799639 *man/desc_get_author.Rd bcca6ccec35b6152a54a8f95354eadbc *man/desc_get_authors.Rd 286b3632ba23140878498380a65bba5c *man/desc_get_built.Rd ffdd1bef54cc6c839291282ab2978e0d *man/desc_get_collate.Rd 238699270f872bbb78989035fba5ee6d *man/desc_get_deps.Rd a8411a5cd6e11e96dcb303054b65bc8c *man/desc_get_field.Rd 01a022d72e33e83a9676fdb9934e1d4e *man/desc_get_maintainer.Rd f8a71db35581155e6a1aa702e197e06e *man/desc_get_remotes.Rd 191429364648ee2946274f88bac6e8af *man/desc_get_urls.Rd 844f88dd93ea42e9e3c97399aca47c5e *man/desc_get_version.Rd 2723a49904eb811e0f7b45ec0320dde2 *man/desc_has_dep.Rd b669f3fc390346108ad9019b418402c2 *man/desc_has_fields.Rd 6d207f0036cda26c7ad14fa1cd5b4eec *man/desc_normalize.Rd 6c1f784506911f67d26aa7357e9cac33 *man/desc_print.Rd 535731aab664aaa4d2d8c506f39a63d8 *man/desc_reformat_fields.Rd f8767056484081498e889dbb4cda2ea7 *man/desc_reorder_fields.Rd 9f9747c659910a1ebdb6095b20fa2ad4 *man/desc_set.Rd ed99c5e07e73497725ea4e4542c35311 *man/desc_set_authors.Rd 26e28cf259babc1907260dde4d27608f *man/desc_set_collate.Rd 114340f4c11e97a5876f890495ca261f *man/desc_set_dep.Rd 446041170ff1776508fdcaf42ec8cfac *man/desc_set_deps.Rd 2eb5d8e5c2de3230a6f58355706a184b *man/desc_set_remotes.Rd f22cccff4053b69fb690a7e0f5dca57a *man/desc_set_urls.Rd 7c3c2a80e1c2f19b2e606b6a345cc5d4 *man/desc_set_version.Rd 644b0b378ca68574140981e51075c4b9 *man/desc_to_latex.Rd 3796d76d4f7e600ff05a25dff40e9f9a *man/desc_validate.Rd b7e9a08954f40e6d484040ee38d90624 *man/description.Rd 8b3b1faf4317298ade0b68c8641110cb *tests/testthat.R be96b5143b1d6266291d4f09583b9cee *tests/testthat/D1 c7c30e1187575c55c4788e0a40d22196 *tests/testthat/D2 0c5171c23afb3abfc6e7fb9810b44ff6 *tests/testthat/D3 add1c497f8147559d80791424d3b14ea *tests/testthat/D4 2c9323b51bd0b848494819c3ee05d1e7 *tests/testthat/D5 38d36d6af112caac5d2c380d2055b689 *tests/testthat/D6 4bbb71a613bde089e0d904c41d57bcf5 *tests/testthat/D7 6b5d80f6a1a9ddf463bc52114f22d809 *tests/testthat/D8 be96b5143b1d6266291d4f09583b9cee *tests/testthat/files/DESCRIPTION 6dc77ce3ba4e9b5ecb2d5e53e7a129e2 *tests/testthat/fixtures/notpkg_1.0.tar.gz 1261a114ea4b6fb4e2ab27228146c2ef *tests/testthat/fixtures/pkg_1.0.0.tar.gz 5cdce130ef8ad8360e3cea164cfe6857 *tests/testthat/fixtures/pkg_1.0.0.tgz 16b679a005c779189526a77b446ed5f6 *tests/testthat/fixtures/pkg_1.0.0.zip 39f0cbfa42fb7e0643ef19ea07749d7e *tests/testthat/fixtures/pkg_1.0.0_R_x86_64-pc-linux-gnu.tar.gz aef8f02891aa60e66955e23356e6e3a4 *tests/testthat/fixtures/xxx.gz 6dc77ce3ba4e9b5ecb2d5e53e7a129e2 *tests/testthat/fixtures/xxx.tar.gz 267812fc7bc60f0a742afcfc33acfc62 *tests/testthat/fixtures/xxx.zip 4a2335de80a9f8648445cba2aabd583f *tests/testthat/helper.R 681b5cdb593bafa9ce5f35dfae530be2 *tests/testthat/output/to_latex.tex 8322c48f91b52412f74b2730d346dabd *tests/testthat/test-archives.R 3e3b38c6d6129320480ee5a6a0a2e225 *tests/testthat/test-assertions.R 7bd7ce4859d9b2d204e91128660b7df6 *tests/testthat/test-authors.R 6915b5dd7cb79aa6ab3b16d5b799b792 *tests/testthat/test-built.R 04d167df04fa31c835f34400d66dc7eb *tests/testthat/test-checks.R bb3600ff906f59f20c74ad662ba470c2 *tests/testthat/test-collate.R 7f7769b4cdc0f3d15f849ee53f1e3d10 *tests/testthat/test-create.R a75046c44c5ddac702cdf5bbfd6050e0 *tests/testthat/test-deps.R 91a2fffc2a8f29c7ffe5e3993bc9be82 *tests/testthat/test-desc.R cafa51d55f9a7fec8bad162921a8455b *tests/testthat/test-encoding.R 0484cad7c85958a2841b2cd9846b6a90 *tests/testthat/test-idempotent.R e38db19967977d0de240ccef06521f54 *tests/testthat/test-non-oo.R 1814b4a663e23c2c36252496e16848fe *tests/testthat/test-queries.R 5e48c570615478c9fa36b543069bd57c *tests/testthat/test-read.R d6022122264f82e96667d62b70c188fb *tests/testthat/test-remotes.R 09d6ed54453d8d642af2d07f0565a75f *tests/testthat/test-repair.R 9f013efc2c1db92325485fef4baf68dd *tests/testthat/test-str.R 74cf5921bed15757fc60d0d956b62bc7 *tests/testthat/test-to_latex.R 62fb74840dc93877d9a61ca6d68f4734 *tests/testthat/test-trailing-ws.R 0b030faa2a7ea613f22dec62dea9c5ca *tests/testthat/test-urls.R 418c886aee25cdc0e088d2b1bbea79ec *tests/testthat/test-utils.R 0f287c1718c783216568c3f0aebd0ade *tests/testthat/test-validation.R bbfa92ac5f36579f74e68a83e680f97c *tests/testthat/test-versions.R a940987c73f36e3084a33ff85a6d87b2 *tests/testthat/test-write.R desc/DESCRIPTION0000644000176200001440000000240513272151205012675 0ustar liggesusersPackage: desc Title: Manipulate DESCRIPTION Files Version: 1.2.0 Authors@R: c( person("Gábor", "Csárdi",, "csardi.gabor@gmail.com", role = c("aut", "cre")), person("Kirill", "Müller", role = c("aut")), person("Jim", "Hester", email = "james.f.hester@gmail.com", role = c("aut"))) Maintainer: Gábor Csárdi Description: Tools to read, write, create, and manipulate DESCRIPTION files. It is intended for packages that create or manipulate other packages. License: MIT + file LICENSE LazyData: true URL: https://github.com/r-lib/desc#readme BugReports: https://github.com/r-lib/desc/issues Depends: R (>= 3.1.0) Suggests: covr, testthat, whoami, withr Imports: assertthat, utils, R6, crayon, rprojroot Encoding: UTF-8 RoxygenNote: 6.0.1.9000 Collate: 'assertions.R' 'authors-at-r.R' 'built.R' 'classes.R' 'collate.R' 'constants.R' 'deps.R' 'description.R' 'encoding.R' 'latex.R' 'non-oo-api.R' 'package-archives.R' 'read.R' 'remotes.R' 'str.R' 'syntax_checks.R' 'urls.R' 'utils.R' 'validate.R' 'version.R' NeedsCompilation: no Packaged: 2018-05-01 20:22:08 UTC; gaborcsardi Author: Gábor Csárdi [aut, cre], Kirill Müller [aut], Jim Hester [aut] Repository: CRAN Date/Publication: 2018-05-01 20:48:05 UTC desc/man/0000755000176200001440000000000013272145436011752 5ustar liggesusersdesc/man/desc_add_author.Rd0000644000176200001440000000216313272145436015353 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_add_author} \alias{desc_add_author} \title{Add an author to Authors@R in DESCRIPTION} \usage{ desc_add_author(given = NULL, family = NULL, email = NULL, role = NULL, comment = NULL, file = ".", normalize = FALSE) } \arguments{ \item{given}{Given name.} \item{family}{Family name.} \item{email}{Email address.} \item{role}{Role.} \item{comment}{Comment.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Add an author to Authors@R in DESCRIPTION } \seealso{ Other Authors@R: \code{\link{desc_add_me}}, \code{\link{desc_add_role}}, \code{\link{desc_change_maintainer}}, \code{\link{desc_del_author}}, \code{\link{desc_del_role}}, \code{\link{desc_get_authors}}, \code{\link{desc_get_author}}, \code{\link{desc_get_maintainer}}, \code{\link{desc_set_authors}} } \concept{Authors@R} desc/man/desc_get.Rd0000644000176200001440000000140013272145436014011 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get} \alias{desc_get} \title{Get a field from a DESCRIPTION file} \usage{ desc_get(keys, file = ".") } \arguments{ \item{keys}{Character vector of fields to get.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ Character vector, values of the specified keys. Non-existing keys return \code{NA}. } \description{ Get a field from a DESCRIPTION file } \seealso{ Other simple queries: \code{\link{desc_del}}, \code{\link{desc_fields}}, \code{\link{desc_get_field}}, \code{\link{desc_has_fields}}, \code{\link{desc_set}} } \concept{simple queries} desc/man/desc_del_dep.Rd0000644000176200001440000000202713272145436014634 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_del_dep} \alias{desc_del_dep} \title{Remove a package dependency from DESCRIPTION} \usage{ desc_del_dep(package, type = c("all", desc::dep_types), file = ".", normalize = FALSE) } \arguments{ \item{package}{Package dependency to remove.} \item{type}{Dependency type to remove. Sometimes a package is depended on via multiple dependency types, e.g. \code{LinkingTo} and \code{Imports}. Defaults to all types.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Remove a package dependency from DESCRIPTION } \seealso{ Other dependencies: \code{\link{desc_del_deps}}, \code{\link{desc_get_deps}}, \code{\link{desc_has_dep}}, \code{\link{desc_set_deps}}, \code{\link{desc_set_dep}} } \concept{dependencies} desc/man/dep_types.Rd0000644000176200001440000000111413272145436014232 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/constants.R \docType{data} \name{dep_types} \alias{dep_types} \title{DESCRIPTION fields that denote package dependencies} \format{An object of class \code{character} of length 5.} \usage{ dep_types } \description{ Currently it has the following ones: Imports, Depends, Suggests, Enhances and LinkingTo. See the \emph{Writing R Extensions} manual for when to use which. } \seealso{ Other field types: \code{\link{cran_ascii_fields}}, \code{\link{cran_valid_fields}} } \concept{field types} \keyword{datasets} desc/man/description.Rd0000644000176200001440000003776513272065400014576 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/description.R \docType{class} \name{description} \alias{description} \title{Read, write, update, validate DESCRIPTION files} \format{An R6 class.} \usage{ description } \description{ Read, write, update, validate DESCRIPTION files } \section{Constructors}{ There are two ways of creating a description object. The first is reading an already existing \code{DESCRIPTION} file; simply give the name of the file as an argument. The default is \code{DESCRIPTION}: \preformatted{ x <- description$new() x2 <- description$new("path/to/DESCRIPTION")} The second way is creating a description object from scratch, supply \code{"!new"} as an argument to do this. \preformatted{ x3 <- description$new("!new")} The complete API reference: \preformatted{description$new(cmd = NULL, file = NULL, text = NULL, package = NULL)} \describe{ \item{cmd:}{A command to create a description from scratch. Currently only \code{"!new"} is implemented. If it does not start with an exclamation mark, it will be interpreted as a \sQuote{file} argument.} \item{file:}{Name of the \code{DESCRIPTION} file to load. If it is a directory, then we assume that it is inside an R package and conduct a search for the package root directory, i.e. the first directory up the tree that contains a \code{DESCRIPTION} file. If \sQuote{cmd}, \sQuote{file}, \sQuote{text} and \sQuote{package} are all \code{NULL} (the default), then the search is started from the working directory. The file can also be an R package (source, or binary), in which case the DESCRIPTION file is extracted from it, but note that in this case \code{$write()} cannot write the file back in the package archive.} \item{text:}{A character scalar containing the full DESCRIPTION. Character vectors are collapsed into a character scalar, with newline as the separator.} \item{package}{If not NULL, then the name of an installed package and the DESCRIPTION file of this package will be loaded.} } } \section{Setting and Querying fields}{ Set a field with \code{$set} and query it with \code{$get}: \preformatted{ x <- description$new("!new") x$get("Package) x$set("Package", "foobar") x$set(Title = "Example Package for 'description'") x$get("Package")} Note that \code{$set} has two forms. You can either give the field name and new value as two arguments; or you can use a single named argument, the argument name is the field name, the argument value is the field value. The \code{$fields} method simply lists the fields in the object: \preformatted{ x$fields()} The \code{$has_fields} method checks if one or multiple fields are present in a description object: \preformatted{ x$has_fields("Package") x$has_fields(c("Title", "foobar"))} The \code{$del} method removes the specified fields: \preformatted{ x$set(foo = "bar") x$del("foo")} \code{$get_field} is similar to \code{$get}, but it queries a single field, it returns an unnamed vector if found, and returns the specified \code{default} value if not. By default it throws an error if the field is not found. The complete API reference: \preformatted{ description$get(keys) description$get_field(key, default, trim_ws = TRUE) description$set(...) description$fields() description$has_fields(keys) description$del(keys)} \describe{ \item{key:}{A character string (length one), the key to query.} \item{default:}{If specified and \code{key} is missing, this value is returned. If not specified, an error is thrown.} \item{trim_ws:}{Whether to trim leading and trailing whitespace from the returned value.} \item{keys:}{A character vector of keys to query, check or delete.} \item{...:}{This must be either two unnamed arguments, the key and and the value to set; or an arbitrary number of named arguments, names are used as keys, values as values to set.} } } \section{Normalizing}{ Format DESCRIPTION in a standard way. \code{$str} formats each field in a standard way and returns them (it does not change the object itself), \code{$print} is used to print it to the screen. The \code{$normalize} function normalizes each field (i.e. it changes the object). Normalization means reformatting the fields, via \code{$reformat_fields()} and also reordering them via \code{$reorder_fields()}. The format of the various fields is opinionated and you might like it or not. Note that \code{desc} only re-formats fields that it updates, and only on demand, so if your formatting preferences differ, you can still manually edit \code{DESCRIPTION} and \code{desc} will respect your edits. \preformatted{ description$str(by_field = FALSE, normalize = TRUE, mode = c("file", "screen")) description$normalize() description$reformat_fields() description$reorder_fields() description$print() } \describe{ \item{by_field:}{Whether to return the normalized format by field, or collapsed into a character scalar.} \item{normalize:}{Whether to reorder and reformat the fields.} \item{mode:}{\sQuote{file} mode formats the fields as they are written to a file with the \code{write} method. \sQuote{screen} mode adds extra markup to some fields, e.g. formats the \code{Authors@R} field in a readable way.} } } \section{Writing it to file}{ The \code{$write} method writes the description to a file. By default it writes it to the file it was created from, if it was created from a file. Otherwise giving a file name is compulsory: \preformatted{ x$write(file = "DESCRIPTION")} The \code{normalize} argument controls whether the fields are reformatted according to a standard style. By default they are not. The API: \preformatted{ description$write(file = NULL, normalize = NULL)} \describe{ \item{file:}{Path to write the description to. If it was created from a file in the first place, then it is written to the same file. Otherwise this argument must be specified.} \item{normalize:}{Whether to reformat the fields in a standard way.} } } \section{Version numbers}{ \preformatted{ description$get_version() description$set_version(version) description$bump_version(which = c("patch", "minor", "major", "dev")) } \describe{ \item{version:}{A string or a \code{\link[base]{package_version}} object.} \item{which:}{Which component of the version number to increase. See details just below.} } These functions are simple helpers to make it easier to query, set and increase the version number of a package. \code{$get_version()} returns the version number as a \code{\link[base]{package_version}} object. It throws an error if the package does not have a \sQuote{Version} field. \code{$set_version()} takes a string or a \code{\link[base]{package_version}} object and sets the \sQuote{Version} field to it. \code{$bump_version()} increases the version number. The \code{which} parameter specifies which component to increase. It can be a string referring to a component: \sQuote{major}, \sQuote{minor}, \sQuote{patch} or \sQuote{dev}, or an integer scalar, for the latter components are counted from one, and the beginning. I.e. component one is equivalent to \sQuote{major}. If a component is bumped, then the ones after it are zeroed out. Trailing zero components are omitted from the new version number, but if the old version number had at least two or three components, then the one will also have two or three. The bumping of the \sQuote{dev} version (the fourth component) is special: if the original version number had less than four components, and the \sQuote{dev} version is bumped, then it is set to \code{9000} instead of \code{1}. This is a convention often used by R developers, it was originally invented by Winston Chang. Both \code{$set_version()} and \code{$bump_version()} use dots to separate the version number components. } \section{Dependencies}{ These functions handle the fields that define how the R package uses another R packages. See \code{\link{dep_types}} for the list of fields in this group. The \code{$get_deps} method returns all declared dependencies, in a data frame with columns: \code{type}, \code{package} and \code{version}. \code{type} is the name of the dependency field, \code{package} is the name of the R package, and \code{version} is the required version. If no specific versions are required, then this is a \code{"\*"}. The \code{$set_deps} method is the opposite of \code{$get_deps} and it sets all dependencies. The input is a data frame, with the same structure as the return value of \code{$get_deps}. The \code{$has_dep} method checks if a package is included in the dependencies. It returns a logical scalar. If \code{type} is not \sQuote{any}, then it has to match as well. The \code{$del_deps} method removes all declared dependencies. The \code{$set_dep} method adds or updates a single dependency. By default it adds the package to the \code{Imports} field. The API: \preformatted{ description$set_dep(package, type = dep_types, version = "\*") description$set_deps(deps) description$get_deps() description$has_dep(package, type = c("any", dep_types)) description$del_dep(package, type = c("all", dep_types)) description$del_deps() } \describe{ \item{package:}{Name of the package to add to or remove from the dependencies.} \item{type:}{Dependency type, see \code{\link{dep_types}}. For \code{$del_dep} it may also be \code{"all"}, and then the package will be deleted from all dependency types.} \item{version:}{Required version. Defaults to \code{"\*"}, which means no explicit version requirements.} \item{deps:}{A data frame with columns \code{type}, \code{package} and \code{version}. \code{$get_deps} returns the same format.} } } \section{Collate fields}{ Collate fields contain lists of file names with R source code, and the package has a separate API for them. In brief, you can use \code{$add_to_collate} to add one or more files to the main or other collate field. You can use \code{$del_from_collate} to remove it from there. The API: \preformatted{ description$set_collate(files, which = c("main", "windows", "unix")) description$get_collate(which = c("main", "windows", "unix")) description$del_collate(which = c("all", "main", "windows", "unix")) description$add_to_collate(files, which = c("default", "all", "main", "windows", "unix")) description$del_from_collate(files, which = c("all", "main", "windows", "unix")) } \describe{ \item{files:}{The files to add or remove, in a character vector.} \item{which:}{Which collate field to manipulate. \code{"default"} for \code{$add_to_collate} means all existing collate fields, or the main one if none exist.} } } \section{Authors}{ There is a specialized API for the \code{Authors@R} field, to add and remove authors, update their roles, change the maintainer, etc. The API: \preformatted{ description$get_authors() description$set_authors(authors) description$get_author(role) description$get_maintainer() } \describe{ \item{authors:}{A \code{person} object, a list of authors.} \item{role:}{The role to query. See \code{person} for details.} } \code{$get_authors} returns a \code{person} object, the parsed authors. See \code{\link[utils]{person}} for details. \code{$get_author} returns a \code{person} object, all authors with the specified role. \code{$get_maintainer} returns the maintainer of the package. It works with \code{Authors@R} fields and with traditional \code{Maintainer} fields as well. \preformatted{ description$add_author(given = NULL, family = NULL, email = NULL, role = NULL, comment = NULL) description$add_me(role = "ctb", comment = NULL) } Add a new author. The arguments correspond to the arguments of the \code{\link[utils]{person}} function. \code{add_me} is a convenience function, it adds the current user as an author, and it needs the \code{whoami} package to be installed. \preformatted{ description$del_author(given = NULL, family = NULL, email = NULL, role = NULL, comment = NULL) } Remove an author, or multiple authors. The author(s) to be removed can be specified via any field(s). All authors matching all specifications will be removed. E.g. if only \code{given = "Joe"} is supplied, then all authors whole given name matches \code{Joe} will be removed. The specifications can be (PCRE) regular expressions. \preformatted{ description$add_role(role, given = NULL, family = NULL, email = NULL, comment = NULL) description$del_role(role, given = NULL, family = NULL, email = NULL, comment = NULL) description$change_maintainer(given = NULL, family = NULL, email = NULL, comment = NULL) } \code{role} is the role to add or delete. The other arguments are used to select a subset of the authors, on which the operation is performed, similarly to \code{$del_author}. } \section{URLs}{ We provide helper functions for manipulating URLs in the \code{URL} field: \preformatted{ description$get_urls() description$set_urls(urls) description$add_urls(urls) description$del_urls(pattern) description$clear_urls() } \describe{ \item{urls:}{Character vector of URLs to set or add.} \item{pattern:}{Perl compatible regular expression to specify the URLs to be removed.} } \code{$get_urls()} returns all urls in a character vector. If no URL fields are present, a zero length vector is returned. \code{$set_urls()} sets the URL field to the URLs specified in the character vector argument. \code{$add_urls()} appends the specified URLs to the URL field. It creates the field if it does not exists. Duplicate URLs are removed. \code{$del_urls()} deletes the URLs that match the specified pattern. \code{$clear_urls()} deletes all URLs. } \section{Remotes}{ \code{devtools}, \code{remotes} and some other packages support the non-standard \code{Remotes} field in \code{DESCRIPTION}. This field can be used to specify locations of dependent packages: GitHub or BitBucket repositories, generic git repositories, etc. Please see the \sQuote{Package remotes} vignette in the \code{devtools} package. \code{desc} has helper functions for manipulating the \code{Remotes} field: \preformatted{ description$get_remotes() description$get_remotes() description$set_remotes(remotes) description$add_remotes(remotes) description$del_remotes(pattern) description$clear_remotes() } \describe{ \item{remotes:}{Character vector of remote dependency locations to set or add.} \item{pattern:}{Perl compatible regular expression to specify the remote dependency locations to remove.} } \code{$get_remotes()} returns all remotes in a character vector. If no URL fields are present, a zero length vector is returned. \code{$set_remotes()} sets the URL field to the Remotes specified in the character vector argument. \code{$add_remotes()} appends the specified remotes to the \code{Remotes} field. It creates the field if it does not exists. Duplicate remotes are removed. \code{$del_remotes()} deletes the remotes that match the specified pattern. \code{$clear_remotes()} deletes all remotes. } \section{Built}{ The \sQuote{Built} field is used in binary packages to store information about when and how a binary package was built. \code{$get_built()} returns the built information as a list with fields \sQuote{R}, \sQuote{Platform}, \sQuote{Date}, \sQuote{OStype}. It throws an error if the package does not have a \sQuote{Built} field. } \section{Encodings}{ When creating a `description` object, `desc` observes the `Encoding` field, if present, and uses the specified encoding to parse the file. Internally, it converts all fields to UTF-8. When writing a `description` object to a file, `desc` uses the `Encoding` field (if present), and converts all fields to the specified encoding. We suggest that whenever you need to use non-ASCII characters in your package, you use the UTF-8 encoding, for maximum portability. } \examples{ ## Create a template desc <- description$new("!new") desc ## Read a file desc2 <- description$new(file = system.file("DESCRIPTION", package = "desc")) desc2 ## Remove a field desc2$del("LazyData") ## Add another one desc2$set(VignetteBuilder = "knitr") desc2$get("VignetteBuilder") desc2 } \keyword{datasets} desc/man/desc_get_maintainer.Rd0000644000176200001440000000154113272145436016226 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_maintainer} \alias{desc_get_maintainer} \title{Query the package maintainer in DESCRIPTION} \usage{ desc_get_maintainer(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ A character scalar. } \description{ Either from the \sQuote{Maintainer} or the \sQuote{Authors@R} field. } \seealso{ Other Authors@R: \code{\link{desc_add_author}}, \code{\link{desc_add_me}}, \code{\link{desc_add_role}}, \code{\link{desc_change_maintainer}}, \code{\link{desc_del_author}}, \code{\link{desc_del_role}}, \code{\link{desc_get_authors}}, \code{\link{desc_get_author}}, \code{\link{desc_set_authors}} } \concept{Authors@R} desc/man/check_field.Rd0000644000176200001440000000112413140567212014451 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/syntax_checks.R \name{check_field} \alias{check_field} \title{Syntactical check of a DESCRIPTION field} \usage{ check_field(x, warn = FALSE, ...) } \arguments{ \item{x}{The field.} \item{warn}{Whether to generate a warning if the syntax check fails.} \item{...}{Additional arguments, they might be used in the future.} } \value{ \code{TRUE} if the field is syntactically correct, otherwise a character vector, containing one or multiple error messages. } \description{ Syntactical check of a DESCRIPTION field } desc/man/desc_reformat_fields.Rd0000644000176200001440000000113413272145436016403 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_reformat_fields} \alias{desc_reformat_fields} \title{Reformat fields in a DESCRIPTION file} \usage{ desc_reformat_fields(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \description{ Reformat the fields in DESCRIPTION in a standard way. } \seealso{ Other repair functions: \code{\link{desc_normalize}}, \code{\link{desc_reorder_fields}} } \concept{repair functions} desc/man/desc_add_role.Rd0000644000176200001440000000266213272145436015016 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_add_role} \alias{desc_add_role} \title{Add a role to one or more authors in Authors@R, in DESCRIPTION} \usage{ desc_add_role(role, given = NULL, family = NULL, email = NULL, comment = NULL, file = ".", normalize = FALSE) } \arguments{ \item{role}{Role to add.} \item{given}{Given name to filter on. Regular expression.} \item{family}{Family name to filter on. Regular expression.} \item{email}{Email address to filter on. Regular expression.} \item{comment}{Comment field to filter on. Regular expression.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ The author(s) can be specified by a combination of the \code{given}, \code{family}, \code{email} and \code{comment} fields. If multiple filters are specified, then all must match to identify the author(s). } \seealso{ Other Authors@R: \code{\link{desc_add_author}}, \code{\link{desc_add_me}}, \code{\link{desc_change_maintainer}}, \code{\link{desc_del_author}}, \code{\link{desc_del_role}}, \code{\link{desc_get_authors}}, \code{\link{desc_get_author}}, \code{\link{desc_get_maintainer}}, \code{\link{desc_set_authors}} } \concept{Authors@R} desc/man/desc_has_dep.Rd0000644000176200001440000000137113272145436014644 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_has_dep} \alias{desc_has_dep} \title{Check for a dependency} \usage{ desc_has_dep(package, type = c("any", desc::dep_types), file = ".") } \arguments{ \item{package}{The package name.} \item{type}{A dependency type or \sQuote{any}.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ A logical scalar. } \description{ Check for a dependency } \seealso{ Other dependencies: \code{\link{desc_del_deps}}, \code{\link{desc_del_dep}}, \code{\link{desc_get_deps}}, \code{\link{desc_set_deps}}, \code{\link{desc_set_dep}} } \concept{dependencies} desc/man/desc_get_deps.Rd0000644000176200001440000000150313272145436015030 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_deps} \alias{desc_get_deps} \title{List all package dependencies from a DESCRIPTION file} \usage{ desc_get_deps(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ Data frame with columns: \code{type} (dependency type), \code{package}, and \code{version}. For non-versioned dependencies \code{version} is \code{*}. } \description{ List all package dependencies from a DESCRIPTION file } \seealso{ Other dependencies: \code{\link{desc_del_deps}}, \code{\link{desc_del_dep}}, \code{\link{desc_has_dep}}, \code{\link{desc_set_deps}}, \code{\link{desc_set_dep}} } \concept{dependencies} desc/man/desc_get_author.Rd0000644000176200001440000000165713272145436015411 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_author} \alias{desc_get_author} \title{Query authors by role in Authors@R, in DESCRIPTION} \usage{ desc_get_author(role = "cre", file = ".") } \arguments{ \item{role}{Role to query. Defaults to the package maintainer.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ A \code{\link[utils]{person}} object. } \description{ Query authors by role in Authors@R, in DESCRIPTION } \seealso{ Other Authors@R: \code{\link{desc_add_author}}, \code{\link{desc_add_me}}, \code{\link{desc_add_role}}, \code{\link{desc_change_maintainer}}, \code{\link{desc_del_author}}, \code{\link{desc_del_role}}, \code{\link{desc_get_authors}}, \code{\link{desc_get_maintainer}}, \code{\link{desc_set_authors}} } \concept{Authors@R} desc/man/desc_del_deps.Rd0000644000176200001440000000141113272145436015013 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_del_deps} \alias{desc_del_deps} \title{Remove all dependencies from DESCRIPTION} \usage{ desc_del_deps(file = ".", normalize = FALSE) } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Remove all dependencies from DESCRIPTION } \seealso{ Other dependencies: \code{\link{desc_del_dep}}, \code{\link{desc_get_deps}}, \code{\link{desc_has_dep}}, \code{\link{desc_set_deps}}, \code{\link{desc_set_dep}} } \concept{dependencies} desc/man/desc_del_from_collate.Rd0000644000176200001440000000174013272145436016533 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_del_from_collate} \alias{desc_del_from_collate} \title{Remove files from the Collate field.} \usage{ desc_del_from_collate(files, which = c("all", "main", "windows", "unix"), file = ".", normalize = FALSE) } \arguments{ \item{files}{Files to remove from the Collate field.} \item{which}{Which collate field to use. Collate fields can be operating system type specific.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Remove files from the Collate field. } \seealso{ Other Collate field: \code{\link{desc_add_to_collate}}, \code{\link{desc_del_collate}}, \code{\link{desc_get_collate}}, \code{\link{desc_set_collate}} } \concept{Collate field} desc/man/desc_get_urls.Rd0000644000176200001440000000104313140567212015053 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_urls} \alias{desc_get_urls} \title{Query the URL field in DESCRIPTION} \usage{ desc_get_urls(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ A character vectors or URLs. A length zero vector is returned if there is no URL field in the package. } \description{ Query the URL field in DESCRIPTION } desc/man/desc_reorder_fields.Rd0000644000176200001440000000113013272145436016222 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_reorder_fields} \alias{desc_reorder_fields} \title{Reorder fields in a DESCRIPTION file} \usage{ desc_reorder_fields(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \description{ Reorder the fields in DESCRIPTION in a standard way. } \seealso{ Other repair functions: \code{\link{desc_normalize}}, \code{\link{desc_reformat_fields}} } \concept{repair functions} desc/man/desc_set_authors.Rd0000644000176200001440000000176413272145436015607 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_set_authors} \alias{desc_set_authors} \title{Set authors in Authors@R, in DESCRIPTION} \usage{ desc_set_authors(authors, file = ".", normalize = FALSE) } \arguments{ \item{authors}{Authors, to set, a \code{\link[utils]{person}} object.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Set authors in Authors@R, in DESCRIPTION } \seealso{ Other Authors@R: \code{\link{desc_add_author}}, \code{\link{desc_add_me}}, \code{\link{desc_add_role}}, \code{\link{desc_change_maintainer}}, \code{\link{desc_del_author}}, \code{\link{desc_del_role}}, \code{\link{desc_get_authors}}, \code{\link{desc_get_author}}, \code{\link{desc_get_maintainer}} } \concept{Authors@R} desc/man/desc_has_fields.Rd0000644000176200001440000000135613272145436015345 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_has_fields} \alias{desc_has_fields} \title{Check if some fields are present in a DESCRIPTION file} \usage{ desc_has_fields(keys, file = ".") } \arguments{ \item{keys}{Character vector of keys to check.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ Logical vector. } \description{ Check if some fields are present in a DESCRIPTION file } \seealso{ Other simple queries: \code{\link{desc_del}}, \code{\link{desc_fields}}, \code{\link{desc_get_field}}, \code{\link{desc_get}}, \code{\link{desc_set}} } \concept{simple queries} desc/man/desc.Rd0000644000176200001440000000272213140567212013154 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/description.R \name{desc} \alias{desc} \title{Read a DESCRIPTION file} \usage{ desc(cmd = NULL, file = NULL, text = NULL, package = NULL) } \arguments{ \item{cmd}{A command to create a description from scratch. Currently only \code{"!new"} is implemented. If it does not start with an exclamation mark, it will be interpreted as the \sQuote{file} argument.} \item{file}{Name of the \code{DESCRIPTION} file to load. If all of \sQuote{cmd}, \sQuote{file} and \sQuote{text} are \code{NULL} (the default), then the \code{DESCRIPTION} file in the current working directory is used. The file can also be an R package (source, or binary), in which case the DESCRIPTION file is extracted from it, but note that in this case \code{$write()} cannot write the file back in the package archive.} \item{text}{A character scalar containing the full DESCRIPTION. Character vectors are collapsed into a character scalar, with newline as the separator.} \item{package}{If not NULL, then the name of an installed package and the DESCRIPTION file of this package will be loaded.} } \description{ This is a convenience wrapper for \code{description$new()}. Very often you want to read an existing \code{DESCRIPTION} file, and to do this you can just supply the path to the file or its directory to \code{desc()}. } \examples{ desc(package = "desc") DESCRIPTION <- system.file("DESCRIPTION", package = "desc") desc(DESCRIPTION) } desc/man/desc_get_authors.Rd0000644000176200001440000000153213272145436015564 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_authors} \alias{desc_get_authors} \title{Query all authors in Authors@R, in DESCRIPTION} \usage{ desc_get_authors(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ A \code{\link[utils]{person}} object. } \description{ Query all authors in Authors@R, in DESCRIPTION } \seealso{ Other Authors@R: \code{\link{desc_add_author}}, \code{\link{desc_add_me}}, \code{\link{desc_add_role}}, \code{\link{desc_change_maintainer}}, \code{\link{desc_del_author}}, \code{\link{desc_del_role}}, \code{\link{desc_get_author}}, \code{\link{desc_get_maintainer}}, \code{\link{desc_set_authors}} } \concept{Authors@R} desc/man/desc_get_field.Rd0000644000176200001440000000226013272065542015160 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_field} \alias{desc_get_field} \alias{desc_get_or_fail} \title{Get a single field from a DESCRIPTION file, fail if not found} \usage{ desc_get_field(key, default = stop("Field '", key, "' not found"), trim_ws = TRUE, file = ".") desc_get_or_fail(keys, file = ".") } \arguments{ \item{key}{The field to query.} \item{default}{Value to return if \code{key} is not found. By default it throws an error.} \item{trim_ws}{Whether to trim leading and trailing whitespace from the value. Defaults to \code{TRUE}.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{keys}{Character vector of fields to get.} } \value{ Character string, the value of \code{key}, or \code{default} if \code{key} is not found and \code{default} is specified. } \description{ Get a single field from a DESCRIPTION file, fail if not found } \seealso{ Other simple queries: \code{\link{desc_del}}, \code{\link{desc_fields}}, \code{\link{desc_get}}, \code{\link{desc_has_fields}}, \code{\link{desc_set}} } desc/man/desc_set_version.Rd0000644000176200001440000000153413272145436015602 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_set_version} \alias{desc_set_version} \title{Set the package version in DESCRIPTION} \usage{ desc_set_version(version, file = ".", normalize = FALSE) } \arguments{ \item{version}{A string or a \code{\link[base]{package_version}} object.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Both \code{$set_version()} and \code{$bump_version()} use dots to separate the version number components. } \seealso{ Other version numbers: \code{\link{desc_bump_version}}, \code{\link{desc_get_version}} } \concept{version numbers} desc/man/desc_add_to_collate.Rd0000644000176200001440000000201313272145436016170 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_add_to_collate} \alias{desc_add_to_collate} \title{Add one or more files to the Collate field, in DESCRIPTION} \usage{ desc_add_to_collate(files, which = c("default", "all", "main", "windows", "unix"), file = ".", normalize = FALSE) } \arguments{ \item{files}{Character vector, files to add.} \item{which}{Which collate field to use. Collate fields can be operating system type specific.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Add one or more files to the Collate field, in DESCRIPTION } \seealso{ Other Collate field: \code{\link{desc_del_collate}}, \code{\link{desc_del_from_collate}}, \code{\link{desc_get_collate}}, \code{\link{desc_set_collate}} } \concept{Collate field} desc/man/desc_get_collate.Rd0000644000176200001440000000147013272145436015523 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_collate} \alias{desc_get_collate} \title{Query the Collate field in DESCRIPTION} \usage{ desc_get_collate(which = c("main", "windows", "unix"), file = ".") } \arguments{ \item{which}{Which collate field to use. Collate fields can be operating system type specific.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ Character vector of file names. } \description{ Query the Collate field in DESCRIPTION } \seealso{ Other Collate field: \code{\link{desc_add_to_collate}}, \code{\link{desc_del_collate}}, \code{\link{desc_del_from_collate}}, \code{\link{desc_set_collate}} } \concept{Collate field} desc/man/desc_set.Rd0000644000176200001440000000200513272145436014027 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_set} \alias{desc_set} \title{Set one or more fields in a DESCRIPTION file} \usage{ desc_set(..., file = ".", normalize = FALSE) } \arguments{ \item{...}{Values to set, see details below.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Set one or more fields in a DESCRIPTION file } \details{ \code{desc_set} supports two forms, the first is two unnamed arguments: the key and its value to set. The second form requires named arguments: names are used as keys and values as values to set. } \seealso{ Other simple queries: \code{\link{desc_del}}, \code{\link{desc_fields}}, \code{\link{desc_get_field}}, \code{\link{desc_get}}, \code{\link{desc_has_fields}} } \concept{simple queries} desc/man/desc_clear_remotes.Rd0000644000176200001440000000114613140567212016057 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_clear_remotes} \alias{desc_clear_remotes} \title{Remove all locations from the Remotes field of DESCRIPTION} \usage{ desc_clear_remotes(file = ".", normalize = FALSE) } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ This simply means that the field is deleted. } desc/man/desc_del_urls.Rd0000644000176200001440000000130313140567212015037 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_del_urls} \alias{desc_del_urls} \title{Delete URLs from the URL field in DESCRIPTION} \usage{ desc_del_urls(pattern, file = ".", normalize = FALSE) } \arguments{ \item{pattern}{Perl-compatible regular expression, all URLs matching this expression will be deleted.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ All URLs matching the specified pattern are deleted. } desc/man/desc_set_dep.Rd0000644000176200001440000000171613272145436014667 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_set_dep} \alias{desc_set_dep} \title{Add a package dependency to a DESCRIPTION file} \usage{ desc_set_dep(package, type = desc::dep_types, version = "*", file = ".", normalize = FALSE) } \arguments{ \item{package}{Package to depend on.} \item{type}{Dependency type.} \item{version}{Version to depend on, for versioned dependencies.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Add a package dependency to a DESCRIPTION file } \seealso{ Other dependencies: \code{\link{desc_del_deps}}, \code{\link{desc_del_dep}}, \code{\link{desc_get_deps}}, \code{\link{desc_has_dep}}, \code{\link{desc_set_deps}} } \concept{dependencies} desc/man/desc_normalize.Rd0000644000176200001440000000112313272145436015234 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_normalize} \alias{desc_normalize} \title{Normalize a DESCRIPTION file} \usage{ desc_normalize(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \description{ Re-formats and re-orders fields in DESCRIPTION in a standard way. } \seealso{ Other repair functions: \code{\link{desc_reformat_fields}}, \code{\link{desc_reorder_fields}} } \concept{repair functions} desc/man/desc_get_version.Rd0000644000176200001440000000127113272145436015564 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_version} \alias{desc_get_version} \title{Query the package version in DESCRIPTION} \usage{ desc_get_version(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ A \code{\link[base]{package_version}} object. } \description{ If the file has no \code{Version} field, or it is an invalid version string, then it throws an error. } \seealso{ Other version numbers: \code{\link{desc_bump_version}}, \code{\link{desc_set_version}} } \concept{version numbers} desc/man/desc_del_remotes.Rd0000644000176200001440000000133713140567212015537 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_del_remotes} \alias{desc_del_remotes} \title{Delete locations from the Remotes field in DESCRIPTION} \usage{ desc_del_remotes(pattern, file = ".", normalize = FALSE) } \arguments{ \item{pattern}{Perl-compatible regular expression, all locations matching this expression will be deleted.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ All locations matching the specified pattern are deleted. } desc/man/desc_change_maintainer.Rd0000644000176200001440000000225713272145436016701 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_change_maintainer} \alias{desc_change_maintainer} \title{Change maintainer of the package, in DESCRIPTION} \usage{ desc_change_maintainer(given = NULL, family = NULL, email = NULL, comment = NULL, file = ".", normalize = FALSE) } \arguments{ \item{given}{Given name.} \item{family}{Family name.} \item{email}{Email address.} \item{comment}{Comment.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Only works with the Authors@R field. } \details{ The current maintainer is kept if they have at least another role. } \seealso{ Other Authors@R: \code{\link{desc_add_author}}, \code{\link{desc_add_me}}, \code{\link{desc_add_role}}, \code{\link{desc_del_author}}, \code{\link{desc_del_role}}, \code{\link{desc_get_authors}}, \code{\link{desc_get_author}}, \code{\link{desc_get_maintainer}}, \code{\link{desc_set_authors}} } \concept{Authors@R} desc/man/cran_valid_fields.Rd0000644000176200001440000000104113272145436015665 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/constants.R \docType{data} \name{cran_valid_fields} \alias{cran_valid_fields} \title{A list of DESCRIPTION fields that are valid according to the CRAN checks} \format{An object of class \code{character} of length 125.} \usage{ cran_valid_fields } \description{ A list of DESCRIPTION fields that are valid according to the CRAN checks } \seealso{ Other field types: \code{\link{cran_ascii_fields}}, \code{\link{dep_types}} } \concept{field types} \keyword{datasets} desc/man/desc_get_built.Rd0000644000176200001440000000130213272145436015211 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_built} \alias{desc_get_built} \title{Query the built field in DESCRIPTION} \usage{ desc_get_built(file = ".", normalize = FALSE) } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \value{ A list with fields \sQuote{R}, \sQuote{Platform}, \sQuote{Date}, \sQuote{OStype}. } \description{ If the file has no \code{Built} field then it throws an error. } \concept{built} desc/man/desc_clear_urls.Rd0000644000176200001440000000113113140567212015360 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_clear_urls} \alias{desc_clear_urls} \title{Remove all URLs from the URL field of DESCRIPTION} \usage{ desc_clear_urls(file = ".", normalize = FALSE) } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Remove all URLs from the URL field of DESCRIPTION } desc/man/desc_fields.Rd0000644000176200001440000000123113272145436014502 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_fields} \alias{desc_fields} \title{List all fields in a DESCRIPTION file} \usage{ desc_fields(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ Character vector of fields. } \description{ List all fields in a DESCRIPTION file } \seealso{ Other simple queries: \code{\link{desc_del}}, \code{\link{desc_get_field}}, \code{\link{desc_get}}, \code{\link{desc_has_fields}}, \code{\link{desc_set}} } \concept{simple queries} desc/man/desc_add_remotes.Rd0000644000176200001440000000157113140567212015523 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_add_remotes} \alias{desc_add_remotes} \title{Add locations in the Remotes field in DESCRIPTION} \usage{ desc_add_remotes(remotes, file = ".", normalize = FALSE) } \arguments{ \item{remotes}{Character vector of remote locations to add. Duplicate locations are eliminated. Note that existing locations are not updated, so if you want to \emph{change} a remote location of a package, you need to delete the old location first and then add the new one.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Add locations in the Remotes field in DESCRIPTION } desc/man/desc_to_latex.Rd0000644000176200001440000000071013140567212015046 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_to_latex} \alias{desc_to_latex} \title{Converts a DESCRIPTION file to LaTeX} \usage{ desc_to_latex(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \description{ Returns the contents of the DESCRIPTION in LaTeX format. } desc/man/desc_del_collate.Rd0000644000176200001440000000164213272145436015511 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_del_collate} \alias{desc_del_collate} \title{Delete the Collate field from DESCRIPTION} \usage{ desc_del_collate(which = c("all", "main", "windows", "unix"), file = ".", normalize = FALSE) } \arguments{ \item{which}{Which collate field to use. Collate fields can be operating system type specific.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Delete the Collate field from DESCRIPTION } \seealso{ Other Collate field: \code{\link{desc_add_to_collate}}, \code{\link{desc_del_from_collate}}, \code{\link{desc_get_collate}}, \code{\link{desc_set_collate}} } \concept{Collate field} desc/man/desc_add_urls.Rd0000644000176200001440000000122513140567212015026 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_add_urls} \alias{desc_add_urls} \title{Add URLs to the URL field in DESCRIPTION} \usage{ desc_add_urls(urls, file = ".", normalize = FALSE) } \arguments{ \item{urls}{Character vector of URLs to add. Duplicate URLs are eliminated.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Add URLs to the URL field in DESCRIPTION } desc/man/desc_print.Rd0000644000176200001440000000071713140567212014372 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_print} \alias{desc_print} \title{Print the contents of a DESCRIPTION file to the screen} \usage{ desc_print(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \description{ Print the contents of a DESCRIPTION file to the screen } desc/man/desc_get_remotes.Rd0000644000176200001440000000114413140567212015546 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_remotes} \alias{desc_get_remotes} \title{List the locations in the Remotes field in DESCRIPTION} \usage{ desc_get_remotes(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \value{ A character vectors or remote locations. A length zero vector is returned if there is no Remotes field in the package. } \description{ List the locations in the Remotes field in DESCRIPTION } desc/man/desc_set_deps.Rd0000644000176200001440000000157613272145436015056 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_set_deps} \alias{desc_set_deps} \title{Set all package dependencies in DESCRIPTION} \usage{ desc_set_deps(deps, file = ".", normalize = FALSE) } \arguments{ \item{deps}{Package dependency data frame, in the same format returned by \code{\link{desc_get_deps}}.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Set all package dependencies in DESCRIPTION } \seealso{ Other dependencies: \code{\link{desc_del_deps}}, \code{\link{desc_del_dep}}, \code{\link{desc_get_deps}}, \code{\link{desc_has_dep}}, \code{\link{desc_set_dep}} } \concept{dependencies} desc/man/desc_set_urls.Rd0000644000176200001440000000125513140567212015074 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_set_urls} \alias{desc_set_urls} \title{Set the URL field in DESCRIPTION} \usage{ desc_set_urls(urls, file = ".", normalize = FALSE) } \arguments{ \item{urls}{A character vector of urls to set.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ The specified urls replace the current ones. The URL field is created if it does not exist currently. } desc/man/desc_bump_version.Rd0000644000176200001440000000332113272145436015746 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_bump_version} \alias{desc_bump_version} \title{Increase the version number in DESCRIPTION} \usage{ desc_bump_version(which, file = ".", normalize = FALSE) } \arguments{ \item{which}{Which component to increase. See details below.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ The \code{which} parameter specifies which component to increase. It can be a string referring to a component: \sQuote{major}, \sQuote{minor}, \sQuote{patch} or \sQuote{dev}, or an integer scalar, for the latter components are counted from one, and the beginning. I.e. component one is equivalent to \sQuote{major}. } \details{ If a component is bumped, then the ones after it are zeroed out. Trailing zero components are omitted from the new version number, but if the old version number had at least two or three components, then the one will also have two or three. The bumping of the \sQuote{dev} version (the fourth component) is special: if the original version number had less than four components, and the \sQuote{dev} version is bumped, then it is set to \code{9000} instead of \code{1}. This is a convention often used by R developers, it was originally invented by Winston Chang. Both \code{$set_version()} and \code{$bump_version()} use dots to separate the version number components. } \seealso{ Other version numbers: \code{\link{desc_get_version}}, \code{\link{desc_set_version}} } \concept{version numbers} desc/man/desc_del.Rd0000644000176200001440000000145213272145436014005 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_del} \alias{desc_del} \title{Remove fields from a DESCRIPTION file} \usage{ desc_del(keys, file = ".", normalize = FALSE) } \arguments{ \item{keys}{Character vector of keys to remove.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Remove fields from a DESCRIPTION file } \seealso{ Other simple queries: \code{\link{desc_fields}}, \code{\link{desc_get_field}}, \code{\link{desc_get}}, \code{\link{desc_has_fields}}, \code{\link{desc_set}} } \concept{simple queries} desc/man/desc_add_me.Rd0000644000176200001440000000203713272145436014452 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_add_me} \alias{desc_add_me} \title{Add the current user as an author to DESCRIPTION} \usage{ desc_add_me(role = "ctb", comment = NULL, file = ".", normalize = FALSE) } \arguments{ \item{role}{Role to set for the user, defaults to contributor.} \item{comment}{Comment, empty by default.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Uses the Authors@R field. } \seealso{ Other Authors@R: \code{\link{desc_add_author}}, \code{\link{desc_add_role}}, \code{\link{desc_change_maintainer}}, \code{\link{desc_del_author}}, \code{\link{desc_del_role}}, \code{\link{desc_get_authors}}, \code{\link{desc_get_author}}, \code{\link{desc_get_maintainer}}, \code{\link{desc_set_authors}} } \concept{Authors@R} desc/man/desc_set_remotes.Rd0000644000176200001440000000132513140567212015563 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_set_remotes} \alias{desc_set_remotes} \title{Set the Remotes field in DESCRIPTION} \usage{ desc_set_remotes(remotes, file = ".", normalize = FALSE) } \arguments{ \item{remotes}{A character vector of remote locations to set.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ The specified locations replace the current ones. The Remotes field is created if it does not exist currently. } desc/man/desc_del_author.Rd0000644000176200001440000000306513272145436015371 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_del_author} \alias{desc_del_author} \title{Remove one or more authors from DESCRIPTION.} \usage{ desc_del_author(given = NULL, family = NULL, email = NULL, role = NULL, comment = NULL, file = ".", normalize = FALSE) } \arguments{ \item{given}{Given name to filter on. Regular expression.} \item{family}{Family name to filter on. Regular expression.} \item{email}{Email address to filter on. Regular expression.} \item{role}{Role to filter on. Regular expression.} \item{comment}{Comment field to filter on. Regular expression.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ It uses the Authors@R field. The author(s) to be removed can be specified via any field(s). All authors matching all specifications will be removed. E.g. if only \code{given = "Joe"} is supplied, then all authors whole given name matches \code{Joe} will be removed. The specifications can be (PCRE) regular expressions. } \seealso{ Other Authors@R: \code{\link{desc_add_author}}, \code{\link{desc_add_me}}, \code{\link{desc_add_role}}, \code{\link{desc_change_maintainer}}, \code{\link{desc_del_role}}, \code{\link{desc_get_authors}}, \code{\link{desc_get_author}}, \code{\link{desc_get_maintainer}}, \code{\link{desc_set_authors}} } \concept{Authors@R} desc/man/cran_ascii_fields.Rd0000644000176200001440000000103413272145436015660 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/constants.R \docType{data} \name{cran_ascii_fields} \alias{cran_ascii_fields} \title{The DESCRIPTION fields that are supposed to be in plain ASCII encoding} \format{An object of class \code{character} of length 16.} \usage{ cran_ascii_fields } \description{ The DESCRIPTION fields that are supposed to be in plain ASCII encoding } \seealso{ Other field types: \code{\link{cran_valid_fields}}, \code{\link{dep_types}} } \concept{field types} \keyword{datasets} desc/man/desc_validate.Rd0000644000176200001440000000065413140567212015027 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_validate} \alias{desc_validate} \title{Validate a DESCRIPTION file} \usage{ desc_validate(file = ".") } \arguments{ \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} } \description{ This function is not implemented yet. } desc/man/desc_del_role.Rd0000644000176200001440000000263713272145436015034 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_del_role} \alias{desc_del_role} \title{Delete a role of an author, in DESCRIPTION} \usage{ desc_del_role(role, given = NULL, family = NULL, email = NULL, comment = NULL, file = ".", normalize = FALSE) } \arguments{ \item{role}{Role to remove.} \item{given}{Given name to filter on. Regular expression.} \item{family}{Family name to filter on. Regular expression.} \item{email}{Email address to filter on. Regular expression.} \item{comment}{Comment field to filter on. Regular expression.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ The author(s) can be specified by a combination of the \code{given}, \code{family}, \code{email} and \code{comment} fields. If multiple filters are specified, then all must match to identify the author(s). } \seealso{ Other Authors@R: \code{\link{desc_add_author}}, \code{\link{desc_add_me}}, \code{\link{desc_add_role}}, \code{\link{desc_change_maintainer}}, \code{\link{desc_del_author}}, \code{\link{desc_get_authors}}, \code{\link{desc_get_author}}, \code{\link{desc_get_maintainer}}, \code{\link{desc_set_authors}} } \concept{Authors@R} desc/man/desc_set_collate.Rd0000644000176200001440000000172413272145436015541 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_set_collate} \alias{desc_set_collate} \title{Set the Collate field in DESCRIPTION} \usage{ desc_set_collate(files, which = c("main", "windows", "unix"), file = ".", normalize = FALSE) } \arguments{ \item{files}{Collate field to set, as a character vector.} \item{which}{Which collate field to use. Collate fields can be operating system type specific.} \item{file}{DESCRIPTION file to use. By default the DESCRIPTION file of the current package (i.e. the package the working directory is part of) is used.} \item{normalize}{Whether to normalize the write when writing back the result. See \code{\link{desc_normalize}}.} } \description{ Set the Collate field in DESCRIPTION } \seealso{ Other Collate field: \code{\link{desc_add_to_collate}}, \code{\link{desc_del_collate}}, \code{\link{desc_del_from_collate}}, \code{\link{desc_get_collate}} } \concept{Collate field} desc/man/check_encoding.Rd0000644000176200001440000000120713272047277015170 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/encoding.R \name{check_encoding} \alias{check_encoding} \title{Check encoding of new or existing fields} \usage{ check_encoding(self, private, new_fields) } \arguments{ \item{self}{Object.} \item{private}{Private env.} \item{new_fields}{New fields, or \code{NULL} to check existing fields.} } \value{ Object, invisibly. } \description{ If \code{new_fields} is \code{NULL}, then the existing fields are checked. Otherwise \code{new_fields} are checked. } \details{ Warnings are given for non-ascii fields, if the \code{Encoding} field is not set. } \keyword{internal} desc/LICENSE0000644000176200001440000000007613272041524012200 0ustar liggesusersYEAR: 2015-2018 COPYRIGHT HOLDER: Gábor Csárdi, RStudio Inc