Hello all, Following up on this old thread as I have recently observed, rather a bad practice (maintaining order of installation for R packages rather than relying on R for that), for solving a problem that R branch tools4pkgs (mentioned in this email) addresses very well. More details can be found in https://github.com/dewittpe/R-install-dependencies/issues/3
Therefore I extracted functionality from base R branch and put into standalone package, named after R branch: https://github.com/jangorecki/tools4pkgs Sharing for whoever would reach this email thread in future. Best Regards, Jan Gorecki On Sat, Oct 29, 2022 at 6:26 PM Jan Gorecki <j.gore...@wit.edu.pl> wrote: > > Thank you Gabriel, > > Just for future readers. Below is a base R way to address this common > problem, as instructed by you (+stopifnot to suppress print). > > Rscript -e 'stopifnot(file.copy("DESCRIPTION", > file.path(tdir<-tempdir(), "PACKAGES"))); > db<-available.packages(paste0("file://", tdir)); > install.packages(setdiff(tools::package_dependencies(read.dcf("DESCRIPTION", > fields="Package")[[1L]], db, which="most")[[1L]], > installed.packages(priority="high")[,"Package"]))' > > 3 liner, 310 chars long command, far from ideal, but does work. > > Best, > Jan > > > On Fri, Oct 28, 2022 at 10:42 PM Gabriel Becker <gabembec...@gmail.com> wrote: > > > > Hi Jan, > > > > > > On Fri, Oct 28, 2022 at 1:57 PM Jan Gorecki <j.gore...@wit.edu.pl> wrote: > >> > >> Gabriel, > >> > >> It is the most basic CI use case. One wants to install only > >> dependencies only of the package, and run R CMD check on the package. > > > > > > Really what you're looking for though, is to install all the dependencies > > which aren't present right? Excluding base packages is just a particular > > way to do that under certain assumptions about the CI environment. > > > > So > > > > > > needed_pkgs <- setdiff(package_dependencies(...), > > installed.packages()[,"Package"]) > > install.packages(needed_pkgs, repos = fancyrepos) > > > > > > will do what you want without installing the package itself, if that is > > important. This will filter out base and recommended packages (which will > > be already installed in your CI container, since R is). > > > > > > Now this does not take into account versioned dependencies, so it's not > > actually fully correct (whereas installing the package is), but it gets you > > where you're trying to go. And in a clean CI container without cached > > package installation for the deps, its equivalent. > > > > > > Also, as an aside, if you need to get the base packages, you can do > > > > installed.packages(priority="base")[,"Package"] > > > > base compiler datasets graphics grDevices grid > > > > "base" "compiler" "datasets" "graphics" "grDevices" "grid" > > > > methods parallel splines stats stats4 tcltk > > > > "methods" "parallel" "splines" "stats" "stats4" "tcltk" > > > > tools utils > > > > "tools" "utils" > > > > > > (to get base and recommended packages use 'high' instead of 'base') > > > > No need to be reaching down into unexported functions. So if you *really* > > only want to exclude base functions (which likely will give you some > > protection from versioned dep issues), you can change the code above to > > > > needed_pkgs <- setdiff(package_dependencies(...), > > installed.packages(priority = "high")[,"Package"]) > > install.packages(needed_pkgs, repos = fancyrepos) > > > > Best, > > ~G > > > >> > >> On Fri, Oct 28, 2022 at 8:42 PM Gabriel Becker <gabembec...@gmail.com> > >> wrote: > >> > > >> > Hi Jan, > >> > > >> > The reason, I suspect without speaking for R-core, is that by design you > >> > should not be specifying package dependencies as additional packages to > >> > install. install.packages already does this for you, as it did in the > >> > construct of a repository code that I provided previously in the thread. > >> > You should be *only* doing > >> > > >> > install.packages(<pkg in question>, repos = *) > >> > > >> > Then everything happens automatically via extremely well tested very > >> > mature code. > >> > > >> > I (still) don't understand why you'd need to pass install.packages the > >> > vector of dependencies yourself, as that is counter to install.packages' > >> > core design. > >> > > >> > Does that make sense? > >> > > >> > Best, > >> > ~G > >> > > >> > On Fri, Oct 28, 2022 at 12:18 PM Jan Gorecki <j.gore...@wit.edu.pl> > >> > wrote: > >> >> > >> >> Gabriel, > >> >> > >> >> I am trying to design generic solution that could be applied to > >> >> arbitrary package. Therefore I went with the latter solution you > >> >> proposed. > >> >> If we wouldn't have to exclude base packages, then its a 3 liner > >> >> > >> >> file.copy("DESCRIPTION", file.path(tdir<-tempdir(), "PACKAGES")); > >> >> db<-available.packages(paste0("file://", tdir)); > >> >> utils::install.packages(tools::package_dependencies("pkgname", db, > >> >> which="most")[[1L]]) > >> >> > >> >> As you noticed, we still have to filter out base packages. Otherwise > >> >> it won't be a robust utility that can be used in CI. Therefore we have > >> >> to add a call to tools:::.get_standard_package_names() which is an > >> >> internal function (as of now). Not only complicating the call but also > >> >> putting the functionality outside of safe use. > >> >> > >> >> Considering above, don't you agree that the following one liner could > >> >> nicely address the problem? The problem that hundreds/thousands of > >> >> packages are now addressing in their CI scripts by using a third party > >> >> packages. > >> >> > >> >> utils::install.packages(packages.dcf("DESCRIPTION", which="most")) > >> >> > >> >> It is hard to me to understand why R members don't consider this basic > >> >> functionality to be part of base R. Possibly they just don't need it > >> >> themselves. Yet isn't this sufficient that hundreds/thousands of > >> >> packages does need this functionality? > >> >> > >> >> Best regards, > >> >> Jan > >> >> > >> >> On Mon, Oct 17, 2022 at 8:39 AM Jan Gorecki <j.gore...@wit.edu.pl> > >> >> wrote: > >> >> > > >> >> > Gabriel and Simon > >> >> > > >> >> > I completely agree with what you are saying. > >> >> > The thing is that obtaining recursive deps, all/most whatever, is > >> >> > already well supported in core R. What is missing is just this single > >> >> > functionality I am requesting. > >> >> > > >> >> > If you will look into the branch you can see there is mirror.packages > >> >> > function meant to mirror a slice of CRAN. It is doing exactly what > >> >> > you described: package_dependencies; to obtain recursive deps, then > >> >> > download all, etc. > >> >> > I would love to have this function provided by core R as well, but we > >> >> > need to start somewhere. > >> >> > > >> >> > There are other use cases as well. > >> >> > For example CI, where one wants to install all/most dependencies and > >> >> > then run R CMD check. Then we don't worry about recursive deps are > >> >> > they will be resolved automatically. > >> >> > I don't think it's reasonable to force users to use 3rd party > >> >> > packages to handle such a common and simple use case. Otherwise one > >> >> > has to hard code deps in CI script. Not robust at all. > >> >> > > >> >> > packages.dcf and repos.dcf makes all that way easier, and are solid > >> >> > base for building customized orchestration like mirroring slice of > >> >> > CRAN. > >> >> > > >> >> > Best regards > >> >> > Jan > >> >> > > >> >> > On Sun, Oct 16, 2022, 01:31 Simon Urbanek > >> >> > <simon.urba...@r-project.org> wrote: > >> >> >> > >> >> >> Jan, > >> >> >> > >> >> >> I think using a single DCF as input is not very practical and would > >> >> >> not be useful in the context you describe (creating self contained > >> >> >> repos) since they typically concern a list of packages, but > >> >> >> essentially splitting out the part of install.packages() which > >> >> >> determines which files will be pulled from where would be very > >> >> >> useful as it would be trivial to use it to create repository (what > >> >> >> we always do in corporate environments) instead of installing the > >> >> >> packages. I suspect that install packages is already too complex so > >> >> >> instead of adding a flag to install.packages one could move that > >> >> >> functionality into a separate function - we all do that constantly > >> >> >> for the sites we manage, so it would be certainly something > >> >> >> worthwhile. > >> >> >> > >> >> >> Cheers, > >> >> >> Simon > >> >> >> > >> >> >> > >> >> >> > On Oct 15, 2022, at 7:14 PM, Jan Gorecki <j.gore...@wit.edu.pl> > >> >> >> > wrote: > >> >> >> > > >> >> >> > Hi Gabriel, > >> >> >> > > >> >> >> > It's very nice usage you provided here. Maybe instead of adding new > >> >> >> > function we could extend packages_depenedncies then? To accept > >> >> >> > file path to > >> >> >> > dsc file. > >> >> >> > > >> >> >> > What about repos.dcf? Maybe additional repositories could be an > >> >> >> > attribute > >> >> >> > attached to returned character vector. > >> >> >> > > >> >> >> > The use case is to, for a given package sources, obtain its > >> >> >> > dependencies, > >> >> >> > so one can use that for installing them/mirroring CRAN subset, or > >> >> >> > whatever. > >> >> >> > The later is especially important for a production environment > >> >> >> > where one > >> >> >> > wants to have fixed version of packages, and mirroring relevant > >> >> >> > subset of > >> >> >> > CRAN is the most simple, and IMO reliable, way to manage such > >> >> >> > environment. > >> >> >> > > >> >> >> > Regards > >> >> >> > Jan > >> >> >> > > >> >> >> > On Fri, Oct 14, 2022, 23:34 Gabriel Becker <gabembec...@gmail.com> > >> >> >> > wrote: > >> >> >> > > >> >> >> >> Hi Jan and Jan, > >> >> >> >> > >> >> >> >> Can you explain a little more what exactly you want the > >> >> >> >> non-recursive, > >> >> >> >> non-version aware dependencies from an individual package for? > >> >> >> >> > >> >> >> >> Either way package_dependencies will do this for you* with a > >> >> >> >> little > >> >> >> >> "aggressive convincing". It wants output from available.packages, > >> >> >> >> but who > >> >> >> >> really cares what it wants? It's a function and we are people :) > >> >> >> >> > >> >> >> >>> library(tools) > >> >> >> >>> db <- read.dcf("~/gabe/checkedout/rtables_clean/DESCRIPTION") > >> >> >> >>> package_dependencies("rtables", db, which = > >> >> >> >>> intersect(c("Depends", > >> >> >> >> "Suggests", "Imports", "LinkingTo"), colnames(db))) > >> >> >> >> $rtables > >> >> >> >> [1] "methods" "magrittr" "formatters" "dplyr" "tibble" > >> >> >> >> [6] "tidyr" "testthat" "xml2" "knitr" > >> >> >> >> "rmarkdown" > >> >> >> >> [11] "flextable" "officer" "stats" "htmltools" "grid" > >> >> >> >> > >> >> >> >> > >> >> >> >> The only gotcha that I see immediately is that "LinkingTo" isn't > >> >> >> >> always > >> >> >> >> there (whereas it is with real output from available.packages). > >> >> >> >> If you > >> >> >> >> know your package doesn't have that (or that it does) at call > >> >> >> >> time , this > >> >> >> >> becomes a one-liner: > >> >> >> >> > >> >> >> >> package_dependencies("rtables", db = > >> >> >> >> read.dcf("~/gabe/checkedout/rtables_clean/DESCRIPTION"), which = > >> >> >> >> c("Depends", "Suggests", "Imports")) > >> >> >> >> $rtables > >> >> >> >> [1] "methods" "magrittr" "formatters" "dplyr" "tibble" > >> >> >> >> [6] "tidyr" "testthat" "xml2" "knitr" > >> >> >> >> "rmarkdown" > >> >> >> >> [11] "flextable" "officer" "stats" "htmltools" "grid" > >> >> >> >> > >> >> >> >> You can also trick it a slightly different way by giving it what > >> >> >> >> it > >> >> >> >> actually wants > >> >> >> >> > >> >> >> >>> tdir <- tempdir() > >> >> >> >>> file.copy("~/gabe/checkedout/rtables_clean/DESCRIPTION", > >> >> >> >>> file.path(tdir, > >> >> >> >> "PACKAGES")) > >> >> >> >> [1] TRUE > >> >> >> >>> avl <- available.packages(paste0("file://", tdir)) > >> >> >> >>> library(tools) > >> >> >> >>> package_dependencies("rtables", avl) > >> >> >> >> $rtables > >> >> >> >> [1] "methods" "magrittr" "formatters" "stats" > >> >> >> >> "htmltools" > >> >> >> >> [6] "grid" > >> >> >> >> > >> >> >> >>> package_dependencies("rtables", avl, which = "all") > >> >> >> >> $rtables > >> >> >> >> [1] "methods" "magrittr" "formatters" "stats" > >> >> >> >> "htmltools" > >> >> >> >> [6] "grid" "dplyr" "tibble" "tidyr" "testthat" > >> >> >> >> [11] "xml2" "knitr" "rmarkdown" "flextable" "officer" > >> >> >> >> > >> >> >> >> So the only real benefits I see that we'd be picking up here is > >> >> >> >> automatic > >> >> >> >> filtering by priority, and automatic extraction of the package > >> >> >> >> name from > >> >> >> >> the DESCRIPTION file. I'm not sure either of those warrant a new > >> >> >> >> exported > >> >> >> >> function that R-core has to maintain forever. > >> >> >> >> > >> >> >> >> Best, > >> >> >> >> ~G > >> >> >> >> > >> >> >> >> * I haven't tested this across all OSes, but I dont' know of any > >> >> >> >> reason it > >> >> >> >> wouldn't work generally. > >> >> >> >> > >> >> >> >> On Fri, Oct 14, 2022 at 2:33 PM Jan Gorecki > >> >> >> >> <j.gore...@wit.edu.pl> wrote: > >> >> >> >> > >> >> >> >>> Hello Jan, > >> >> >> >>> > >> >> >> >>> Thanks for confirming about many packages reinventing this > >> >> >> >>> missing > >> >> >> >>> functionality. > >> >> >> >>> packages.dcf was not meant handle versions. It just extracts > >> >> >> >>> names of > >> >> >> >>> dependencies... Yes, such a simple thing, yet missing in base R. > >> >> >> >>> > >> >> >> >>> Versions of packages can be controlled when setting up R pkgs > >> >> >> >>> repo. This > >> >> >> >>> is > >> >> >> >>> how I used to handle it. Making a CRAN subset mirror of fixed > >> >> >> >>> version > >> >> >> >>> pkgs. > >> >> >> >>> BTW. function for that is also included in mentioned branch. I > >> >> >> >>> am just not > >> >> >> >>> proposing it, to increase the chance of having at least this > >> >> >> >>> simple, > >> >> >> >>> missing, functionality merged. > >> >> >> >>> > >> >> >> >>> Best > >> >> >> >>> Jan > >> >> >> >>> > >> >> >> >>> On Fri, Oct 14, 2022, 15:14 Jan Netík <neti...@gmail.com> wrote: > >> >> >> >>> > >> >> >> >>>> Hello Jan, > >> >> >> >>>> > >> >> >> >>>> I have seen many packages that implemented dependencies > >> >> >> >>>> "extraction" on > >> >> >> >>>> their own for internal purposes and today I was doing exactly > >> >> >> >>>> that for > >> >> >> >>>> mine. It's not a big deal using read.dcf on DESCRIPTION. It was > >> >> >> >>> sufficient > >> >> >> >>>> for me, but I had to take care of some \n chars (the overall > >> >> >> >>>> returned > >> >> >> >>> value > >> >> >> >>>> has some rough edges, in my opinion). However, the function > >> >> >> >>>> from the > >> >> >> >>> branch > >> >> >> >>>> seems to not care about version requirements, which are crucial > >> >> >> >>>> for me. > >> >> >> >>>> Maybe that is something to reconsider before merging. > >> >> >> >>>> > >> >> >> >>>> Best, > >> >> >> >>>> Jan > >> >> >> >>>> > >> >> >> >>>> pá 14. 10. 2022 v 2:27 odesílatel Jan Gorecki > >> >> >> >>>> <j.gore...@wit.edu.pl> > >> >> >> >>>> napsal: > >> >> >> >>>> > >> >> >> >>>>> Dear R devs, > >> >> >> >>>>> > >> >> >> >>>>> I would like to raise a request for a simple helper function. > >> >> >> >>>>> Utility function to extract package dependencies from > >> >> >> >>>>> DESCRIPTION file. > >> >> >> >>>>> > >> >> >> >>>>> I do think that tools package is better place, for such a > >> >> >> >>>>> fundamental > >> >> >> >>>>> functionality, than community packages. > >> >> >> >>>>> > >> >> >> >>>>> tools pkg seems perfect fit (having already great function > >> >> >> >>>>> write_PACKAGES). > >> >> >> >>>>> > >> >> >> >>>>> Functionality I am asking for is already in R svn repository > >> >> >> >>>>> since > >> >> >> >>> 2016, > >> >> >> >>>>> in > >> >> >> >>>>> a branch tools4pkgs. Function is called 'packages.dcf'. > >> >> >> >>>>> Another one 'repos.dcf' would be a good functional > >> >> >> >>>>> complementary to it. > >> >> >> >>>>> > >> >> >> >>>>> Those two simple helper functions really makes it easier for > >> >> >> >>> organizations > >> >> >> >>>>> to glue together usage of their own R packages repos and CRAN > >> >> >> >>>>> repo in a > >> >> >> >>>>> smooth way. That could possibly help to offload CRAN from new > >> >> >> >>> submissions. > >> >> >> >>>>> > >> >> >> >>>>> gh mirror link for easy preview: > >> >> >> >>>>> > >> >> >> >>>>> > >> >> >> >>> https://github.com/wch/r-source/blob/tools4pkgs/src/library/tools/R/packages.R#L419 > >> >> >> >>>>> > >> >> >> >>>>> Regards > >> >> >> >>>>> Jan Gorecki > >> >> >> >>>>> > >> >> >> >>>>> [[alternative HTML version deleted]] > >> >> >> >>>>> > >> >> >> >>>>> ______________________________________________ > >> >> >> >>>>> R-devel@r-project.org mailing list > >> >> >> >>>>> https://stat.ethz.ch/mailman/listinfo/r-devel > >> >> >> >>>>> > >> >> >> >>>> > >> >> >> >>> > >> >> >> >>> [[alternative HTML version deleted]] > >> >> >> >>> > >> >> >> >>> ______________________________________________ > >> >> >> >>> R-devel@r-project.org mailing list > >> >> >> >>> https://stat.ethz.ch/mailman/listinfo/r-devel > >> >> >> >>> > >> >> >> >> > >> >> >> > > >> >> >> > [[alternative HTML version deleted]] > >> >> >> > > >> >> >> > ______________________________________________ > >> >> >> > R-devel@r-project.org mailing list > >> >> >> > https://stat.ethz.ch/mailman/listinfo/r-devel > >> >> >> > > >> >> >> ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel