desc/0000755000176200001440000000000013140637671011200 5ustar liggesusersdesc/inst/0000755000176200001440000000000013140567212012146 5ustar liggesusersdesc/inst/README.Rmd0000644000176200001440000000755713140567212013565 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). desc/inst/NEWS.md0000644000176200001440000000077613140567212013256 0ustar liggesusers # 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.md0000644000176200001440000001714313140567212013433 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). 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/0000755000176200001440000000000013140567212012333 5ustar liggesusersdesc/tests/testthat.R0000644000176200001440000000006413140567212014316 0ustar liggesuserslibrary(testthat) library(desc) test_check("desc") desc/tests/testthat/0000755000176200001440000000000013140637671014202 5ustar liggesusersdesc/tests/testthat/test-encoding.R0000644000176200001440000000161513140567212017064 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") }) 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-desc.R0000644000176200001440000000016513140567212016213 0ustar liggesusers context("desc") test_that("desc wrapper works", { expect_equal( desc("D2"), description$new("D2") ) }) desc/tests/testthat/fixtures/0000755000176200001440000000000013140567212016044 5ustar liggesusersdesc/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.gz0000644000176200001440000000051513140567212020471 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.R0000644000176200001440000000150213140567212016256 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_)) }) desc/tests/testthat/test-to_latex.R0000644000176200001440000000122313140567212017110 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 = TRUE) }) 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.R0000644000176200001440000000072213140567212016426 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()) }) 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.R0000644000176200001440000001310513140567212016500 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_null(desc_get_deps(file = d)) }) 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", "Encoding", "Remotes", "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.R0000644000176200001440000000706713140567212016240 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_null(deps) }) 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.tex0000644000176200001440000000126413140567212020077 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.R0000644000176200001440000001163713140567212016770 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ábor Csárdi " ) 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/files/0000755000176200001440000000000013140570270015273 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.R0000644000176200001440000000430013140567212016745 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ábor Csárdi")) expect_equal(desc$get("Imports"), c(Imports = "\n R6")) }) 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ábor Csárdi")) 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.R0000644000176200001440000000172213140567212016753 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_)) }) 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/D40000644000176200001440000000053413140567212014367 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 desc/tests/testthat/test-archives.R0000644000176200001440000000465713140567212017113 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" )) 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_error( d4 <- description$new(file.path("fixtures", "notpkg_1.0.tar.gz")), "Cannot extract DESCRIPTION" ) }) desc/tests/testthat/test-read.R0000644000176200001440000000154313140567212016211 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ábor Csárdi")) 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" ) }) desc/tests/testthat/test-str.R0000644000176200001440000000350713140567212016110 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), "Authors@R (parsed): * Hadley Wickham [aut, cre, cph] * Peter Danenberg [aut, cph] * Manuel Eugster [aut, cph] * RStudio [cph]", fixed = TRUE ) }) desc/NAMESPACE0000644000176200001440000000612513140567212012414 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,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(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_collate) export(desc_get_deps) 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.md0000644000176200001440000000077613140567212012301 0ustar liggesusers # 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/0000755000176200001440000000000013140567212011372 5ustar liggesusersdesc/R/classes.R0000644000176200001440000000402213140567212013150 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"), 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"), PackageList = c("VignetteBuilder", "RdMacros"), 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.R0000644000176200001440000000472513140567212012665 0ustar liggesusers 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") } 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.R0000644000176200001440000000226513140567212013200 0ustar liggesusers parse_remotes <- function(remotes) { str_trim(strsplit(remotes, "\\s*,\\s*", perl = TRUE)[[1]]) } deparse_remotes <- function(remotes) { 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.R0000644000176200001440000000551713140567212012460 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) } 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)) do.call(rbind, 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.R0000644000176200001440000000165213140567212013307 0ustar liggesusers #' Check encoding of new or existing fields #' #' If \code{new_fields} is \code{NULL}, then the existing #' fields are checked. Otherwised \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.R0000644000176200001440000000676713140567212013727 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(deparse(call$x), " 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 ", deparse(call$x), " 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/description.R0000644000176200001440000006770013140567212014052 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_or_fail} is similar to \code{$get}, but throws an error #' if a field does not exist, except of silently returning #' \code{NA_character}. #' #' The complete API reference: #' \preformatted{ description$get(keys) #' description$get_or_fail(keys) #' description$set(...) #' description$fields() #' description$has_fields(keys) #' description$del(keys)} #' \describe{ #' \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 #' reformats 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 compulsary: #' \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, udpate 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. #' #' @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_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) ), private = list( data = NULL, path = "DESCRIPTION", 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) ## 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] changed <- mat[, names(private$notws)] != private$notws if (any(changed)) private$notws <- private$notws[! changed] postprocess_trailing_ws(tmp, names(private$notws)) if (file.exists(file) && is_dir(file)) file <- find_description(file) writeLines(readLines(tmp), file) 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 <- unlist(res) names(res) <- keys res } 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, 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.R0000644000176200001440000000606413140567212012333 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, ": ", 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" ) 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) { 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 #' @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.R0000644000176200001440000002265213140567212014372 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 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 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 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]?$", x)) } chks( x = x, warn = warn, chk("must be a list of IETF language codes defined by 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.R0000644000176200001440000000200213140567212012474 0ustar liggesusers parse_urls <- function(urls) { str_trim(strsplit(urls, "[,\\s]+", perl = TRUE)[[1]]) } 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.R0000644000176200001440000000141413140567212012430 0ustar liggesusers ## TODO: handle empty files read_dcf <- function(file) { lines <- readLines(file) no_tws_fields <- sub( ":$", "", grep("^[^\\s]+:$", lines, perl = TRUE, value = TRUE) ) con <- textConnection(lines, local = TRUE) fields <- colnames(read.dcf(con)) close(con) 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 = ", ")) } 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.R0000644000176200001440000004050513140567212013475 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 fields from a DESCRIPTION file, fail if not found #' #' @inheritParams desc_get #' @return Character vector, values of the specified keys. #' Non-existing keys return \code{NA}. #' #' @family simple queries #' @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 #' #' Reformats and reorders 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") ## ------------------------------------------------------------------- # nocov end desc/R/package-archives.R0000644000176200001440000000270113140567212014712 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 get_description_from_package <- function(file) { uncompress <- if (is_zip_file(file)) unzip else untar package_name <- sub("_.*$", "", basename(file)) tmp <- tempfile() suppressWarnings(uncompress( file, files = paste(package_name, sep = "/", "DESCRIPTION"), exdir = tmp )) desc <- file.path(tmp, package_name, "DESCRIPTION") if (!file.exists(desc)) { stop("Cannot extract DESCRIPTION from ", sQuote(file)) } desc } desc/MD50000644000176200001440000001507513140637671011520 0ustar liggesusersb120a98a326be283dee5416f745a47c7 *DESCRIPTION e4c81207cdbd596c9e35a231e630e872 *LICENSE 4e254b99976e579a2587cecb34a7c229 *NAMESPACE 3056cc67c2902fb0032a72e11d495e3a *NEWS.md dc985b802fd20b6d0d31adaa5929cad5 *R/assertions.R babff9502088d0d0062c6cccbe86c3eb *R/authors-at-r.R e13f26e1ec730f2f133ba45efc8c4a60 *R/classes.R 39c3291961f1119871f8b3576aa06c4d *R/collate.R 418508ee6da0653620bfbf67f4dfdbd5 *R/constants.R 87c6a8c69ef7a464d62b9e9c974c1a51 *R/deps.R 6f867cf06289e8aec541b3065450b761 *R/description.R 1327877ac0ca3f0132fb959bddc8365d *R/encoding.R 8b53a4c108f2cba9e3b2684b30b00df0 *R/latex.R 4236fbc124e625d4d7e866783192696b *R/non-oo-api.R 50a6134f5a03ab1295ee9d941495eea2 *R/package-archives.R 80205733fbcc2dd463b4679f3ae8d53c *R/read.R fad76c098683791fd87bee78ca016611 *R/remotes.R fe84270cb5fa350ff53046022c7a86b4 *R/str.R 3167990c8ab9a520cf45e51f641eeaaf *R/syntax_checks.R 1903e0b416ba812c5767561fae410752 *R/urls.R c2be1854c16b3ef1c62766a30aa30033 *R/utils.R 7609c65315c4ccc461b4312b88e44e62 *R/validate.R 9b3b1554e0ec41655574a6ba78f8a84a *R/version.R 3ba0ce861688512cabe7cf512952e4cc *inst/DESCRIPTION dcee715ad05f22f9ea9015c7b9b4b0fc *inst/DESCRIPTION2 3056cc67c2902fb0032a72e11d495e3a *inst/NEWS.md a21b37eda742851762f4920ed9d32153 *inst/README.Rmd 0ea2e15de4e924d6e0caaa7c600df2d4 *inst/README.md dcb395e54a74f1a3e245107d3a7c462b *man/check_encoding.Rd 7e5ed2e9239d833fb6dfdb79cd33b4b4 *man/check_field.Rd 737f049bec71fdb4d033a71872687f62 *man/cran_ascii_fields.Rd 6fc600cbc6c101d70ecbbc3e369ed83d *man/cran_valid_fields.Rd a3a809fc89d20c8074092db7ceb538c3 *man/dep_types.Rd 5ed873c0a4c47152d098f34e31abb773 *man/desc.Rd 9c7ac53396b3f2026341a95d5805ff54 *man/desc_add_author.Rd 58582ba7155f961fdf5418ed8408b4eb *man/desc_add_me.Rd 71706994e9b0be7f75c8b2e7eacbeedf *man/desc_add_remotes.Rd 0cdf462feab0271295a3d43664127ac1 *man/desc_add_role.Rd 4f68385fb64eecaf7c97bb70cca2737a *man/desc_add_to_collate.Rd 891dc1dadafa3b454b0603d73e0d57aa *man/desc_add_urls.Rd 2d590497f4fb0c88aedcc7e4f8a15366 *man/desc_bump_version.Rd e31650ac99464245228bfa6175b1dffb *man/desc_change_maintainer.Rd dc77c76d09b96aa30d0cca6a86debe40 *man/desc_clear_remotes.Rd a96c15eb21a62d796f73254995f0f44f *man/desc_clear_urls.Rd ec6a33b1a1cb753eb4199646cf29bcc7 *man/desc_del.Rd a78490e3f52365b3708e401848a6dea6 *man/desc_del_author.Rd 8eb2495d08d694c333941485cd56d1df *man/desc_del_collate.Rd 940ad60e62289b82e5f1f7a95ff3ebab *man/desc_del_dep.Rd 3b837791e78755abace507762c86beea *man/desc_del_deps.Rd 699968fdca0ddf2637903f7f598731fa *man/desc_del_from_collate.Rd bb28faf1c729437fb533c3fc4232178a *man/desc_del_remotes.Rd 5013912f2ca8aec7812f5889cb70a77e *man/desc_del_role.Rd c5aeee74741c9a60a52b6a6af11f343d *man/desc_del_urls.Rd 5769c2c428dd3d6fad29c5f7a748791a *man/desc_fields.Rd dbf2da6905930f0179fc93c7a8de8d53 *man/desc_get.Rd a70a7f06d61b5a870ecca401e1b1a95a *man/desc_get_author.Rd 1aa1666b26ba947eef643803e7be8f98 *man/desc_get_authors.Rd b31f62168e3eee63c70685da79530cb5 *man/desc_get_collate.Rd 04e2d3e6056320f7db40f858a1b3337c *man/desc_get_deps.Rd e6831e6c45a6cd6822fdb7f521faf49f *man/desc_get_maintainer.Rd 9b2220cc3f2cb0f5bd413c8e933cd0ed *man/desc_get_or_fail.Rd f8a71db35581155e6a1aa702e197e06e *man/desc_get_remotes.Rd 191429364648ee2946274f88bac6e8af *man/desc_get_urls.Rd e7e8ca420bc568ac84e0eaa521e48056 *man/desc_get_version.Rd a37df7a1e5602b98fa9c24bd4473bb8e *man/desc_has_dep.Rd 142d818ce66c8f927f2c4d23e1de2a3d *man/desc_has_fields.Rd 0b99f8ff7b4eafcb3024c593d890ab66 *man/desc_normalize.Rd 6c1f784506911f67d26aa7357e9cac33 *man/desc_print.Rd c35d6dc412d5bb981990b6567136c1f0 *man/desc_reformat_fields.Rd 9f3d13eaf7964187601b3ec96ac9dd4d *man/desc_reorder_fields.Rd 7c8949e7d02fd9bfc55cf9a10632e277 *man/desc_set.Rd 1c8464488a7ad5d7615b9c7dc877fff2 *man/desc_set_authors.Rd ee00f9c46b96d2ba8ae106404055608d *man/desc_set_collate.Rd 3819e5b089cd5076328ba0b6b5902343 *man/desc_set_dep.Rd c4eb564530d2ad4cdc35b7120d8274ff *man/desc_set_deps.Rd 2eb5d8e5c2de3230a6f58355706a184b *man/desc_set_remotes.Rd f22cccff4053b69fb690a7e0f5dca57a *man/desc_set_urls.Rd 0e98b3e064e24ee4ff8462c107d38877 *man/desc_set_version.Rd 644b0b378ca68574140981e51075c4b9 *man/desc_to_latex.Rd 3796d76d4f7e600ff05a25dff40e9f9a *man/desc_validate.Rd cf7b13c7a12245c8775f0bc8965ca34a *man/description.Rd 17a96b3396f1857d99adece6077e1577 *tests/testthat.R be96b5143b1d6266291d4f09583b9cee *tests/testthat/D1 c7c30e1187575c55c4788e0a40d22196 *tests/testthat/D2 0c5171c23afb3abfc6e7fb9810b44ff6 *tests/testthat/D3 8e9f51d287512d940952ae45304d7019 *tests/testthat/D4 2c9323b51bd0b848494819c3ee05d1e7 *tests/testthat/D5 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 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 b7d43ebade5d8e25d0273284f39eb7b8 *tests/testthat/test-archives.R e1731b58f55950189d5fe2226ee3311e *tests/testthat/test-authors.R 04d167df04fa31c835f34400d66dc7eb *tests/testthat/test-checks.R bb3600ff906f59f20c74ad662ba470c2 *tests/testthat/test-collate.R 7f7769b4cdc0f3d15f849ee53f1e3d10 *tests/testthat/test-create.R b8839d6860a2035aec77b833504f5524 *tests/testthat/test-deps.R 91a2fffc2a8f29c7ffe5e3993bc9be82 *tests/testthat/test-desc.R 2e66935fe29cd96ff06b5ff2f36f6a56 *tests/testthat/test-encoding.R 0484cad7c85958a2841b2cd9846b6a90 *tests/testthat/test-idempotent.R e9d7def0ebabc6180dadd4d6185f1882 *tests/testthat/test-non-oo.R b050b433642dc8e1353063a3d4e6bc4f *tests/testthat/test-queries.R 23e640a4e35175373c2a876fa80067e6 *tests/testthat/test-read.R 5336a948fb80ed8c3088b3e8c927e723 *tests/testthat/test-remotes.R 09d6ed54453d8d642af2d07f0565a75f *tests/testthat/test-repair.R c2aee1218a3b5a642c96a95212fc31ee *tests/testthat/test-str.R 6a949f92ab8c27e5254f6fd7d7180ec6 *tests/testthat/test-to_latex.R 62fb74840dc93877d9a61ca6d68f4734 *tests/testthat/test-trailing-ws.R 01531bec9205016b2d41b01d820a96f3 *tests/testthat/test-urls.R 418c886aee25cdc0e088d2b1bbea79ec *tests/testthat/test-utils.R 0f287c1718c783216568c3f0aebd0ade *tests/testthat/test-validation.R bbfa92ac5f36579f74e68a83e680f97c *tests/testthat/test-versions.R c53312942e21436c7a7b743359cbb398 *tests/testthat/test-write.R desc/DESCRIPTION0000644000176200001440000000222513140637671012707 0ustar liggesusersPackage: desc Title: Manipulate DESCRIPTION Files Version: 1.1.1 Authors@R: c( person("Gábor", "Csárdi",, "csardi.gabor@gmail.com", role = c("aut", "cre")), person("Kirill", "Müller", 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: 5.0.1.9000 Collate: 'assertions.R' 'authors-at-r.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: 2017-08-03 09:45:28 UTC; gaborcsardi Author: Gábor Csárdi [aut, cre], Kirill Müller [aut] Repository: CRAN Date/Publication: 2017-08-03 15:22:33 UTC desc/man/0000755000176200001440000000000013140567212011744 5ustar liggesusersdesc/man/desc_add_author.Rd0000644000176200001440000000213713140567212015346 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}} } desc/man/desc_get.Rd0000644000176200001440000000135313140567212014012 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_or_fail}}, \code{\link{desc_has_fields}}, \code{\link{desc_set}} } desc/man/desc_del_dep.Rd0000644000176200001440000000200013140567212014615 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}} } desc/man/dep_types.Rd0000644000176200001440000000106613140567212014232 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}} } \keyword{datasets} desc/man/description.Rd0000644000176200001440000003544613140567212014572 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_or_fail} is similar to \code{$get}, but throws an error if a field does not exist, except of silently returning \code{NA_character}. The complete API reference: \preformatted{ description$get(keys) description$get_or_fail(keys) description$set(...) description$fields() description$has_fields(keys) description$del(keys)} \describe{ \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 reformats 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 compulsary: \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, udpate 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. } \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.Rd0000644000176200001440000000151513140567212016221 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}} } 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.Rd0000644000176200001440000000110113140567212016367 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}} } desc/man/desc_add_role.Rd0000644000176200001440000000263613140567212015011 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}} } desc/man/desc_has_dep.Rd0000644000176200001440000000134213140567212014634 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}} } desc/man/desc_get_deps.Rd0000644000176200001440000000145413140567212015027 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}} } desc/man/desc_get_author.Rd0000644000176200001440000000163313140567212015375 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}} } desc/man/desc_del_deps.Rd0000644000176200001440000000136213140567212015012 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}} } desc/man/desc_del_from_collate.Rd0000644000176200001440000000171013140567212016522 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}} } 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.Rd0000644000176200001440000000107513140567212016224 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}} } desc/man/desc_set_authors.Rd0000644000176200001440000000174013140567212015573 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}} } desc/man/desc_has_fields.Rd0000644000176200001440000000133113140567212015330 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_or_fail}}, \code{\link{desc_get}}, \code{\link{desc_set}} } 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.Rd0000644000176200001440000000150613140567212015557 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}} } desc/man/desc_set_version.Rd0000644000176200001440000000150213140567212015567 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}} } desc/man/desc_add_to_collate.Rd0000644000176200001440000000176313140567212016175 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}} } desc/man/desc_get_collate.Rd0000644000176200001440000000144013140567212015512 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}} } desc/man/desc_set.Rd0000644000176200001440000000176013140567212014030 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_or_fail}}, \code{\link{desc_get}}, \code{\link{desc_has_fields}} } 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.Rd0000644000176200001440000000166713140567212014666 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}} } desc/man/desc_normalize.Rd0000644000176200001440000000106613140567212015234 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{ Reformats and reorders fields in DESCRIPTION in a standard way. } \seealso{ Other repair functions: \code{\link{desc_reformat_fields}}, \code{\link{desc_reorder_fields}} } desc/man/desc_get_version.Rd0000644000176200001440000000123713140567212015560 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}} } 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.Rd0000644000176200001440000000223313140567212016665 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}} } desc/man/cran_valid_fields.Rd0000644000176200001440000000101313140567212015656 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}} } \keyword{datasets} 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.Rd0000644000176200001440000000120213140567212014472 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_or_fail}}, \code{\link{desc_get}}, \code{\link{desc_has_fields}}, \code{\link{desc_set}} } 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.Rd0000644000176200001440000000161213140567212015500 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}} } 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.Rd0000644000176200001440000000154713140567212015046 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}} } 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.Rd0000644000176200001440000000326713140567212015751 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}} } desc/man/desc_del.Rd0000644000176200001440000000142313140567212013775 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_or_fail}}, \code{\link{desc_get}}, \code{\link{desc_has_fields}}, \code{\link{desc_set}} } desc/man/desc_add_me.Rd0000644000176200001440000000201313140567212014436 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}} } 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.Rd0000644000176200001440000000304113140567212015355 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}} } desc/man/cran_ascii_fields.Rd0000644000176200001440000000100613140567212015651 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}} } \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.Rd0000644000176200001440000000261313140567212015020 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}} } desc/man/desc_set_collate.Rd0000644000176200001440000000167413140567212015537 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}} } desc/man/check_encoding.Rd0000644000176200001440000000121013140567212015150 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. Otherwised \code{new_fields} are checked. } \details{ Warnings are given for non-ascii fields, if the \code{Encoding} field is not set. } \keyword{internal} desc/man/desc_get_or_fail.Rd0000644000176200001440000000143513140567212015506 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/non-oo-api.R \name{desc_get_or_fail} \alias{desc_get_or_fail} \title{Get fields from a DESCRIPTION file, fail if not found} \usage{ desc_get_or_fail(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 fields 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/LICENSE0000644000176200001440000000006113140567212012173 0ustar liggesusersYEAR: 2015-2016 COPYRIGHT HOLDER: Gábor Csárdi