├── .Rbuildignore ├── .gitattributes ├── .github ├── .gitignore ├── CODE_OF_CONDUCT.md └── workflows │ ├── R-CMD-check.yaml │ ├── pkgdown.yaml │ ├── pr-commands.yaml │ └── test-coverage.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── MAINTENANCE.md ├── Makefile ├── NAMESPACE ├── NEWS.md ├── R ├── bioc-standalone.R ├── bioc.R ├── circular.R ├── cran.R ├── dcf.R ├── decompress.R ├── deps.R ├── devel.R ├── download.R ├── git-auth.R ├── git.R ├── github.R ├── install-bioc.R ├── install-bitbucket.R ├── install-cran.R ├── install-dev.R ├── install-git.R ├── install-github.R ├── install-gitlab.R ├── install-local.R ├── install-remote.R ├── install-svn.R ├── install-url.R ├── install-version.R ├── install.R ├── json.R ├── package-deps.R ├── package.R ├── parse-git.R ├── remotes-package.R ├── submodule.R ├── system.R ├── system_requirements.R └── utils.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── codecov.yml ├── inst ├── COPYRIGHTS ├── install-github.R └── install-github.Rin ├── install-github.R ├── man ├── available_packages.Rd ├── bioc_install_repos.Rd ├── download.Rd ├── download_version.Rd ├── git_credentials.Rd ├── github_refs.Rd ├── github_remote.Rd ├── gitlab_pat.Rd ├── install_bioc.Rd ├── install_bitbucket.Rd ├── install_cran.Rd ├── install_deps.Rd ├── install_dev.Rd ├── install_git.Rd ├── install_github.Rd ├── install_gitlab.Rd ├── install_local.Rd ├── install_remote.Rd ├── install_svn.Rd ├── install_url.Rd ├── install_version.Rd ├── package_deps.Rd ├── parse-git-repo.Rd ├── remotes-package.Rd ├── standardise_dep.Rd ├── system_requirements.Rd └── update_packages.Rd ├── remotes.Rproj ├── tests ├── testthat.R └── testthat │ ├── Biobase │ └── DESCRIPTION │ ├── MASS │ └── DESCRIPTION │ ├── _snaps │ └── github.md │ ├── archives │ ├── foo.tar │ ├── foo.tar.bz2 │ ├── foo.tar.gz │ ├── foo.tbz │ ├── foo.tgz │ ├── foo.zip │ └── foo │ │ ├── DESCRIPTION │ │ ├── R │ │ └── foo.R │ │ └── configure │ ├── helper.R │ ├── invalidpkg │ └── DESCRIPTION │ ├── noremotes │ └── DESCRIPTION │ ├── submodule │ ├── DESCRIPTION │ └── NAMESPACE │ ├── test-bioc.R │ ├── test-cran.R │ ├── test-dcf.R │ ├── test-decompress.R │ ├── test-deps.R │ ├── test-devel.R │ ├── test-download.R │ ├── test-git.R │ ├── test-github.R │ ├── test-install-bioc.R │ ├── test-install-bitbucket.R │ ├── test-install-cran.R │ ├── test-install-deps.R │ ├── test-install-dev.R │ ├── test-install-git.R │ ├── test-install-github.R │ ├── test-install-gitlab.R │ ├── test-install-local.R │ ├── test-install-remote.R │ ├── test-install-svn.R │ ├── test-install-url.R │ ├── test-install-version.R │ ├── test-install.R │ ├── test-json.R │ ├── test-package-deps.R │ ├── test-package.R │ ├── test-parse-git.R │ ├── test-script.R │ ├── test-submodule.R │ ├── test-system.R │ ├── test-system_requirements.R │ ├── test-utils.R │ ├── urlremotes │ └── DESCRIPTION │ └── withremotes │ └── DESCRIPTION └── vignettes └── dependencies.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^Meta$ 2 | ^doc$ 3 | ^docs$ 4 | ^_pkgdown\.yml$ 5 | ^codecov\.yml$ 6 | ^docs$ 7 | ^_pkgdown\.yml$ 8 | ^.*\.Rproj$ 9 | ^\.Rproj\.user$ 10 | ^Makefile$ 11 | ^README.markdown$ 12 | ^.travis.yml$ 13 | ^appveyor.yml$ 14 | ^install-github.R$ 15 | ^install-github.Rin$ 16 | ^\.env$ 17 | ^revdep$ 18 | ^cran-comments\.md$ 19 | ^CRAN-RELEASE$ 20 | ^\.gitattributes$ 21 | ^\.github$ 22 | ^LICENSE\.md$ 23 | ^MAINTENANCE\.md$ 24 | ^pkgdown$ 25 | ^README\.Rmd$ 26 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /install-github.R linguist-generated 2 | /inst/install-github.R linguist-generated 3 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual 10 | identity and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or advances of 31 | any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email address, 35 | without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at codeofconduct@posit.co. 63 | All complaints will be reviewed and investigated promptly and fairly. 64 | 65 | All community leaders are obligated to respect the privacy and security of the 66 | reporter of any incident. 67 | 68 | ## Enforcement Guidelines 69 | 70 | Community leaders will follow these Community Impact Guidelines in determining 71 | the consequences for any action they deem in violation of this Code of Conduct: 72 | 73 | ### 1. Correction 74 | 75 | **Community Impact**: Use of inappropriate language or other behavior deemed 76 | unprofessional or unwelcome in the community. 77 | 78 | **Consequence**: A private, written warning from community leaders, providing 79 | clarity around the nature of the violation and an explanation of why the 80 | behavior was inappropriate. A public apology may be requested. 81 | 82 | ### 2. Warning 83 | 84 | **Community Impact**: A violation through a single incident or series of 85 | actions. 86 | 87 | **Consequence**: A warning with consequences for continued behavior. No 88 | interaction with the people involved, including unsolicited interaction with 89 | those enforcing the Code of Conduct, for a specified period of time. This 90 | includes avoiding interactions in community spaces as well as external channels 91 | like social media. Violating these terms may lead to a temporary or permanent 92 | ban. 93 | 94 | ### 3. Temporary Ban 95 | 96 | **Community Impact**: A serious violation of community standards, including 97 | sustained inappropriate behavior. 98 | 99 | **Consequence**: A temporary ban from any sort of interaction or public 100 | communication with the community for a specified period of time. No public or 101 | private interaction with the people involved, including unsolicited interaction 102 | with those enforcing the Code of Conduct, is allowed during this period. 103 | Violating these terms may lead to a permanent ban. 104 | 105 | ### 4. Permanent Ban 106 | 107 | **Community Impact**: Demonstrating a pattern of violation of community 108 | standards, including sustained inappropriate behavior, harassment of an 109 | individual, or aggression toward or disparagement of classes of individuals. 110 | 111 | **Consequence**: A permanent ban from any sort of public interaction within the 112 | community. 113 | 114 | ## Attribution 115 | 116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 117 | version 2.1, available at 118 | . 119 | 120 | Community Impact Guidelines were inspired by 121 | [Mozilla's code of conduct enforcement ladder][https://github.com/mozilla/inclusion]. 122 | 123 | For answers to common questions about this code of conduct, see the FAQ at 124 | . Translations are available at . 125 | 126 | [homepage]: https://www.contributor-covenant.org 127 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | # 4 | # NOTE: This workflow is overkill for most R packages and 5 | # check-standard.yaml is likely a better choice. 6 | # usethis::use_github_action("check-standard") will install it. 7 | on: 8 | push: 9 | branches: [main, master] 10 | pull_request: 11 | branches: [main, master] 12 | 13 | name: R-CMD-check 14 | 15 | jobs: 16 | R-CMD-check: 17 | runs-on: ${{ matrix.config.os }} 18 | 19 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | config: 25 | - {os: macos-latest, r: 'release'} 26 | 27 | - {os: windows-latest, r: 'release'} 28 | # Use 3.6 to trigger usage of RTools35 29 | - {os: windows-latest, r: '3.6'} 30 | # use 4.1 to check with rtools40's older compiler 31 | - {os: windows-latest, r: '4.1'} 32 | 33 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 34 | - {os: ubuntu-latest, r: 'release'} 35 | - {os: ubuntu-latest, r: 'oldrel-1'} 36 | - {os: ubuntu-latest, r: 'oldrel-2'} 37 | - {os: ubuntu-latest, r: 'oldrel-3'} 38 | - {os: ubuntu-latest, r: 'oldrel-4'} 39 | 40 | env: 41 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 42 | R_KEEP_PKG_SOURCE: yes 43 | 44 | steps: 45 | - uses: actions/checkout@v3 46 | 47 | - uses: r-lib/actions/setup-pandoc@v2 48 | 49 | - uses: r-lib/actions/setup-r@v2 50 | with: 51 | r-version: ${{ matrix.config.r }} 52 | http-user-agent: ${{ matrix.config.http-user-agent }} 53 | use-public-rspm: true 54 | 55 | - uses: r-lib/actions/setup-r-dependencies@v2 56 | with: 57 | extra-packages: any::rcmdcheck, git2r=?ignore-before-r=4.0.0 58 | needs: check 59 | 60 | - uses: r-lib/actions/check-r-package@v2 61 | with: 62 | upload-snapshots: true 63 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | # Only restrict concurrency for non-PR jobs 18 | concurrency: 19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 20 | env: 21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 22 | permissions: 23 | contents: write 24 | steps: 25 | - uses: actions/checkout@v3 26 | 27 | - uses: r-lib/actions/setup-pandoc@v2 28 | 29 | - uses: r-lib/actions/setup-r@v2 30 | with: 31 | use-public-rspm: true 32 | 33 | - uses: r-lib/actions/setup-r-dependencies@v2 34 | with: 35 | extra-packages: any::pkgdown, local::. 36 | needs: website 37 | 38 | - name: Build site 39 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 40 | shell: Rscript {0} 41 | 42 | - name: Deploy to GitHub pages 🚀 43 | if: github.event_name != 'pull_request' 44 | uses: JamesIves/github-pages-deploy-action@v4.4.1 45 | with: 46 | clean: false 47 | branch: gh-pages 48 | folder: docs 49 | -------------------------------------------------------------------------------- /.github/workflows/pr-commands.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | issue_comment: 5 | types: [created] 6 | 7 | name: Commands 8 | 9 | jobs: 10 | document: 11 | if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/document') }} 12 | name: document 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - uses: r-lib/actions/pr-fetch@v2 20 | with: 21 | repo-token: ${{ secrets.GITHUB_TOKEN }} 22 | 23 | - uses: r-lib/actions/setup-r@v2 24 | with: 25 | use-public-rspm: true 26 | 27 | - uses: r-lib/actions/setup-r-dependencies@v2 28 | with: 29 | extra-packages: any::roxygen2 30 | needs: pr-document 31 | 32 | - name: Document 33 | run: roxygen2::roxygenise() 34 | shell: Rscript {0} 35 | 36 | - name: commit 37 | run: | 38 | git config --local user.name "$GITHUB_ACTOR" 39 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" 40 | git add man/\* NAMESPACE 41 | git commit -m 'Document' 42 | 43 | - uses: r-lib/actions/pr-push@v2 44 | with: 45 | repo-token: ${{ secrets.GITHUB_TOKEN }} 46 | 47 | style: 48 | if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/style') }} 49 | name: style 50 | runs-on: ubuntu-latest 51 | env: 52 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 53 | steps: 54 | - uses: actions/checkout@v3 55 | 56 | - uses: r-lib/actions/pr-fetch@v2 57 | with: 58 | repo-token: ${{ secrets.GITHUB_TOKEN }} 59 | 60 | - uses: r-lib/actions/setup-r@v2 61 | 62 | - name: Install dependencies 63 | run: install.packages("styler") 64 | shell: Rscript {0} 65 | 66 | - name: Style 67 | run: styler::style_pkg() 68 | shell: Rscript {0} 69 | 70 | - name: commit 71 | run: | 72 | git config --local user.name "$GITHUB_ACTOR" 73 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" 74 | git add \*.R 75 | git commit -m 'Style' 76 | 77 | - uses: r-lib/actions/pr-push@v2 78 | with: 79 | repo-token: ${{ secrets.GITHUB_TOKEN }} 80 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: test-coverage 10 | 11 | jobs: 12 | test-coverage: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - uses: r-lib/actions/setup-r@v2 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v2 25 | with: 26 | extra-packages: any::covr 27 | needs: coverage 28 | 29 | - name: Test coverage 30 | run: | 31 | covr::codecov( 32 | quiet = FALSE, 33 | clean = FALSE, 34 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") 35 | ) 36 | shell: Rscript {0} 37 | 38 | - name: Show testthat output 39 | if: always() 40 | run: | 41 | ## -------------------------------------------------------------------- 42 | find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true 43 | shell: bash 44 | 45 | - name: Upload test results 46 | if: failure() 47 | uses: actions/upload-artifact@v3 48 | with: 49 | name: coverage-test-failures 50 | path: ${{ runner.temp }}/package 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Meta 2 | doc 3 | .Rproj.user 4 | .Rhistory 5 | .RData 6 | /.env 7 | docs/ 8 | /inst/doc 9 | docs 10 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: remotes 2 | Title: R Package Installation from Remote Repositories, Including 'GitHub' 3 | Version: 2.5.0.9000 4 | Authors@R: c( 5 | person("Gábor", "Csárdi", , "csardi.gabor@gmail.com", role = c("aut", "cre")), 6 | person("Jim", "Hester", role = "aut"), 7 | person("Hadley", "Wickham", role = "aut"), 8 | person("Winston", "Chang", role = "aut"), 9 | person("Martin", "Morgan", role = "aut"), 10 | person("Dan", "Tenenbaum", role = "aut"), 11 | person("Posit Software, PBC", role = c("cph", "fnd")), 12 | person("Ascent Digital Services", role = "cph") 13 | ) 14 | Description: Download and install R packages stored in 'GitHub', 'GitLab', 15 | 'Bitbucket', 'Bioconductor', or plain 'subversion' or 'git' 16 | repositories. This package provides the 'install_*' functions in 17 | 'devtools'. Indeed most of the code was copied over from 'devtools'. 18 | License: MIT + file LICENSE 19 | URL: https://remotes.r-lib.org, https://github.com/r-lib/remotes#readme 20 | BugReports: https://github.com/r-lib/remotes/issues 21 | Depends: 22 | R (>= 3.0.0) 23 | Imports: 24 | methods, 25 | stats, 26 | tools, 27 | utils 28 | Suggests: 29 | brew, 30 | callr, 31 | codetools, 32 | covr, 33 | curl, 34 | git2r (>= 0.23.0), 35 | knitr, 36 | mockery, 37 | pingr, 38 | pkgbuild (>= 1.0.1), 39 | rmarkdown, 40 | rprojroot, 41 | testthat (>= 3.0.0), 42 | webfakes, 43 | withr 44 | VignetteBuilder: 45 | knitr 46 | Config/Needs/website: tidyverse/tidytemplate 47 | Config/testthat/edition: 3 48 | Encoding: UTF-8 49 | Roxygen: list(markdown = TRUE) 50 | RoxygenNote: 7.2.3 51 | SystemRequirements: Subversion for install_svn, git for install_git 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2015-2024 2 | COPYRIGHT HOLDER: remotes core team, see COPYRIGHTS file 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2021 remotes authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MAINTENANCE.md: -------------------------------------------------------------------------------- 1 | ## Current state 2 | 3 | Remotes is mostly stable and works for the vast majority of people. 4 | However it accumulates a steady stream of issues and pull requests. 5 | Many of the issues are general installation problems unrelated to remotes itself, and are often better addressed to the community site. 6 | Most of the pull requests are for extensions to other code hosting platforms, or tweaks to ones we don't use regularly (like GitLab). 7 | This makes them somewhat challenging to review and accept, as if it is a platform we don't typically use it is easy for things to break in the future. 8 | In addition testing in general is a challenge, many of the tests require internet access and use up the hourly rate limits, which makes them flaky and the test suite is pretty slow overall. 9 | 10 | There is also a Makefile which needs to be run for any code change, which is easy to forget to do in practice. 11 | 12 | ## Known outstanding issues 13 | 14 | remotes contains a bundled PAT to make using remotes on CI services avoid rate limits. 15 | Unfortunately the bundled PAT somewhat frequently gets invalidated because a user commits it to somewhere on GitHub and GitHub automatically scans new commits for PATs and invalidates them. 16 | When this happens we would have to release a new version of remotes with a new PAT. 17 | The damage done is somewhat limited these days, as the GitHub Actions workflows by default use the automatic GITHUB_TOKEN as the PAT, so most of our builds are not affected. 18 | This can affect builds on other CI systems however. 19 | A workaround is for the user to setup their own PAT rather then relying on the built in one. 20 | 21 | `install.packages()` has a known issue when there are a mix of binary and source packages, like when a package is recently released to CRAN and the binary is not yet built. 22 | It can try to install the packages in the wrong order and there is little the user or remotes can do to fix this. https://bugs.r-project.org/show_bug.cgi?id=17864 23 | Fixing it would require remotes to handle more of the installation ordering itself then it already does, which is what pak does. 24 | Or `install.packages()` could potentially be patched to fix the problem, but getting a good reproducible example seems challenging and R core has been unresponsive to the issue. 25 | 26 | There is a known incompatibility when you have multiple sets of credentials needed. 27 | For instance if you have some repositories that need a private GitHub account and some that need the public one, but don't have the same PAT which has both access. 28 | I don't believe there is an easy to implement solution to this problem given the current code. 29 | A workaround is to use a URL remote for the private stuff instead of a GitHub remote. 30 | 31 | There are also ongoing issues with the GitLab remotes and various scenarios with private repositories. 32 | Unfortunately we don't use GitLab enough ourselves to really smooth out the rough edges. 33 | 34 | ## Future directions 35 | 36 | Ideally remotes would be marked superseded and additional development around package installation would occur in either pak or renv. 37 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | SRC := $(wildcard R/*R) 3 | 4 | all: inst/install-github.R install-github.R 5 | 6 | inst/install-github.R: inst/install-github.Rin $(SRC) 7 | Rscript -e 'library(brew);brew("$<", "$@")' 8 | 9 | install-github.R: inst/install-github.R 10 | cp $< $@ 11 | 12 | clean: 13 | rm inst/install-github.R install-github.R 14 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(format,bioc_git2r_remote) 4 | S3method(format,bioc_xgit_remote) 5 | S3method(format,bitbucket_remote) 6 | S3method(format,cran_remote) 7 | S3method(format,git2r_remote) 8 | S3method(format,github_remote) 9 | S3method(format,gitlab_remote) 10 | S3method(format,local_remote) 11 | S3method(format,remotes) 12 | S3method(format,url_remote) 13 | S3method(format,xgit_remote) 14 | S3method(github_resolve_ref,"NULL") 15 | S3method(github_resolve_ref,default) 16 | S3method(github_resolve_ref,github_pull) 17 | S3method(github_resolve_ref,github_release) 18 | S3method(print,package_deps) 19 | S3method(remote_download,bioc_git2r_remote) 20 | S3method(remote_download,bioc_xgit_remote) 21 | S3method(remote_download,bitbucket_remote) 22 | S3method(remote_download,git2r_remote) 23 | S3method(remote_download,github_remote) 24 | S3method(remote_download,gitlab_remote) 25 | S3method(remote_download,local_remote) 26 | S3method(remote_download,svn_remote) 27 | S3method(remote_download,url_remote) 28 | S3method(remote_download,xgit_remote) 29 | S3method(remote_metadata,bioc_git2r_remote) 30 | S3method(remote_metadata,bioc_xgit_remote) 31 | S3method(remote_metadata,bitbucket_remote) 32 | S3method(remote_metadata,git2r_remote) 33 | S3method(remote_metadata,github_remote) 34 | S3method(remote_metadata,gitlab_remote) 35 | S3method(remote_metadata,local_remote) 36 | S3method(remote_metadata,svn_remote) 37 | S3method(remote_metadata,url_remote) 38 | S3method(remote_metadata,xgit_remote) 39 | S3method(remote_package_name,bioc_git2r_remote) 40 | S3method(remote_package_name,bioc_xgit_remote) 41 | S3method(remote_package_name,bitbucket_remote) 42 | S3method(remote_package_name,cran_remote) 43 | S3method(remote_package_name,default) 44 | S3method(remote_package_name,git2r_remote) 45 | S3method(remote_package_name,github_remote) 46 | S3method(remote_package_name,gitlab_remote) 47 | S3method(remote_package_name,local_remote) 48 | S3method(remote_package_name,svn_remote) 49 | S3method(remote_package_name,url_remote) 50 | S3method(remote_package_name,xgit_remote) 51 | S3method(remote_sha,bioc_git2r_remote) 52 | S3method(remote_sha,bioc_xgit_remote) 53 | S3method(remote_sha,bitbucket_remote) 54 | S3method(remote_sha,cran_remote) 55 | S3method(remote_sha,default) 56 | S3method(remote_sha,git2r_remote) 57 | S3method(remote_sha,github_remote) 58 | S3method(remote_sha,gitlab_remote) 59 | S3method(remote_sha,local_remote) 60 | S3method(remote_sha,svn_remote) 61 | S3method(remote_sha,url_remote) 62 | S3method(remote_sha,xgit_remote) 63 | S3method(update,package_deps) 64 | export(add_metadata) 65 | export(available_packages) 66 | export(available_packages_reset) 67 | export(available_packages_set) 68 | export(bioc_install_repos) 69 | export(bioc_version) 70 | export(dev_package_deps) 71 | export(download_version) 72 | export(git_credentials) 73 | export(github_pull) 74 | export(github_release) 75 | export(github_remote) 76 | export(gitlab_pat) 77 | export(install_bioc) 78 | export(install_bitbucket) 79 | export(install_cran) 80 | export(install_deps) 81 | export(install_dev) 82 | export(install_git) 83 | export(install_github) 84 | export(install_gitlab) 85 | export(install_local) 86 | export(install_remote) 87 | export(install_svn) 88 | export(install_url) 89 | export(install_version) 90 | export(local_package_deps) 91 | export(package_deps) 92 | export(parse_github_repo_spec) 93 | export(parse_github_url) 94 | export(parse_repo_spec) 95 | export(remote_download) 96 | export(remote_metadata) 97 | export(remote_package_name) 98 | export(remote_sha) 99 | export(standardise_dep) 100 | export(system_requirements) 101 | export(update_packages) 102 | importFrom(stats,update) 103 | importFrom(tools,file_ext) 104 | importFrom(utils,available.packages) 105 | importFrom(utils,compareVersion) 106 | importFrom(utils,contrib.url) 107 | importFrom(utils,download.file) 108 | importFrom(utils,install.packages) 109 | importFrom(utils,read.delim) 110 | -------------------------------------------------------------------------------- /R/bioc.R: -------------------------------------------------------------------------------- 1 | 2 | 3 | #' @export 4 | #' @rdname bioc_install_repos 5 | #' @keywords internal 6 | #' @examples 7 | #' bioc_version() 8 | #' bioc_version("3.4") 9 | 10 | bioc_version <- function(r_ver = getRversion()) { 11 | bioconductor$get_bioc_version(r_ver) 12 | } 13 | 14 | #' Tools for Bioconductor repositories 15 | #' 16 | #' `bioc_version()` returns the Bioconductor version for the current or the 17 | #' specified R version. 18 | #' 19 | #' `bioc_install_repos()` deduces the URLs of the Bioconductor repositories. 20 | #' 21 | #' @details 22 | #' Both functions observe the `R_BIOC_VERSION` environment variable, which 23 | #' can be set to force a Bioconductor version. If this is set, then the 24 | #' `r_ver` and `bioc_ver` arguments are ignored. 25 | #' 26 | #' `bioc_install_repos()` observes the `R_BIOC_MIRROR` environment variable 27 | #' and also the `BioC_mirror` option, which can be set to the desired 28 | #' Bioconductor mirror. The option takes precedence if both are set. Its 29 | #' default value is `https://bioconductor.org`. 30 | #' 31 | #' @return 32 | #' `bioc_version()` returns a Bioconductor version, a `package_version` 33 | #' object. 34 | #' 35 | #' `bioc_install_repos()` returns a named character vector of the URLs of 36 | #' the Bioconductor repositories, appropriate for the current or the 37 | #' specified R version. 38 | #' 39 | #' @param r_ver R version to use. For `bioc_install_repos()` it is 40 | #' ignored if `bioc_ver` is specified. 41 | #' @param bioc_ver Bioconductor version to use. Defaults to the default one 42 | #' corresponding to `r_ver`. 43 | #' 44 | #' @export 45 | #' @keywords internal 46 | #' @examples 47 | #' bioc_install_repos() 48 | 49 | bioc_install_repos <- function(r_ver = getRversion(), 50 | bioc_ver = bioc_version(r_ver)) { 51 | bioconductor$get_repos(bioc_ver) 52 | } 53 | -------------------------------------------------------------------------------- /R/circular.R: -------------------------------------------------------------------------------- 1 | 2 | ## A environment to hold which packages are being installed so packages 3 | ## with circular dependencies can be skipped the second time. 4 | 5 | installing <- new.env(parent = emptyenv()) 6 | 7 | is_root_install <- function() is.null(installing$packages) 8 | 9 | exit_from_root_install <- function() installing$packages <- NULL 10 | 11 | check_for_circular_dependencies <- function(pkgdir, quiet) { 12 | pkgdir <- normalizePath(pkgdir) 13 | pkg <- get_desc_field(file.path(pkgdir, "DESCRIPTION"), "Package") 14 | 15 | if (pkg %in% installing$packages) { 16 | if (!quiet) message("Skipping ", pkg, ", it is already being installed") 17 | TRUE 18 | 19 | } else { 20 | installing$packages <- c(installing$packages, pkg) 21 | FALSE 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /R/cran.R: -------------------------------------------------------------------------------- 1 | cache <- new.env(parent = emptyenv()) 2 | 3 | #' @rdname available_packages 4 | #' @export 5 | available_packages_set <- function(repos, type, db) { 6 | signature <- rawToChar(serialize(list(repos, type), NULL, ascii = TRUE)) 7 | if (is.null(cache[[signature]])) { 8 | cache[[signature]] <- db 9 | } 10 | cache[[signature]] 11 | } 12 | 13 | #' @rdname available_packages 14 | #' @export 15 | available_packages_reset <- function() { 16 | rm(list = ls(envir = cache), envir = cache) 17 | } 18 | 19 | #' Simpler available.packages 20 | #' 21 | #' This is mostly equivalent to [utils::available.packages()] however it also 22 | #' caches the full result. Additionally the cache can be assigned explicitly with 23 | #' [available_packages_set()] and reset (cleared) with [available_packages_reset()]. 24 | #' 25 | #' @inheritParams utils::available.packages 26 | #' @keywords internal 27 | #' @seealso [utils::available.packages()] for full documentation on the output format. 28 | #' @export 29 | available_packages <- function(repos = getOption("repos"), type = getOption("pkgType")) { 30 | available_packages_set( 31 | repos, type, 32 | suppressWarnings(utils::available.packages(utils::contrib.url(repos, type), type = type)) 33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /R/dcf.R: -------------------------------------------------------------------------------- 1 | read_dcf <- function(path) { 2 | fields <- colnames(read.dcf(path)) 3 | as.list(read.dcf(path, keep.white = fields)[1, ]) 4 | } 5 | 6 | write_dcf <- function(path, desc) { 7 | write.dcf( 8 | rbind(unlist(desc)), 9 | file = path, 10 | keep.white = names(desc), 11 | indent = 0 12 | ) 13 | } 14 | 15 | get_desc_field <- function(path, field) { 16 | dcf <- read_dcf(path) 17 | dcf[[field]] 18 | } 19 | -------------------------------------------------------------------------------- /R/decompress.R: -------------------------------------------------------------------------------- 1 | # Decompress pkg, if needed 2 | source_pkg <- function(path, subdir = NULL) { 3 | if (!dir.exists(path)) { 4 | bundle <- path 5 | outdir <- tempfile(pattern = "remotes") 6 | dir.create(outdir) 7 | 8 | path <- decompress(path, outdir) 9 | } else { 10 | bundle <- NULL 11 | } 12 | 13 | pkg_path <- if (is.null(subdir)) path else file.path(path, subdir) 14 | 15 | # Check it's an R package 16 | if (!file.exists(file.path(pkg_path, "DESCRIPTION"))) { 17 | stop("Does not appear to be an R package (no DESCRIPTION)", call. = FALSE) 18 | } 19 | 20 | # Check configure is executable if present 21 | config_path <- file.path(pkg_path, "configure") 22 | if (file.exists(config_path)) { 23 | Sys.chmod(config_path, "777") 24 | } 25 | 26 | pkg_path 27 | } 28 | 29 | 30 | decompress <- function(src, target) { 31 | stopifnot(file.exists(src)) 32 | 33 | if (grepl("\\.zip$", src)) { 34 | my_unzip(src, target) 35 | outdir <- getrootdir(as.vector(utils::unzip(src, list = TRUE)$Name)) 36 | } else if (grepl("\\.(tar|tar\\.gz|tar\\.bz2|tgz|tbz)$", src)) { 37 | untar(src, exdir = target) 38 | outdir <- getrootdir(untar(src, list = TRUE)) 39 | } else { 40 | ext <- gsub("^[^.]*\\.", "", src) 41 | stop("Don't know how to decompress files with extension ", ext, 42 | call. = FALSE) 43 | } 44 | 45 | file.path(target, outdir) 46 | } 47 | 48 | 49 | # Returns everything before the last slash in a filename 50 | # getdir("path/to/file") returns "path/to" 51 | # getdir("path/to/dir/") returns "path/to/dir" 52 | getdir <- function(path) sub("/[^/]*$", "", path) 53 | 54 | # Given a list of files, returns the root (the topmost folder) 55 | # getrootdir(c("path/to/file", "path/to/other/thing")) returns "path/to" 56 | # It does not check that all paths have a common prefix. It fails for 57 | # empty input vector. It assumes that directories end with '/'. 58 | getrootdir <- function(file_list) { 59 | stopifnot(length(file_list) > 0) 60 | slashes <- nchar(gsub("[^/]", "", file_list)) 61 | if (min(slashes) == 0) return(".") 62 | 63 | getdir(file_list[which.min(slashes)]) 64 | } 65 | 66 | my_unzip <- function(src, target, unzip = getOption("unzip", "internal")) { 67 | if (unzip %in% c("internal", "")) { 68 | return(utils::unzip(src, exdir = target)) 69 | } 70 | 71 | args <- paste( 72 | "-oq", shQuote(src), 73 | "-d", shQuote(target) 74 | ) 75 | 76 | system_check(unzip, args) 77 | } 78 | -------------------------------------------------------------------------------- /R/devel.R: -------------------------------------------------------------------------------- 1 | 2 | ## The checking code looks for the objects in the package namespace, so defining 3 | ## dll here removes the following NOTE 4 | ## Registration problem: 5 | ## Evaluating ‘dll$foo’ during check gives error 6 | ## ‘object 'dll' not found’: 7 | ## .C(dll$foo, 0L) 8 | ## See https://github.com/wch/r-source/blob/d4e8fc9832f35f3c63f2201e7a35fbded5b5e14c/src/library/tools/R/QC.R##L1950-L1980 9 | ## Setting the class is needed to avoid a note about returning the wrong class. 10 | ## The local object is found first in the actual call, so current behavior is 11 | ## unchanged. 12 | 13 | dll <- list(foo = structure(list(), class = "NativeSymbolInfo")) 14 | 15 | has_devel <- function() { 16 | tryCatch( 17 | has_devel2(), 18 | error = function(e) FALSE 19 | ) 20 | } 21 | 22 | ## This is similar to devtools:::has_devel(), with some 23 | ## very minor differences. 24 | 25 | has_devel2 <- function() { 26 | foo_path <- file.path(tempfile(fileext = ".c")) 27 | 28 | cat("void foo(int *bar) { *bar=1; }\n", file = foo_path) 29 | on.exit(unlink(foo_path)) 30 | 31 | R(c("CMD", "SHLIB", basename(foo_path)), dirname(foo_path)) 32 | dylib <- sub("\\.c$", .Platform$dynlib.ext, foo_path) 33 | on.exit(unlink(dylib), add = TRUE) 34 | 35 | dll <- dyn.load(dylib) 36 | on.exit(dyn.unload(dylib), add = TRUE) 37 | 38 | stopifnot(.C(dll$foo, 0L)[[1]] == 1L) 39 | TRUE 40 | } 41 | 42 | missing_devel_warning <- function(pkgdir) { 43 | pkgname <- tryCatch( 44 | get_desc_field(file.path(pkgdir, "DESCRIPTION"), "Package"), 45 | error = function(e) NULL 46 | ) %||% "" 47 | 48 | sys <- sys_type() 49 | 50 | warning( 51 | "Package ", 52 | pkgname, 53 | " has compiled code, but no suitable ", 54 | "compiler(s) were found. Installation will likely fail.\n ", 55 | if (sys == "windows") { 56 | c("Install Rtools (https://cran.r-project.org/bin/windows/Rtools/).", 57 | "Then use the pkgbuild package, or make sure that Rtools in the PATH.") 58 | }, 59 | if (sys == "macos") "Install XCode and make sure it works.", 60 | if (sys == "linux") "Install compilers via your Linux package manager." 61 | ) 62 | } 63 | 64 | R <- function(args, path = tempdir()) { 65 | 66 | r <- file.path(R.home("bin"), "R") 67 | 68 | args <- c( 69 | "--no-site-file", "--no-environ", "--no-save", 70 | "--no-restore", "--quiet", 71 | args 72 | ) 73 | 74 | system_check(r, args, path = path) 75 | } 76 | -------------------------------------------------------------------------------- /R/git.R: -------------------------------------------------------------------------------- 1 | 2 | # Extract the commit hash from a git archive. Git archives include the SHA1 3 | # hash as the comment field of the tarball pax extended header 4 | # (see https://www.kernel.org/pub/software/scm/git/docs/git-archive.html) 5 | # For GitHub archives this should be the first header after the default one 6 | # (512 byte) header. 7 | git_extract_sha1_tar <- function(bundle) { 8 | 9 | # open the bundle for reading 10 | # We use gzcon for everything because (from ?gzcon) 11 | # > Reading from a connection which does not supply a ‘gzip’ magic 12 | # > header is equivalent to reading from the original connection 13 | conn <- gzcon(file(bundle, open = "rb", raw = TRUE)) 14 | on.exit(close(conn)) 15 | 16 | # The default pax header is 512 bytes long and the first pax extended header 17 | # with the comment should be 51 bytes long 18 | # `52 comment=` (11 chars) + 40 byte SHA1 hash 19 | len <- 0x200 + 0x33 20 | res <- rawToChar(readBin(conn, "raw", n = len)[0x201:len]) 21 | 22 | if (grepl("^52 comment=", res)) { 23 | sub("52 comment=", "", res) 24 | } else { 25 | NULL 26 | } 27 | } 28 | 29 | git <- function(args, quiet = TRUE, path = ".") { 30 | full <- paste0(shQuote(check_git_path()), " ", paste(args, collapse = "")) 31 | if (!quiet) { 32 | message(full) 33 | } 34 | 35 | result <- in_dir(path, system(full, intern = TRUE, ignore.stderr = quiet)) 36 | 37 | status <- attr(result, "status") %||% 0 38 | if (!identical(as.character(status), "0")) { 39 | stop("Command failed (", status, ")", call. = FALSE) 40 | } 41 | 42 | result 43 | } 44 | 45 | # Retrieve the current running path of the git binary. 46 | # @param git_binary_name The name of the binary depending on the OS. 47 | git_path <- function(git_binary_name = NULL) { 48 | # Use user supplied path 49 | if (!is.null(git_binary_name)) { 50 | if (!file.exists(git_binary_name)) { 51 | stop("Path ", git_binary_name, " does not exist", .call = FALSE) 52 | } 53 | return(git_binary_name) 54 | } 55 | 56 | # Look on path 57 | git_path <- Sys.which("git")[[1]] 58 | if (git_path != "") return(git_path) 59 | 60 | # On Windows, look in common locations 61 | if (os_type() == "windows") { 62 | look_in <- c( 63 | "C:/Program Files/Git/bin/git.exe", 64 | "C:/Program Files (x86)/Git/bin/git.exe" 65 | ) 66 | found <- file.exists(look_in) 67 | if (any(found)) return(look_in[found][1]) 68 | } 69 | 70 | NULL 71 | } 72 | 73 | check_git_path <- function(git_binary_name = NULL) { 74 | 75 | path <- git_path(git_binary_name) 76 | 77 | if (is.null(path)) { 78 | stop("Git does not seem to be installed on your system.", call. = FALSE) 79 | } 80 | 81 | path 82 | } 83 | -------------------------------------------------------------------------------- /R/install-cran.R: -------------------------------------------------------------------------------- 1 | 2 | #' Attempts to install a package from CRAN. 3 | #' 4 | #' This function is vectorised on `pkgs` so you can install multiple 5 | #' packages in a single command. 6 | #' 7 | #' @param pkgs A character vector of packages to install. 8 | #' @inheritParams install_github 9 | #' @export 10 | #' @family package installation 11 | #' @examples 12 | #' \dontrun{ 13 | #' install_cran("ggplot2") 14 | #' install_cran(c("httpuv", "shiny")) 15 | #' } 16 | install_cran <- function(pkgs, repos = getOption("repos"), type = getOption("pkgType"), 17 | dependencies = NA, 18 | upgrade = c("default", "ask", "always", "never"), 19 | force = FALSE, 20 | quiet = FALSE, 21 | build = TRUE, build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 22 | build_manual = FALSE, build_vignettes = FALSE, 23 | ...) { 24 | 25 | remotes <- lapply(pkgs, cran_remote, repos = repos, type = type) 26 | 27 | install_remotes(remotes, 28 | dependencies = dependencies, 29 | upgrade = upgrade, 30 | force = force, 31 | quiet = quiet, 32 | build = build, 33 | build_opts = build_opts, 34 | build_manual = build_manual, 35 | build_vignettes = build_vignettes, 36 | repos = repos, 37 | type = type, 38 | ...) 39 | } 40 | 41 | cran_remote <- function(pkg, repos = getOption("repos"), type = getOption("pkgType"), ...) { 42 | 43 | repos <- fix_repositories(repos) 44 | 45 | remote("cran", 46 | name = pkg, 47 | repos = repos, 48 | pkg_type = type) 49 | } 50 | 51 | #' @export 52 | remote_package_name.cran_remote <- function(remote, ...) { 53 | remote$name 54 | } 55 | 56 | #' @export 57 | remote_sha.cran_remote <- function(remote, ...) { 58 | cran <- available_packages(remote$repos, remote$pkg_type) 59 | 60 | trim_ws(unname(cran[, "Version"][match(remote$name, rownames(cran))])) 61 | } 62 | 63 | #' @export 64 | format.cran_remote <- function(x, ...) { 65 | "CRAN" 66 | } 67 | -------------------------------------------------------------------------------- /R/install-dev.R: -------------------------------------------------------------------------------- 1 | #' Install the development version of a package 2 | #' 3 | #' `install_dev()` retrieves the package DESCRIPTION from the CRAN mirror and 4 | #' looks in the 'URL' and 'BugReports' fields for GitHub, GitLab or Bitbucket 5 | #' URLs. It then calls the appropriate `install_()` function to install the 6 | #' development package. 7 | #' 8 | #' @param package The package name to install. 9 | #' @param cran_url The URL of the CRAN mirror to use, by default based on the 10 | #' 'repos' option. If unset uses 'https://cloud.r-project.org'. 11 | #' @param ... Additional arguments passed to [install_github()], 12 | #' [install_gitlab()], or [install_bitbucket()] functions. 13 | #' @family package installation 14 | #' @export 15 | #' @examples 16 | #' \dontrun{ 17 | #' # From GitHub 18 | #' install_dev("dplyr") 19 | #' 20 | #' # From GitLab 21 | #' install_dev("iemiscdata") 22 | #' 23 | #' # From Bitbucket 24 | #' install_dev("argparser") 25 | #' } 26 | install_dev <- function(package, cran_url = getOption("repos")[["CRAN"]], ...) { 27 | if (is.null(cran_url) || identical(cran_url, "@CRAN@")) { 28 | cran_url <- "https://cloud.r-project.org" 29 | } 30 | 31 | refs <- dev_split_ref(package) 32 | url <- build_url(cran_url, "web", "packages", refs[["pkg"]], "DESCRIPTION") 33 | 34 | f <- tempfile() 35 | on.exit(unlink(f)) 36 | 37 | download(f, url) 38 | desc <- read_dcf(f) 39 | 40 | url_fields <- c(desc$URL, desc$BugReports) 41 | 42 | if (length(url_fields) == 0) { 43 | stop("Could not determine development repository", call. = FALSE) 44 | } 45 | 46 | pkg_urls <- unlist(strsplit(url_fields, "[[:space:]]*,[[:space:]]*")) 47 | 48 | # Remove trailing "/issues" from the BugReports URL 49 | pkg_urls <- sub("/issues/?$", "", pkg_urls) 50 | 51 | valid_domains <- c("github[.]com", "gitlab[.]com", "bitbucket[.]org") 52 | 53 | parts <- 54 | re_match(pkg_urls, 55 | sprintf("^https?://(?%s)/(?%s)/(?%s)(?:/(?%s))?", 56 | domain = paste0(valid_domains, collapse = "|"), 57 | username = "[^/]+", 58 | repo = "[^/@#]+", 59 | subdir = "[^/@$ ]+" 60 | ) 61 | )[c("domain", "username", "repo", "subdir")] 62 | 63 | # Remove cases which don't match and duplicates 64 | 65 | parts <- unique(stats::na.omit(parts)) 66 | 67 | if (nrow(parts) != 1) { 68 | stop("Could not determine development repository", call. = FALSE) 69 | } 70 | 71 | full_ref <- paste0( 72 | paste0(c(parts$username, parts$repo, if (nzchar(parts$subdir)) parts$subdir), collapse = "/"), 73 | refs[["ref"]] 74 | ) 75 | 76 | switch(parts$domain, 77 | github.com = install_github(full_ref, ...), 78 | gitlab.com = install_gitlab(full_ref, ...), 79 | bitbucket.org = install_bitbucket(full_ref, ...) 80 | ) 81 | } 82 | -------------------------------------------------------------------------------- /R/install-local.R: -------------------------------------------------------------------------------- 1 | 2 | #' Install a package from a local file 3 | #' 4 | #' This function is vectorised so you can install multiple packages in 5 | #' a single command. 6 | #' 7 | #' @param path path to local directory, or compressed file (tar, zip, tar.gz 8 | #' tar.bz2, tgz2 or tbz) 9 | #' @inheritParams install_url 10 | #' @inheritParams install_github 11 | #' @export 12 | #' @family package installation 13 | #' @examples 14 | #' \dontrun{ 15 | #' dir <- tempfile() 16 | #' dir.create(dir) 17 | #' pkg <- download.packages("testthat", dir, type = "source") 18 | #' install_local(pkg[, 2]) 19 | #' } 20 | 21 | install_local <- function(path = ".", subdir = NULL, 22 | dependencies = NA, 23 | upgrade = c("default", "ask", "always", "never"), 24 | force = FALSE, 25 | quiet = FALSE, 26 | build = !is_binary_pkg(path), 27 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 28 | build_manual = FALSE, build_vignettes = FALSE, 29 | repos = getOption("repos"), 30 | type = getOption("pkgType"), 31 | ...) { 32 | 33 | remotes <- lapply(path, local_remote, subdir = subdir) 34 | install_remotes(remotes, 35 | dependencies = dependencies, 36 | upgrade = upgrade, 37 | force = force, 38 | quiet = quiet, 39 | build = build, 40 | build_opts = build_opts, 41 | build_manual = build_manual, 42 | build_vignettes = build_vignettes, 43 | repos = repos, 44 | type = type, 45 | ...) 46 | } 47 | 48 | local_remote <- function(path, subdir = NULL, branch = NULL, args = character(0), ...) { 49 | remote("local", 50 | path = normalizePath(path), 51 | subdir = subdir 52 | ) 53 | } 54 | 55 | #' @export 56 | remote_download.local_remote <- function(x, quiet = FALSE) { 57 | # Already downloaded - just need to copy to tempdir() 58 | bundle <- tempfile() 59 | dir.create(bundle) 60 | suppressWarnings( 61 | res <- file.copy(x$path, bundle, recursive = TRUE) 62 | ) 63 | if (!all(res)) { 64 | stop("Could not copy `", x$path, "` to `", bundle, "`", call. = FALSE) 65 | } 66 | 67 | # file.copy() creates directory inside of bundle 68 | dir(bundle, full.names = TRUE)[1] 69 | } 70 | 71 | #' @export 72 | remote_metadata.local_remote <- function(x, bundle = NULL, source = NULL, sha = NULL) { 73 | list( 74 | RemoteType = "local", 75 | RemoteUrl = x$path, 76 | RemoteSubdir = x$subdir 77 | ) 78 | } 79 | 80 | #' @export 81 | remote_package_name.local_remote <- function(remote, ...) { 82 | is_tarball <- !dir.exists(remote$path) 83 | if (is_tarball) { 84 | # Assume the name is the name of the tarball 85 | return(sub("_.*$", "", basename(remote$path))) 86 | } 87 | description_path <- file.path(remote$path, "DESCRIPTION") 88 | 89 | read_dcf(description_path)$Package 90 | } 91 | 92 | #' @export 93 | remote_sha.local_remote <- function(remote, ...) { 94 | is_tarball <- !dir.exists(remote$path) 95 | if (is_tarball) { 96 | return(NA_character_) 97 | } 98 | 99 | read_dcf(file.path(remote$path, "DESCRIPTION"))$Version 100 | } 101 | 102 | #' @export 103 | format.local_remote <- function(x, ...) { 104 | "local" 105 | } 106 | -------------------------------------------------------------------------------- /R/install-url.R: -------------------------------------------------------------------------------- 1 | 2 | #' Install a package from a url 3 | #' 4 | #' This function is vectorised so you can install multiple packages in 5 | #' a single command. 6 | #' 7 | #' @param url location of package on internet. The url should point to a 8 | #' zip file, a tar file or a bzipped/gzipped tar file. 9 | #' @param subdir subdirectory within url bundle that contains the R package. 10 | #' @param ... Other arguments passed on to [utils::install.packages()]. 11 | #' @inheritParams install_github 12 | #' @export 13 | #' 14 | #' @family package installation 15 | #' @examples 16 | #' \dontrun{ 17 | #' install_url("https://github.com/hadley/stringr/archive/HEAD.zip") 18 | #' } 19 | 20 | install_url <- function(url, subdir = NULL, 21 | dependencies = NA, 22 | upgrade = c("default", "ask", "always", "never"), 23 | force = FALSE, 24 | quiet = FALSE, 25 | build = TRUE, build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 26 | build_manual = FALSE, build_vignettes = FALSE, 27 | repos = getOption("repos"), 28 | type = getOption("pkgType"), 29 | ...) { 30 | remotes <- lapply(url, url_remote, subdir = subdir) 31 | install_remotes(remotes, 32 | dependencies = dependencies, 33 | upgrade = upgrade, 34 | force = force, 35 | quiet = quiet, 36 | build = build, 37 | build_opts = build_opts, 38 | build_manual = build_manual, 39 | build_vignettes = build_vignettes, 40 | repos = repos, 41 | type = type, 42 | ...) 43 | } 44 | 45 | url_remote <- function(url, subdir = NULL, ...) { 46 | remote("url", 47 | url = url, 48 | subdir = subdir 49 | ) 50 | } 51 | 52 | #' @importFrom tools file_ext 53 | #' @export 54 | remote_download.url_remote <- function(x, quiet = FALSE) { 55 | if (!quiet) { 56 | message("Downloading package from url: ", x$url) # nocov 57 | } 58 | 59 | ext <- if (grepl("\\.tar\\.gz$", x$url)) "tar.gz" else file_ext(x$url) 60 | 61 | bundle <- tempfile(fileext = paste0(".", ext)) 62 | download(bundle, x$url) 63 | } 64 | 65 | #' @export 66 | remote_metadata.url_remote <- function(x, bundle = NULL, source = NULL, sha = NULL) { 67 | list( 68 | RemoteType = "url", 69 | RemoteUrl = x$url, 70 | RemoteSubdir = x$subdir 71 | ) 72 | } 73 | 74 | #' @export 75 | remote_package_name.url_remote <- function(remote, ...) { 76 | NA_character_ 77 | } 78 | 79 | #' @export 80 | remote_sha.url_remote <- function(remote, ...) { 81 | NA_character_ 82 | } 83 | 84 | #' @export 85 | format.url_remote <- function(x, ...) { 86 | "URL" 87 | } 88 | -------------------------------------------------------------------------------- /R/json.R: -------------------------------------------------------------------------------- 1 | 2 | # Standalone JSON parser 3 | # 4 | # The purpose of this file is to provide a standalone JSON parser. 5 | # It is quite slow and bare. If you need a proper parser please use the 6 | # jsonlite package. 7 | # 8 | # The canonical location of this file is in the remotes package: 9 | # https://github.com/r-lib/remotes/blob/HEAD/R/json.R 10 | # 11 | # API: 12 | # parse(text) 13 | # parse_file(filename) 14 | # 15 | # NEWS: 16 | # - 2019/05/15 First standalone version 17 | 18 | json <- local({ 19 | 20 | tokenize_json <- function(text) { 21 | text <- paste(text, collapse = "\n") 22 | 23 | ESCAPE <- '(\\\\[^u[:cntrl:]]|\\\\u[0-9a-fA-F]{4})' 24 | CHAR <- '[^[:cntrl:]"\\\\]' 25 | 26 | STRING <- paste0('"', CHAR, '*(', ESCAPE, CHAR, '*)*"') 27 | NUMBER <- "-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?" 28 | KEYWORD <- 'null|false|true' 29 | SPACE <- '[[:space:]]+' 30 | 31 | match <- gregexpr( 32 | pattern = paste0( 33 | STRING, "|", NUMBER, "|", KEYWORD, "|", SPACE, "|", "." 34 | ), 35 | text = text, 36 | perl = TRUE 37 | ) 38 | 39 | grep("^\\s+$", regmatches(text, match)[[1]], value = TRUE, invert = TRUE) 40 | } 41 | 42 | throw <- function(...) { 43 | stop("JSON: ", ..., call. = FALSE) 44 | } 45 | 46 | # Parse a JSON file 47 | # 48 | # @param filename Path to the JSON file. 49 | # @return R objects corresponding to the JSON file. 50 | 51 | parse_file <- function(filename) { 52 | parse(readLines(filename, warn = FALSE)) 53 | } 54 | 55 | # Parse a JSON string 56 | # 57 | # @param text JSON string. 58 | # @return R object corresponding to the JSON string. 59 | 60 | parse <- function(text) { 61 | 62 | tokens <- tokenize_json(text) 63 | token <- NULL 64 | ptr <- 1 65 | 66 | read_token <- function() { 67 | if (ptr <= length(tokens)) { 68 | token <<- tokens[ptr] 69 | ptr <<- ptr + 1 70 | } else { 71 | token <<- 'EOF' 72 | } 73 | } 74 | 75 | parse_value <- function(name = "") { 76 | if (token == "{") { 77 | parse_object() 78 | } else if (token == "[") { 79 | parse_array() 80 | } else if (token == "EOF" || (nchar(token) == 1 && ! token %in% 0:9)) { 81 | throw("EXPECTED value GOT ", token) 82 | } else { 83 | j2r(token) 84 | } 85 | } 86 | 87 | parse_object <- function() { 88 | res <- structure(list(), names = character()) 89 | 90 | read_token() 91 | 92 | ## Invariant: we are at the beginning of an element 93 | while (token != "}") { 94 | 95 | ## "key" 96 | if (grepl('^".*"$', token)) { 97 | key <- j2r(token) 98 | } else { 99 | throw("EXPECTED string GOT ", token) 100 | } 101 | 102 | ## : 103 | read_token() 104 | if (token != ":") { throw("EXPECTED : GOT ", token) } 105 | 106 | ## value 107 | read_token() 108 | res[key] <- list(parse_value()) 109 | 110 | ## } or , 111 | read_token() 112 | if (token == "}") { 113 | break 114 | } else if (token != ",") { 115 | throw("EXPECTED , or } GOT ", token) 116 | } 117 | read_token() 118 | } 119 | 120 | res 121 | } 122 | 123 | parse_array <- function() { 124 | res <- list() 125 | 126 | read_token() 127 | 128 | ## Invariant: we are at the beginning of an element 129 | while (token != "]") { 130 | ## value 131 | res <- c(res, list(parse_value())) 132 | 133 | ## ] or , 134 | read_token() 135 | if (token == "]") { 136 | break 137 | } else if (token != ",") { 138 | throw("EXPECTED , GOT ", token) 139 | } 140 | read_token() 141 | } 142 | 143 | res 144 | } 145 | 146 | read_token() 147 | parse_value(tokens) 148 | } 149 | 150 | j2r <- function(token) { 151 | if (token == "null") { 152 | NULL 153 | } else if (token == "true") { 154 | TRUE 155 | } else if (token == "false") { 156 | FALSE 157 | } else if (grepl('^".*"$', token)) { 158 | trimq(token) 159 | } else { 160 | as.numeric(token) 161 | } 162 | } 163 | 164 | trimq <- function(x) { 165 | sub('^"(.*)"$', "\\1", x) 166 | } 167 | 168 | structure( 169 | list( 170 | .internal = environment(), 171 | parse = parse, 172 | parse_file = parse_file 173 | ), 174 | class = c("standalone_json", "standalone")) 175 | }) 176 | -------------------------------------------------------------------------------- /R/package-deps.R: -------------------------------------------------------------------------------- 1 | 2 | parse_deps <- function(string) { 3 | if (is.null(string)) return() 4 | stopifnot(is.character(string), length(string) == 1) 5 | if (grepl("^\\s*$", string)) return() 6 | 7 | # Split by commas with surrounding whitespace removed 8 | pieces <- strsplit(string, "[[:space:]]*,[[:space:]]*")[[1]] 9 | 10 | # Get the names 11 | names <- gsub("\\s*\\(.*?\\)", "", pieces) 12 | names <- gsub("^\\s+|\\s+$", "", names) 13 | 14 | # Get the versions and comparison operators 15 | versions_str <- pieces 16 | have_version <- grepl("\\(.*\\)", versions_str) 17 | versions_str[!have_version] <- NA 18 | 19 | compare <- sub(".*\\(\\s*(\\S+)\\s+.*\\s*\\).*", "\\1", versions_str) 20 | versions <- sub(".*\\(\\s*\\S+\\s+(\\S*)\\s*\\).*", "\\1", versions_str) 21 | 22 | # Check that non-NA comparison operators are valid 23 | compare_nna <- compare[!is.na(compare)] 24 | compare_valid <- compare_nna %in% c(">", ">=", "==", "<=", "<") 25 | if(!all(compare_valid)) { 26 | stop("Invalid comparison operator in dependency: ", 27 | paste(compare_nna[!compare_valid], collapse = ", ")) 28 | } 29 | 30 | deps <- data.frame(name = names, compare = compare, 31 | version = versions, stringsAsFactors = FALSE) 32 | 33 | # Remove R dependency 34 | deps[names != "R", ] 35 | } 36 | -------------------------------------------------------------------------------- /R/package.R: -------------------------------------------------------------------------------- 1 | 2 | load_pkg_description <- function(path) { 3 | 4 | path <- normalizePath(path, mustWork = TRUE) 5 | 6 | if (!is_dir(path)) { 7 | dir <- tempfile() 8 | path_desc <- untar_description(path, dir = dir) 9 | on.exit(unlink(dir, recursive = TRUE)) 10 | 11 | } else { 12 | path_desc <- file.path(path, "DESCRIPTION") 13 | } 14 | 15 | desc <- read_dcf(path_desc) 16 | names(desc) <- tolower(names(desc)) 17 | desc$path <- path 18 | 19 | desc 20 | } 21 | -------------------------------------------------------------------------------- /R/parse-git.R: -------------------------------------------------------------------------------- 1 | #' Parse a remote git repo specification 2 | #' 3 | #' A remote repo can be specified in two ways: 4 | #' \describe{ 5 | #' \item{as a URL}{`parse_github_url()` handles HTTPS and SSH remote URLs 6 | #' and various GitHub browser URLs} 7 | #' \item{via a shorthand}{`parse_repo_spec()` handles this concise form: 8 | #' `[username/]repo[/subdir][#pull|@ref|@*release]`} 9 | #' } 10 | #' 11 | #' @param repo Character scalar, the repo specification. 12 | #' @return List with members: `username`, `repo`, `subdir` 13 | #' `ref`, `pull`, `release`, some which will be empty. 14 | #' 15 | #' @name parse-git-repo 16 | #' @examples 17 | #' parse_repo_spec("metacran/crandb") 18 | #' parse_repo_spec("jimhester/covr#47") ## pull request 19 | #' parse_repo_spec("jeroen/curl@v0.9.3") ## specific tag 20 | #' parse_repo_spec("tidyverse/dplyr@*release") ## shorthand for latest release 21 | #' parse_repo_spec("r-lib/remotes@550a3c7d3f9e1493a2ba") ## commit SHA 22 | #' parse_repo_spec("igraph=igraph/rigraph") ## Different package name from repo name 23 | #' 24 | #' parse_github_url("https://github.com/jeroen/curl.git") 25 | #' parse_github_url("git@github.com:metacran/crandb.git") 26 | #' parse_github_url("https://github.com/jimhester/covr") 27 | #' parse_github_url("https://github.example.com/user/repo.git") 28 | #' parse_github_url("git@github.example.com:user/repo.git") 29 | #' 30 | #' parse_github_url("https://github.com/r-lib/remotes/pull/108") 31 | #' parse_github_url("https://github.com/r-lib/remotes/tree/name-of-branch") 32 | #' parse_github_url("https://github.com/r-lib/remotes/commit/1234567") 33 | #' parse_github_url("https://github.com/r-lib/remotes/releases/latest") 34 | #' parse_github_url("https://github.com/r-lib/remotes/releases/tag/1.0.0") 35 | NULL 36 | 37 | #' @export 38 | #' @rdname parse-git-repo 39 | parse_repo_spec <- function(repo) { 40 | package_name_rx <- "(?:(?[[:alpha:]][[:alnum:].]*[[:alnum:]])=)?" 41 | username_rx <- "(?:(?[^/]+)/)" 42 | repo_rx <- "(?[^/@#]+)" 43 | subdir_rx <- "(?:/(?[^@#]*[^@#/])/?)?" 44 | ref_rx <- "(?:@(?[^*].*))" 45 | pull_rx <- "(?:#(?[0-9]+))" 46 | release_rx <- "(?:@(?[*]release))" 47 | ref_or_pull_or_release_rx <- sprintf( 48 | "(?:%s|%s|%s)?", ref_rx, pull_rx, release_rx 49 | ) 50 | spec_rx <- sprintf( 51 | "^%s%s%s%s%s$", package_name_rx, username_rx, repo_rx, subdir_rx, ref_or_pull_or_release_rx 52 | ) 53 | params <- as.list(re_match(text = repo, pattern = spec_rx)) 54 | 55 | if (is.na(params$.match)) { 56 | stop(sprintf("Invalid git repo specification: '%s'", repo)) 57 | } 58 | 59 | params[grepl("^[^\\.]", names(params))] 60 | } 61 | 62 | #' @export 63 | #' @rdname parse-git-repo 64 | parse_github_repo_spec <- parse_repo_spec 65 | 66 | #' @export 67 | #' @rdname parse-git-repo 68 | parse_github_url <- function(repo) { 69 | prefix_rx <- "(?:github[^/:]+[/:])" 70 | username_rx <- "(?:(?[^/]+)/)" 71 | repo_rx <- "(?[^/@#]+)" 72 | ref_rx <- "(?:(?:tree|commit|releases/tag)/(?.+$))" 73 | pull_rx <- "(?:pull/(?.+$))" 74 | release_rx <- "(?:releases/)(?.+$)" 75 | ref_or_pull_or_release_rx <- sprintf( 76 | "(?:/(%s|%s|%s))?", ref_rx, pull_rx, release_rx 77 | ) 78 | url_rx <- sprintf( 79 | "%s%s%s%s", 80 | prefix_rx, username_rx, repo_rx, ref_or_pull_or_release_rx 81 | ) 82 | params <- as.list(re_match(text = repo, pattern = url_rx)) 83 | 84 | if (is.na(params$.match)) { 85 | stop(sprintf("Invalid GitHub URL: '%s'", repo)) 86 | } 87 | if (params$ref == "" && params$pull == "" && params$release == "") { 88 | params$repo <- gsub("\\.git$", "", params$repo) 89 | } 90 | if (params$release == "latest") { 91 | params$release <- "*release" 92 | } 93 | 94 | params[grepl("^[^\\.]", names(params))] 95 | } 96 | 97 | parse_git_repo <- function(repo) { 98 | 99 | if (grepl("^https://github|^git@github", repo)) { 100 | params <- parse_github_url(repo) 101 | } else { 102 | params <- parse_repo_spec(repo) 103 | } 104 | params <- params[viapply(params, nchar) > 0] 105 | 106 | if (!is.null(params$pull)) { 107 | params$ref <- github_pull(params$pull) 108 | params$pull <- NULL 109 | } 110 | 111 | if (!is.null(params$release)) { 112 | params$ref <- github_release() 113 | params$release <- NULL 114 | } 115 | 116 | params 117 | } 118 | 119 | -------------------------------------------------------------------------------- /R/remotes-package.R: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | 4 | ## usethis namespace: start 5 | ## usethis namespace: end 6 | NULL 7 | -------------------------------------------------------------------------------- /R/submodule.R: -------------------------------------------------------------------------------- 1 | parse_submodules <- function(file) { 2 | if (grepl("\n", file)) { 3 | x <- strsplit(file, "\n")[[1]] 4 | } else { 5 | x <- readLines(file) 6 | } 7 | 8 | # https://git-scm.com/docs/git-config#_syntax 9 | # Subsection names are case sensitive and can contain any characters except 10 | # newline and the null byte. Doublequote " and backslash can be included by 11 | # escaping them as \" and \\ 12 | double_quoted_string_with_escapes <- '(?:\\\\.|[^"])*' 13 | 14 | # Otherwise extract section names 15 | section_names <- re_match( 16 | x, 17 | sprintf('^[[:space:]]*\\[submodule "(?%s)"\\][[:space:]]*$', double_quoted_string_with_escapes) 18 | )$submodule 19 | 20 | # If no sections found return the empty list 21 | if (all(is.na(section_names))) { 22 | return(list()) 23 | } 24 | 25 | # Extract name = value 26 | # The variable names are case-insensitive, allow only alphanumeric characters 27 | # and -, and must start with an alphabetic character. 28 | variable_name <- "[[:alpha:]][[:alnum:]\\-]*" 29 | mapping_values <- re_match( 30 | x, 31 | sprintf('^[[:space:]]*(?%s)[[:space:]]*=[[:space:]]*(?.*)[[:space:]]*$', variable_name), 32 | ) 33 | 34 | values <- cbind(submodule = fill(section_names), mapping_values[c("name", "value")], stringsAsFactors = FALSE) 35 | values <- values[!is.na(mapping_values$.match), ] 36 | 37 | # path and valid url are required 38 | if (!all(c("path", "url") %in% values$name)) { 39 | warning("Invalid submodule definition, skipping submodule installation", immediate. = TRUE, call. = FALSE) 40 | return(list()) 41 | } 42 | 43 | # Roughly equivalent to tidyr::spread(values, name, value) 44 | res <- stats::reshape(values, idvar = "submodule", timevar = "name", v.name = "value", direction = "wide") 45 | 46 | # Set the column names, reshape prepends `value.` to path, url and branch 47 | colnames(res) <- gsub("value[.]", "", colnames(res)) 48 | 49 | # path and valid url are required 50 | if (any(is.na(res$url), is.na(res$path))) { 51 | warning("Invalid submodule definition, skipping submodule installation", immediate. = TRUE, call. = FALSE) 52 | return(list()) 53 | } 54 | 55 | # branch is optional 56 | if (!exists("branch", res)) { 57 | res$branch <- NA_character_ 58 | } 59 | 60 | # Remove unneeded attribute 61 | attr(res, "reshapeWide") <- NULL 62 | 63 | # Remove rownames 64 | rownames(res) <- NULL 65 | 66 | res 67 | } 68 | 69 | # Adapted from https://stackoverflow.com/a/9517731/2055486 70 | fill <- function(x) { 71 | not_missing <- !is.na(x) 72 | 73 | res <- x[not_missing] 74 | res[cumsum(not_missing)] 75 | } 76 | 77 | update_submodule <- function(url, path, branch, quiet) { 78 | args <- c('clone', '--depth', '1', '--no-hardlinks --recurse-submodules') 79 | if (length(branch) > 0 && !is.na(branch) && branch != 'HEAD') { 80 | args <- c(args, "--branch", branch) 81 | } 82 | args <- c(args, url, path) 83 | 84 | git(paste0(args, collapse = " "), quiet = quiet) 85 | } 86 | 87 | update_submodules <- function(source, subdir, quiet) { 88 | file <- file.path(source, ".gitmodules") 89 | 90 | if (!file.exists(file)) { 91 | 92 | if (!is.null(subdir)) { 93 | nb_sub_folders <- lengths(strsplit(subdir, "/")) 94 | source <- do.call(file.path, as.list(c(source, rep("..", nb_sub_folders)))) 95 | } 96 | 97 | file <- file.path(source, ".gitmodules") 98 | if (!file.exists(file)) { 99 | return() 100 | } 101 | } 102 | info <- parse_submodules(file) 103 | 104 | # Fixes #234 105 | if (length(info) == 0) { 106 | return() 107 | } 108 | to_ignore <- in_r_build_ignore(info$path, file.path(source, ".Rbuildignore")) 109 | if (!(length(info) > 0)) { 110 | return() 111 | } 112 | info <- info[!to_ignore, ] 113 | 114 | for (i in seq_len(NROW(info))) { 115 | update_submodule(info$url[[i]], file.path(source, info$path[[i]]), info$branch[[i]], quiet) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /R/system.R: -------------------------------------------------------------------------------- 1 | 2 | system_check <- function(command, args = character(), quiet = TRUE, 3 | error = TRUE, path = ".") { 4 | 5 | out <- tempfile() 6 | err <- tempfile() 7 | on.exit(unlink(out), add = TRUE) 8 | on.exit(unlink(err), add = TRUE) 9 | 10 | ## We suppress warnings, they are given if the command 11 | ## exits with a non-zero status 12 | res <- in_dir( 13 | path, 14 | suppressWarnings( 15 | system2(command, args = args, stdout = out, stderr = err) 16 | ) 17 | ) 18 | 19 | res <- list( 20 | stdout = tryCatch( 21 | suppressWarnings(win2unix(read_char(out))), 22 | error = function(e) "" 23 | ), 24 | stderr = tryCatch( 25 | suppressWarnings(win2unix(read_char(err))), 26 | error = function(e) "" 27 | ), 28 | status = res 29 | ) 30 | 31 | if (error && res$status != 0) { 32 | stop("Command ", command, " failed ", res$stderr) 33 | } 34 | 35 | if (! quiet) { 36 | if (! identical(res$stdout, NA_character_)) cat(res$stdout) 37 | if (! identical(res$stderr, NA_character_)) cat(res$stderr) 38 | } 39 | 40 | res 41 | } 42 | 43 | win2unix <- function(str) { 44 | gsub("\r\n", "\n", str, fixed = TRUE) 45 | } 46 | 47 | read_char <- function(path, ...) { 48 | readChar(path, nchars = file.info(path)$size, ...) 49 | } 50 | -------------------------------------------------------------------------------- /R/system_requirements.R: -------------------------------------------------------------------------------- 1 | DEFAULT_RSPM_REPO_ID <- "1" # cran 2 | DEFAULT_RSPM <- "https://packagemanager.posit.co" 3 | 4 | #' Query the system requirements for a package (and its dependencies) 5 | #' 6 | #' Returns a character vector of commands to run that will install system 7 | #' requirements for the queried operating system. 8 | #' 9 | #' @param os,os_release The operating system and operating system release version, see 10 | #' for the 11 | #' list of supported operating systems. 12 | #' 13 | #' If `os_release` is `NULL`, `os` must consist of the operating system 14 | #' and the version separated by a dash, e.g. `"ubuntu-18.04"`. 15 | #' @param path The path to the dev package's root directory. 16 | #' @param package CRAN package name(s) to lookup system requirements for. If not 17 | #' `NULL`, this is used and `path` is ignored. 18 | #' @param curl The location of the curl binary on your system. 19 | #' @return A character vector of commands needed to install the system requirements for the package. 20 | #' @export 21 | system_requirements <- function(os, os_release = NULL, path = ".", package = NULL, curl = Sys.which("curl")) { 22 | if (is.null(os_release)) { 23 | os_release <- strsplit(os, "-", fixed = TRUE)[[1]] 24 | if (length(os_release) != 2) { 25 | stop("If os_release is missing, os must consist of name and release.", call. = FALSE) 26 | } 27 | 28 | os <- os_release[[1]] 29 | os_release <- os_release[[2]] 30 | } 31 | 32 | os_versions <- supported_os_versions() 33 | 34 | os <- match.arg(os, names(os_versions)) 35 | 36 | os_release <- match.arg(os_release, os_versions[[os]]) 37 | 38 | if (!nzchar(curl)) { 39 | stop("`curl` must be on the `PATH`.", call. = FALSE) 40 | } 41 | 42 | rspm <- Sys.getenv("RSPM_ROOT", DEFAULT_RSPM) 43 | rspm_repo_id <- Sys.getenv("RSPM_REPO_ID", DEFAULT_RSPM_REPO_ID) 44 | rspm_repo_url <- sprintf("%s/__api__/repos/%s", rspm, rspm_repo_id) 45 | 46 | if (!is.null(package)) { 47 | res <- system2( 48 | curl, 49 | args = c( 50 | "--silent", 51 | "-L", 52 | shQuote(sprintf("%s/sysreqs?all=false&pkgname=%s&distribution=%s&release=%s", 53 | rspm_repo_url, 54 | paste(package, collapse = "&pkgname="), 55 | os, 56 | os_release) 57 | )), 58 | stdout = TRUE 59 | ) 60 | res <- json$parse(res) 61 | if (!is.null(res$error)) { 62 | stop(res$error) 63 | } 64 | pre_install <- unique(unlist(c(res[["pre_install"]], lapply(res[["requirements"]], `[[`, c("requirements", "pre_install"))))) 65 | install_scripts <- unique(unlist(c(res[["install_scripts"]], lapply(res[["requirements"]], `[[`, c("requirements", "install_scripts"))))) 66 | } else { 67 | desc_file <- normalizePath(file.path(path, "DESCRIPTION"), mustWork = FALSE) 68 | if (!file.exists(desc_file)) { 69 | stop("`", path, "` must contain a package.", call. = FALSE) 70 | } 71 | 72 | res <- system2( 73 | curl, 74 | args = c( 75 | "--silent", 76 | "-L", 77 | "--data-binary", 78 | shQuote(paste0("@", desc_file)), 79 | shQuote(sprintf("%s/sysreqs?distribution=%s&release=%s&suggests=true", 80 | rspm_repo_url, 81 | os, 82 | os_release) 83 | ) 84 | ), 85 | stdout = TRUE 86 | ) 87 | res <- json$parse(res) 88 | if (!is.null(res$error)) { 89 | stop(res$error) 90 | } 91 | 92 | pre_install <- unique(unlist(c(res[["pre_install"]], lapply(res[["dependencies"]], `[[`, "pre_install")))) 93 | install_scripts <- unique(unlist(c(res[["install_scripts"]], lapply(res[["dependencies"]], `[[`, "install_scripts")))) 94 | } 95 | 96 | as.character(c(pre_install, install_scripts)) 97 | } 98 | 99 | # Adapted from https://github.com/rstudio/r-system-requirements/blob/master/systems.json 100 | # OSs commented out are not currently supported by the API 101 | supported_os_versions <- function() { 102 | list( 103 | #"debian" = c("8", "9"), 104 | "ubuntu" = c("14.04", "16.04", "18.04", "20.04", "22.04", "24.04"), 105 | "centos" = c("6", "7", "8"), 106 | "redhat" = c("6", "7", "8"), 107 | "opensuse" = c("42.3", "15.0"), 108 | "sle" = c("12.3", "15.0") 109 | #"windows" = c("") 110 | ) 111 | } 112 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://remotes.r-lib.org 2 | 3 | development: 4 | mode: auto 5 | 6 | template: 7 | package: tidytemplate 8 | bootstrap: 5 9 | 10 | includes: 11 | in_header: | 12 | 13 | 14 | 15 | reference: 16 | - title: Package Installation 17 | desc: Tools for installing packages from a variety of locations. 18 | contents: 19 | - install_bioc 20 | - install_bitbucket 21 | - install_cran 22 | - install_dev 23 | - install_git 24 | - install_github 25 | - install_gitlab 26 | - install_local 27 | - install_svn 28 | - install_url 29 | - install_version 30 | - download_version 31 | - update_packages 32 | - system_requirements 33 | - title: Dependencies 34 | desc: Tools for working with package dependencies. 35 | contents: 36 | - contains("deps") 37 | - title: GitHub helpers 38 | desc: Utilities for interacting with GitHub. 39 | contents: 40 | - starts_with("github") 41 | - starts_with("parse_github") 42 | authors: 43 | "Jim Hester": 44 | href: http://jimhester.com 45 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /inst/COPYRIGHTS: -------------------------------------------------------------------------------- 1 | (c) 2015-2016 Ascent Digital Services (formerly Mango Solutions) 2 | (c) 2017 Gábor Csárdi 3 | (c) 2017-2024 Posit Software, PBC (formerly RStudio) 4 | -------------------------------------------------------------------------------- /inst/install-github.Rin: -------------------------------------------------------------------------------- 1 | # Autogenerated from contents in the package's R directory, do not edit! 2 | # Run make to update. 3 | 4 | function(...) { 5 | 6 | ## This is the code of the package, put in here by brew 7 | 8 | <% 9 | Sys.setlocale("LC_COLLATE","C") 10 | lapply( 11 | sort(list.files("R", full.names = TRUE)), 12 | function(x) { 13 | text <- c(paste0("# Contents of ", x), readLines(x)) 14 | cat(paste0(" ", text), sep = "\n") 15 | } 16 | ) 17 | %> 18 | 19 | ## Standalone mode, make sure that we restore the env var on exit 20 | old <- Sys.getenv("R_REMOTES_STANDALONE", NA_character_) 21 | Sys.setenv("R_REMOTES_STANDALONE" = "true") 22 | if (is.na(old)) { 23 | on.exit(Sys.unsetenv("R_REMOTES_STANDALONE"), add = TRUE) 24 | } else { 25 | on.exit(Sys.setenv("R_REMOTES_STANDALONE" = old), add = TRUE) 26 | } 27 | 28 | install_github(...) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /man/available_packages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cran.R 3 | \name{available_packages_set} 4 | \alias{available_packages_set} 5 | \alias{available_packages_reset} 6 | \alias{available_packages} 7 | \title{Simpler available.packages} 8 | \usage{ 9 | available_packages_set(repos, type, db) 10 | 11 | available_packages_reset() 12 | 13 | available_packages(repos = getOption("repos"), type = getOption("pkgType")) 14 | } 15 | \arguments{ 16 | \item{repos}{ 17 | character vector, the base URL(s) of the repositories to use. 18 | } 19 | 20 | \item{type}{ 21 | character string, indicate which type of packages: see 22 | \code{\link[utils]{install.packages}}. 23 | 24 | If \code{type = "both"} this will use the source repository. 25 | } 26 | } 27 | \description{ 28 | This is mostly equivalent to \code{\link[utils:available.packages]{utils::available.packages()}} however it also 29 | caches the full result. Additionally the cache can be assigned explicitly with 30 | \code{\link[=available_packages_set]{available_packages_set()}} and reset (cleared) with \code{\link[=available_packages_reset]{available_packages_reset()}}. 31 | } 32 | \seealso{ 33 | \code{\link[utils:available.packages]{utils::available.packages()}} for full documentation on the output format. 34 | } 35 | \keyword{internal} 36 | -------------------------------------------------------------------------------- /man/bioc_install_repos.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bioc.R 3 | \name{bioc_version} 4 | \alias{bioc_version} 5 | \alias{bioc_install_repos} 6 | \title{Tools for Bioconductor repositories} 7 | \usage{ 8 | bioc_version(r_ver = getRversion()) 9 | 10 | bioc_install_repos(r_ver = getRversion(), bioc_ver = bioc_version(r_ver)) 11 | } 12 | \arguments{ 13 | \item{r_ver}{R version to use. For \code{bioc_install_repos()} it is 14 | ignored if \code{bioc_ver} is specified.} 15 | 16 | \item{bioc_ver}{Bioconductor version to use. Defaults to the default one 17 | corresponding to \code{r_ver}.} 18 | } 19 | \value{ 20 | \code{bioc_version()} returns a Bioconductor version, a \code{package_version} 21 | object. 22 | 23 | \code{bioc_install_repos()} returns a named character vector of the URLs of 24 | the Bioconductor repositories, appropriate for the current or the 25 | specified R version. 26 | } 27 | \description{ 28 | \code{bioc_version()} returns the Bioconductor version for the current or the 29 | specified R version. 30 | } 31 | \details{ 32 | \code{bioc_install_repos()} deduces the URLs of the Bioconductor repositories. 33 | 34 | Both functions observe the \code{R_BIOC_VERSION} environment variable, which 35 | can be set to force a Bioconductor version. If this is set, then the 36 | \code{r_ver} and \code{bioc_ver} arguments are ignored. 37 | 38 | \code{bioc_install_repos()} observes the \code{R_BIOC_MIRROR} environment variable 39 | and also the \code{BioC_mirror} option, which can be set to the desired 40 | Bioconductor mirror. The option takes precedence if both are set. Its 41 | default value is \verb{https://bioconductor.org}. 42 | } 43 | \examples{ 44 | bioc_version() 45 | bioc_version("3.4") 46 | bioc_install_repos() 47 | } 48 | \keyword{internal} 49 | -------------------------------------------------------------------------------- /man/download.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/download.R 3 | \name{download} 4 | \alias{download} 5 | \title{Download a file} 6 | \usage{ 7 | download( 8 | path, 9 | url, 10 | auth_token = NULL, 11 | basic_auth = NULL, 12 | quiet = TRUE, 13 | headers = NULL 14 | ) 15 | } 16 | \arguments{ 17 | \item{path}{Path to download to. \code{dirname(path)} must exist.} 18 | 19 | \item{url}{URL.} 20 | 21 | \item{auth_token}{Token for token-based authentication or \code{NULL}.} 22 | 23 | \item{basic_auth}{List with \code{user} and \code{password} for basic HTTP 24 | authentication, or \code{NULL}.} 25 | 26 | \item{quiet}{Passed to \code{\link[=download.file]{download.file()}} or \code{\link[curl:curl_download]{curl::curl_download()}}.} 27 | 28 | \item{headers}{Named character vector of HTTP headers to use.} 29 | } 30 | \value{ 31 | \code{path}, if the download was successful. 32 | } 33 | \description{ 34 | Uses either the curl package for R versions older than 3.2.0, 35 | otherwise a wrapper around \code{\link[=download.file]{download.file()}}. 36 | } 37 | \details{ 38 | We respect the \code{download.file.method} setting of the user. If it is 39 | not set, then see \code{download_method()} for choosing a method. 40 | 41 | Authentication can be supplied three ways: 42 | \itemize{ 43 | \item By setting \code{auth_token}. This will append an HTTP \code{Authorization} 44 | header: \verb{Authorization: token \{auth_token\}}. 45 | \item By setting \code{basic_auth} to a list with elements \code{user} and \code{password}. 46 | This will append a proper \verb{Authorization: Basic \{encoded_password\}} 47 | HTTP header. 48 | \item By specifying the proper \code{headers} directly. 49 | } 50 | 51 | If both \code{auth_token} and \code{basic_auth} are specified, that's an error. 52 | \code{auth_token} and \code{basic_auth} are \emph{appended} to \code{headers}, so they 53 | take precedence over an \code{Authorization} header that is specified 54 | directly in \code{headers}. 55 | } 56 | \keyword{internal} 57 | -------------------------------------------------------------------------------- /man/download_version.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-version.R 3 | \name{download_version} 4 | \alias{download_version} 5 | \title{Download a specified version of a CRAN package} 6 | \usage{ 7 | download_version( 8 | package, 9 | version = NULL, 10 | repos = getOption("repos"), 11 | type = getOption("pkgType"), 12 | ... 13 | ) 14 | } 15 | \arguments{ 16 | \item{package}{Name of the package to install.} 17 | 18 | \item{version}{Version of the package to install. Can either be a string giving the exact 19 | version required, or a specification in the same format as the parenthesized expressions used 20 | in package dependencies. One of the following formats: 21 | \itemize{ 22 | \item An exact version required, as a string, e.g. \code{"0.1.13"} 23 | \item A comparison operator and a version, e.g. \code{">= 0.1.12"} 24 | \item Several criteria to satisfy, as a comma-separated string, e.g. \code{">= 1.12.0, < 1.14"} 25 | \item Several criteria to satisfy, as elements of a character vector, e.g. \code{c(">= 1.12.0", "< 1.14")} 26 | }} 27 | 28 | \item{repos}{ 29 | character vector, the base URL(s) of the repositories 30 | to use, e.g., the URL of a CRAN mirror such as 31 | \code{"https://cloud.r-project.org"}. For more details on 32 | supported URL schemes see \code{\link{url}}. 33 | 34 | Can be \code{NULL} to install from local files, directories or URLs: 35 | this will be inferred by extension from \code{pkgs} if of length one. 36 | } 37 | 38 | \item{type}{character, indicating the type of package to download and 39 | install. Will be \code{"source"} except on Windows and some macOS 40 | builds: see the section on \sQuote{Binary packages} for those. 41 | } 42 | 43 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 44 | } 45 | \value{ 46 | Name of the downloaded file. 47 | } 48 | \description{ 49 | It downloads the package to a temporary file, and 50 | returns the name of the file. 51 | } 52 | -------------------------------------------------------------------------------- /man/git_credentials.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-git.R 3 | \name{git_credentials} 4 | \alias{git_credentials} 5 | \title{Specify git credentials to use} 6 | \usage{ 7 | git_credentials() 8 | } 9 | \description{ 10 | The global option \code{remotes.git_credentials} is used to set the git 11 | credentials. 12 | } 13 | \keyword{internal} 14 | -------------------------------------------------------------------------------- /man/github_refs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-github.R 3 | \name{github_pull} 4 | \alias{github_pull} 5 | \alias{github_release} 6 | \title{GitHub references} 7 | \usage{ 8 | github_pull(pull) 9 | 10 | github_release() 11 | } 12 | \arguments{ 13 | \item{pull}{Character string specifying the pull request to install} 14 | } 15 | \description{ 16 | Use as \code{ref} parameter to \code{\link[=install_github]{install_github()}}. 17 | Allows installing a specific pull request or the latest release. 18 | } 19 | \examples{ 20 | github_pull("42") 21 | } 22 | \seealso{ 23 | \code{\link[=install_github]{install_github()}} 24 | } 25 | -------------------------------------------------------------------------------- /man/github_remote.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-github.R 3 | \name{github_remote} 4 | \alias{github_remote} 5 | \title{Create a new github_remote} 6 | \usage{ 7 | github_remote( 8 | repo, 9 | ref = "HEAD", 10 | subdir = NULL, 11 | auth_token = github_pat(), 12 | sha = NULL, 13 | host = "api.github.com", 14 | ... 15 | ) 16 | } 17 | \arguments{ 18 | \item{repo}{Repository address in the format 19 | \verb{username/repo[/subdir][@ref|#pull|@*release]}. Alternatively, you can 20 | specify \code{subdir} and/or \code{ref} using the respective parameters 21 | (see below); if both are specified, the values in \code{repo} take 22 | precedence.} 23 | 24 | \item{ref}{Desired git reference. Could be a commit, tag, or branch 25 | name, or a call to \code{\link[=github_pull]{github_pull()}} or \code{\link[=github_release]{github_release()}}. Defaults to 26 | \code{"HEAD"}, which means the default branch on GitHub and for git remotes. 27 | See \href{https://help.github.com/en/github/administering-a-repository/setting-the-default-branch}{setting-the-default-branch} 28 | for more details.} 29 | 30 | \item{subdir}{Subdirectory within repo that contains the R package.} 31 | 32 | \item{auth_token}{To install from a private repo, generate a personal 33 | access token (PAT) with at least repo scope in 34 | \url{https://github.com/settings/tokens} and 35 | supply to this argument. This is safer than using a password because 36 | you can easily delete a PAT without affecting any others. Defaults to 37 | the \code{GITHUB_PAT} environment variable.} 38 | 39 | \item{host}{GitHub API host to use. Override with your GitHub enterprise 40 | hostname, for example, \code{"github.hostname.com/api/v3"}.} 41 | 42 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 43 | } 44 | \description{ 45 | This is an internal function to create a new github_remote, users should 46 | generally have no need for it. 47 | } 48 | \keyword{internal} 49 | -------------------------------------------------------------------------------- /man/gitlab_pat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-gitlab.R 3 | \name{gitlab_pat} 4 | \alias{gitlab_pat} 5 | \title{Retrieve GitLab personal access token.} 6 | \usage{ 7 | gitlab_pat(quiet = TRUE) 8 | } 9 | \description{ 10 | A GitLab personal access token 11 | Looks in env var \code{GITLAB_PAT} 12 | } 13 | \keyword{internal} 14 | -------------------------------------------------------------------------------- /man/install_bioc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-bioc.R 3 | \name{install_bioc} 4 | \alias{install_bioc} 5 | \title{Install a development package from the Bioconductor git repository} 6 | \usage{ 7 | install_bioc( 8 | repo, 9 | mirror = getOption("BioC_git", download_url("git.bioconductor.org/packages")), 10 | git = c("auto", "git2r", "external"), 11 | dependencies = NA, 12 | upgrade = c("default", "ask", "always", "never"), 13 | force = FALSE, 14 | quiet = FALSE, 15 | build = TRUE, 16 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 17 | build_manual = FALSE, 18 | build_vignettes = FALSE, 19 | repos = getOption("repos"), 20 | type = getOption("pkgType"), 21 | ... 22 | ) 23 | } 24 | \arguments{ 25 | \item{repo}{Repository address in the format 26 | \verb{[username:password@][release/]repo[#commit]}. Valid values for 27 | the release are \sQuote{devel}, 28 | \sQuote{release} (the default if none specified), or numeric release 29 | numbers (e.g. \sQuote{3.3}).} 30 | 31 | \item{mirror}{The Bioconductor git mirror to use} 32 | 33 | \item{git}{Whether to use the \code{git2r} package, or an external 34 | git client via system. Default is \code{git2r} if it is installed, 35 | otherwise an external git installation.} 36 | 37 | \item{dependencies}{Which dependencies do you want to check? 38 | Can be a character vector (selecting from "Depends", "Imports", 39 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 40 | 41 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 42 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 43 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 44 | just check this package, not its dependencies). 45 | 46 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 47 | 48 | You can also specify dependencies from one or more additional fields, 49 | common ones include: 50 | \itemize{ 51 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 52 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 53 | }} 54 | 55 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 56 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 57 | and falls back to "ask" if unset. "ask" prompts the user for which out of 58 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 59 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 60 | "always" and "never" respectively.} 61 | 62 | \item{force}{Force installation, even if the remote state has not changed 63 | since the previous install.} 64 | 65 | \item{quiet}{If \code{TRUE}, suppress output.} 66 | 67 | \item{build}{If \code{TRUE} build the package before installing.} 68 | 69 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 70 | 71 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 72 | 73 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 74 | 75 | \item{repos}{A character vector giving repositories to use.} 76 | 77 | \item{type}{Type of package to \code{update}.} 78 | 79 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 80 | } 81 | \description{ 82 | This function requires \code{git} to be installed on your system in order to 83 | be used. 84 | } 85 | \details{ 86 | It is vectorised so you can install multiple packages with 87 | a single command. 88 | 89 | This is intended as an aid for Bioconductor developers. If you want to 90 | install the release version of a Bioconductor package one can use the 91 | \code{BiocManager} package. 92 | } 93 | \examples{ 94 | \dontrun{ 95 | install_bioc("SummarizedExperiment") 96 | install_bioc("devel/SummarizedExperiment") 97 | install_bioc("3.3/SummarizedExperiment") 98 | install_bioc("SummarizedExperiment#abc123") 99 | install_bioc("user:password@release/SummarizedExperiment") 100 | install_bioc("user:password@devel/SummarizedExperiment") 101 | install_bioc("user:password@SummarizedExperiment#abc123") 102 | } 103 | } 104 | \seealso{ 105 | Other package installation: 106 | \code{\link{install_bitbucket}()}, 107 | \code{\link{install_cran}()}, 108 | \code{\link{install_dev}()}, 109 | \code{\link{install_github}()}, 110 | \code{\link{install_gitlab}()}, 111 | \code{\link{install_git}()}, 112 | \code{\link{install_local}()}, 113 | \code{\link{install_svn}()}, 114 | \code{\link{install_url}()}, 115 | \code{\link{install_version}()} 116 | } 117 | \concept{package installation} 118 | -------------------------------------------------------------------------------- /man/install_cran.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-cran.R 3 | \name{install_cran} 4 | \alias{install_cran} 5 | \title{Attempts to install a package from CRAN.} 6 | \usage{ 7 | install_cran( 8 | pkgs, 9 | repos = getOption("repos"), 10 | type = getOption("pkgType"), 11 | dependencies = NA, 12 | upgrade = c("default", "ask", "always", "never"), 13 | force = FALSE, 14 | quiet = FALSE, 15 | build = TRUE, 16 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 17 | build_manual = FALSE, 18 | build_vignettes = FALSE, 19 | ... 20 | ) 21 | } 22 | \arguments{ 23 | \item{pkgs}{A character vector of packages to install.} 24 | 25 | \item{repos}{A character vector giving repositories to use.} 26 | 27 | \item{type}{Type of package to \code{update}.} 28 | 29 | \item{dependencies}{Which dependencies do you want to check? 30 | Can be a character vector (selecting from "Depends", "Imports", 31 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 32 | 33 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 34 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 35 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 36 | just check this package, not its dependencies). 37 | 38 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 39 | 40 | You can also specify dependencies from one or more additional fields, 41 | common ones include: 42 | \itemize{ 43 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 44 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 45 | }} 46 | 47 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 48 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 49 | and falls back to "ask" if unset. "ask" prompts the user for which out of 50 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 51 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 52 | "always" and "never" respectively.} 53 | 54 | \item{force}{Force installation, even if the remote state has not changed 55 | since the previous install.} 56 | 57 | \item{quiet}{If \code{TRUE}, suppress output.} 58 | 59 | \item{build}{If \code{TRUE} build the package before installing.} 60 | 61 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 62 | 63 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 64 | 65 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 66 | 67 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 68 | } 69 | \description{ 70 | This function is vectorised on \code{pkgs} so you can install multiple 71 | packages in a single command. 72 | } 73 | \examples{ 74 | \dontrun{ 75 | install_cran("ggplot2") 76 | install_cran(c("httpuv", "shiny")) 77 | } 78 | } 79 | \seealso{ 80 | Other package installation: 81 | \code{\link{install_bioc}()}, 82 | \code{\link{install_bitbucket}()}, 83 | \code{\link{install_dev}()}, 84 | \code{\link{install_github}()}, 85 | \code{\link{install_gitlab}()}, 86 | \code{\link{install_git}()}, 87 | \code{\link{install_local}()}, 88 | \code{\link{install_svn}()}, 89 | \code{\link{install_url}()}, 90 | \code{\link{install_version}()} 91 | } 92 | \concept{package installation} 93 | -------------------------------------------------------------------------------- /man/install_deps.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install.R 3 | \name{install_deps} 4 | \alias{install_deps} 5 | \title{Install package dependencies if needed.} 6 | \usage{ 7 | install_deps( 8 | pkgdir = ".", 9 | dependencies = NA, 10 | repos = getOption("repos"), 11 | type = getOption("pkgType"), 12 | upgrade = c("default", "ask", "always", "never"), 13 | quiet = FALSE, 14 | build = TRUE, 15 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 16 | build_manual = FALSE, 17 | build_vignettes = FALSE, 18 | ... 19 | ) 20 | } 21 | \arguments{ 22 | \item{pkgdir}{Path to a package directory, or to a package tarball.} 23 | 24 | \item{dependencies}{Which dependencies do you want to check? 25 | Can be a character vector (selecting from "Depends", "Imports", 26 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 27 | 28 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 29 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 30 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 31 | just check this package, not its dependencies). 32 | 33 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 34 | 35 | You can also specify dependencies from one or more additional fields, 36 | common ones include: 37 | \itemize{ 38 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 39 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 40 | }} 41 | 42 | \item{repos}{A character vector giving repositories to use.} 43 | 44 | \item{type}{Type of package to \code{update}.} 45 | 46 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 47 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 48 | and falls back to "ask" if unset. "ask" prompts the user for which out of 49 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 50 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 51 | "always" and "never" respectively.} 52 | 53 | \item{quiet}{If \code{TRUE}, suppress output.} 54 | 55 | \item{build}{If \code{TRUE} build the package before installing.} 56 | 57 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 58 | 59 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 60 | 61 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 62 | 63 | \item{...}{additional arguments passed to \code{\link[utils:install.packages]{utils::install.packages()}}.} 64 | } 65 | \description{ 66 | Install package dependencies if needed. 67 | } 68 | \examples{ 69 | \dontrun{install_deps(".")} 70 | } 71 | -------------------------------------------------------------------------------- /man/install_dev.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-dev.R 3 | \name{install_dev} 4 | \alias{install_dev} 5 | \title{Install the development version of a package} 6 | \usage{ 7 | install_dev(package, cran_url = getOption("repos")[["CRAN"]], ...) 8 | } 9 | \arguments{ 10 | \item{package}{The package name to install.} 11 | 12 | \item{cran_url}{The URL of the CRAN mirror to use, by default based on the 13 | 'repos' option. If unset uses 'https://cloud.r-project.org'.} 14 | 15 | \item{...}{Additional arguments passed to \code{\link[=install_github]{install_github()}}, 16 | \code{\link[=install_gitlab]{install_gitlab()}}, or \code{\link[=install_bitbucket]{install_bitbucket()}} functions.} 17 | } 18 | \description{ 19 | \code{install_dev()} retrieves the package DESCRIPTION from the CRAN mirror and 20 | looks in the 'URL' and 'BugReports' fields for GitHub, GitLab or Bitbucket 21 | URLs. It then calls the appropriate \code{install_()} function to install the 22 | development package. 23 | } 24 | \examples{ 25 | \dontrun{ 26 | # From GitHub 27 | install_dev("dplyr") 28 | 29 | # From GitLab 30 | install_dev("iemiscdata") 31 | 32 | # From Bitbucket 33 | install_dev("argparser") 34 | } 35 | } 36 | \seealso{ 37 | Other package installation: 38 | \code{\link{install_bioc}()}, 39 | \code{\link{install_bitbucket}()}, 40 | \code{\link{install_cran}()}, 41 | \code{\link{install_github}()}, 42 | \code{\link{install_gitlab}()}, 43 | \code{\link{install_git}()}, 44 | \code{\link{install_local}()}, 45 | \code{\link{install_svn}()}, 46 | \code{\link{install_url}()}, 47 | \code{\link{install_version}()} 48 | } 49 | \concept{package installation} 50 | -------------------------------------------------------------------------------- /man/install_git.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-git.R 3 | \name{install_git} 4 | \alias{install_git} 5 | \title{Install a package from a git repository} 6 | \usage{ 7 | install_git( 8 | url, 9 | subdir = NULL, 10 | ref = NULL, 11 | branch = NULL, 12 | credentials = git_credentials(), 13 | git = c("auto", "git2r", "external"), 14 | dependencies = NA, 15 | upgrade = c("default", "ask", "always", "never"), 16 | force = FALSE, 17 | quiet = FALSE, 18 | build = TRUE, 19 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 20 | build_manual = FALSE, 21 | build_vignettes = FALSE, 22 | repos = getOption("repos"), 23 | type = getOption("pkgType"), 24 | ... 25 | ) 26 | } 27 | \arguments{ 28 | \item{url}{Location of package. The url should point to a public or 29 | private repository.} 30 | 31 | \item{subdir}{A sub-directory within a git repository that may 32 | contain the package we are interested in installing.} 33 | 34 | \item{ref}{Name of branch, tag or SHA reference to use, if not HEAD.} 35 | 36 | \item{branch}{Deprecated, synonym for ref.} 37 | 38 | \item{credentials}{A git2r credentials object passed through to clone. 39 | Supplying this argument implies using \code{git2r} with \code{git}.} 40 | 41 | \item{git}{Whether to use the \code{git2r} package, or an external 42 | git client via system. Default is \code{git2r} if it is installed, 43 | otherwise an external git installation.} 44 | 45 | \item{dependencies}{Which dependencies do you want to check? 46 | Can be a character vector (selecting from "Depends", "Imports", 47 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 48 | 49 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 50 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 51 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 52 | just check this package, not its dependencies). 53 | 54 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 55 | 56 | You can also specify dependencies from one or more additional fields, 57 | common ones include: 58 | \itemize{ 59 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 60 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 61 | }} 62 | 63 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 64 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 65 | and falls back to "ask" if unset. "ask" prompts the user for which out of 66 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 67 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 68 | "always" and "never" respectively.} 69 | 70 | \item{force}{Force installation, even if the remote state has not changed 71 | since the previous install.} 72 | 73 | \item{quiet}{If \code{TRUE}, suppress output.} 74 | 75 | \item{build}{If \code{TRUE} build the package before installing.} 76 | 77 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 78 | 79 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 80 | 81 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 82 | 83 | \item{repos}{A character vector giving repositories to use.} 84 | 85 | \item{type}{Type of package to \code{update}.} 86 | 87 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 88 | } 89 | \description{ 90 | It is vectorised so you can install multiple packages with 91 | a single command. You do not need to have the \code{git2r} package, 92 | or an external git client installed. 93 | } 94 | \details{ 95 | If you need to set git credentials for use in the \code{Remotes} field you can do 96 | so by placing the credentials in the \code{remotes.git_credentials} global 97 | option. 98 | } 99 | \examples{ 100 | \dontrun{ 101 | install_git("https://github.com/hadley/stringr.git") 102 | install_git("https://github.com/hadley/stringr.git", ref = "stringr-0.2") 103 | } 104 | } 105 | \seealso{ 106 | Other package installation: 107 | \code{\link{install_bioc}()}, 108 | \code{\link{install_bitbucket}()}, 109 | \code{\link{install_cran}()}, 110 | \code{\link{install_dev}()}, 111 | \code{\link{install_github}()}, 112 | \code{\link{install_gitlab}()}, 113 | \code{\link{install_local}()}, 114 | \code{\link{install_svn}()}, 115 | \code{\link{install_url}()}, 116 | \code{\link{install_version}()} 117 | } 118 | \concept{package installation} 119 | -------------------------------------------------------------------------------- /man/install_github.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-github.R 3 | \name{install_github} 4 | \alias{install_github} 5 | \title{Attempts to install a package directly from GitHub.} 6 | \usage{ 7 | install_github( 8 | repo, 9 | ref = "HEAD", 10 | subdir = NULL, 11 | auth_token = github_pat(quiet), 12 | host = "api.github.com", 13 | dependencies = NA, 14 | upgrade = c("default", "ask", "always", "never"), 15 | force = FALSE, 16 | quiet = FALSE, 17 | build = TRUE, 18 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 19 | build_manual = FALSE, 20 | build_vignettes = FALSE, 21 | repos = getOption("repos"), 22 | type = getOption("pkgType"), 23 | ... 24 | ) 25 | } 26 | \arguments{ 27 | \item{repo}{Repository address in the format 28 | \verb{username/repo[/subdir][@ref|#pull|@*release]}. Alternatively, you can 29 | specify \code{subdir} and/or \code{ref} using the respective parameters 30 | (see below); if both are specified, the values in \code{repo} take 31 | precedence.} 32 | 33 | \item{ref}{Desired git reference. Could be a commit, tag, or branch 34 | name, or a call to \code{\link[=github_pull]{github_pull()}} or \code{\link[=github_release]{github_release()}}. Defaults to 35 | \code{"HEAD"}, which means the default branch on GitHub and for git remotes. 36 | See \href{https://help.github.com/en/github/administering-a-repository/setting-the-default-branch}{setting-the-default-branch} 37 | for more details.} 38 | 39 | \item{subdir}{Subdirectory within repo that contains the R package.} 40 | 41 | \item{auth_token}{To install from a private repo, generate a personal 42 | access token (PAT) with at least repo scope in 43 | \url{https://github.com/settings/tokens} and 44 | supply to this argument. This is safer than using a password because 45 | you can easily delete a PAT without affecting any others. Defaults to 46 | the \code{GITHUB_PAT} environment variable.} 47 | 48 | \item{host}{GitHub API host to use. Override with your GitHub enterprise 49 | hostname, for example, \code{"github.hostname.com/api/v3"}.} 50 | 51 | \item{dependencies}{Which dependencies do you want to check? 52 | Can be a character vector (selecting from "Depends", "Imports", 53 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 54 | 55 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 56 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 57 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 58 | just check this package, not its dependencies). 59 | 60 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 61 | 62 | You can also specify dependencies from one or more additional fields, 63 | common ones include: 64 | \itemize{ 65 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 66 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 67 | }} 68 | 69 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 70 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 71 | and falls back to "ask" if unset. "ask" prompts the user for which out of 72 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 73 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 74 | "always" and "never" respectively.} 75 | 76 | \item{force}{Force installation, even if the remote state has not changed 77 | since the previous install.} 78 | 79 | \item{quiet}{If \code{TRUE}, suppress output.} 80 | 81 | \item{build}{If \code{TRUE} build the package before installing.} 82 | 83 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 84 | 85 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 86 | 87 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 88 | 89 | \item{repos}{A character vector giving repositories to use.} 90 | 91 | \item{type}{Type of package to \code{update}.} 92 | 93 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 94 | } 95 | \description{ 96 | This function is vectorised on \code{repo} so you can install multiple 97 | packages in a single command. 98 | } 99 | \details{ 100 | If the repository uses submodules a command-line git client is required to 101 | clone the submodules. 102 | } 103 | \examples{ 104 | \dontrun{ 105 | install_github("klutometis/roxygen") 106 | install_github("wch/ggplot2", ref = github_pull("142")) 107 | install_github(c("rstudio/httpuv", "rstudio/shiny")) 108 | install_github(c("hadley/httr@v0.4", "klutometis/roxygen#142", 109 | "r-lib/roxygen2@*release", "mfrasca/r-logging/pkg")) 110 | 111 | # To install from a private repo, use auth_token with a token 112 | # from https://github.com/settings/tokens. You only need the 113 | # repo scope. Best practice is to save your PAT in env var called 114 | # GITHUB_PAT. 115 | install_github("hadley/private", auth_token = "abc") 116 | 117 | # To pass option arguments to `R CMD INSTALL` use `INSTALL_opts`. e.g. to 118 | install a package with source references and tests 119 | install_github("rstudio/shiny", INSTALL_opts = c("--with-keep.source", "--install-tests")) 120 | } 121 | } 122 | \seealso{ 123 | \code{\link[=github_pull]{github_pull()}} 124 | 125 | Other package installation: 126 | \code{\link{install_bioc}()}, 127 | \code{\link{install_bitbucket}()}, 128 | \code{\link{install_cran}()}, 129 | \code{\link{install_dev}()}, 130 | \code{\link{install_gitlab}()}, 131 | \code{\link{install_git}()}, 132 | \code{\link{install_local}()}, 133 | \code{\link{install_svn}()}, 134 | \code{\link{install_url}()}, 135 | \code{\link{install_version}()} 136 | } 137 | \concept{package installation} 138 | -------------------------------------------------------------------------------- /man/install_gitlab.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-gitlab.R 3 | \name{install_gitlab} 4 | \alias{install_gitlab} 5 | \title{Install a package from GitLab} 6 | \usage{ 7 | install_gitlab( 8 | repo, 9 | subdir = NULL, 10 | auth_token = gitlab_pat(quiet), 11 | host = "gitlab.com", 12 | dependencies = NA, 13 | upgrade = c("default", "ask", "always", "never"), 14 | force = FALSE, 15 | quiet = FALSE, 16 | build = TRUE, 17 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 18 | build_manual = FALSE, 19 | build_vignettes = FALSE, 20 | repos = getOption("repos"), 21 | type = getOption("pkgType"), 22 | ... 23 | ) 24 | } 25 | \arguments{ 26 | \item{repo}{Repository address in the format 27 | \verb{username/repo[@ref]}.} 28 | 29 | \item{subdir}{Subdirectory within repo that contains the R package.} 30 | 31 | \item{auth_token}{To install from a private repo, generate a personal access 32 | token (PAT) with at least read_api scope in 33 | \url{https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html} and 34 | supply to this argument. This is safer than using a password because you 35 | can easily delete a PAT without affecting any others. Defaults to the 36 | GITLAB_PAT environment variable.} 37 | 38 | \item{host}{GitLab API host to use. Override with your GitLab enterprise 39 | hostname, for example, \code{"gitlab.hostname.com"}. 40 | The PROTOCOL is required by packrat during Posit Connect deployment. While 41 | \link{install_gitlab} may work without, omitting it generally 42 | leads to package restoration errors.} 43 | 44 | \item{dependencies}{Which dependencies do you want to check? 45 | Can be a character vector (selecting from "Depends", "Imports", 46 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 47 | 48 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 49 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 50 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 51 | just check this package, not its dependencies). 52 | 53 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 54 | 55 | You can also specify dependencies from one or more additional fields, 56 | common ones include: 57 | \itemize{ 58 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 59 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 60 | }} 61 | 62 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 63 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 64 | and falls back to "ask" if unset. "ask" prompts the user for which out of 65 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 66 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 67 | "always" and "never" respectively.} 68 | 69 | \item{force}{Force installation, even if the remote state has not changed 70 | since the previous install.} 71 | 72 | \item{quiet}{If \code{TRUE}, suppress output.} 73 | 74 | \item{build}{If \code{TRUE} build the package before installing.} 75 | 76 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 77 | 78 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 79 | 80 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 81 | 82 | \item{repos}{A character vector giving repositories to use.} 83 | 84 | \item{type}{Type of package to \code{update}.} 85 | 86 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 87 | } 88 | \description{ 89 | This function is vectorised on \code{repo} so you can install multiple 90 | packages in a single command. Like other remotes the repository will skip 91 | installation if \code{force == FALSE} (the default) and the remote state has 92 | not changed since the previous installation. 93 | } 94 | \examples{ 95 | \dontrun{ 96 | install_gitlab("jimhester/covr") 97 | } 98 | } 99 | \seealso{ 100 | Other package installation: 101 | \code{\link{install_bioc}()}, 102 | \code{\link{install_bitbucket}()}, 103 | \code{\link{install_cran}()}, 104 | \code{\link{install_dev}()}, 105 | \code{\link{install_github}()}, 106 | \code{\link{install_git}()}, 107 | \code{\link{install_local}()}, 108 | \code{\link{install_svn}()}, 109 | \code{\link{install_url}()}, 110 | \code{\link{install_version}()} 111 | } 112 | \concept{package installation} 113 | -------------------------------------------------------------------------------- /man/install_local.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-local.R 3 | \name{install_local} 4 | \alias{install_local} 5 | \title{Install a package from a local file} 6 | \usage{ 7 | install_local( 8 | path = ".", 9 | subdir = NULL, 10 | dependencies = NA, 11 | upgrade = c("default", "ask", "always", "never"), 12 | force = FALSE, 13 | quiet = FALSE, 14 | build = !is_binary_pkg(path), 15 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 16 | build_manual = FALSE, 17 | build_vignettes = FALSE, 18 | repos = getOption("repos"), 19 | type = getOption("pkgType"), 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{path}{path to local directory, or compressed file (tar, zip, tar.gz 25 | tar.bz2, tgz2 or tbz)} 26 | 27 | \item{subdir}{subdirectory within url bundle that contains the R package.} 28 | 29 | \item{dependencies}{Which dependencies do you want to check? 30 | Can be a character vector (selecting from "Depends", "Imports", 31 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 32 | 33 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 34 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 35 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 36 | just check this package, not its dependencies). 37 | 38 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 39 | 40 | You can also specify dependencies from one or more additional fields, 41 | common ones include: 42 | \itemize{ 43 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 44 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 45 | }} 46 | 47 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 48 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 49 | and falls back to "ask" if unset. "ask" prompts the user for which out of 50 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 51 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 52 | "always" and "never" respectively.} 53 | 54 | \item{force}{Force installation, even if the remote state has not changed 55 | since the previous install.} 56 | 57 | \item{quiet}{If \code{TRUE}, suppress output.} 58 | 59 | \item{build}{If \code{TRUE} build the package before installing.} 60 | 61 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 62 | 63 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 64 | 65 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 66 | 67 | \item{repos}{A character vector giving repositories to use.} 68 | 69 | \item{type}{Type of package to \code{update}.} 70 | 71 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 72 | } 73 | \description{ 74 | This function is vectorised so you can install multiple packages in 75 | a single command. 76 | } 77 | \examples{ 78 | \dontrun{ 79 | dir <- tempfile() 80 | dir.create(dir) 81 | pkg <- download.packages("testthat", dir, type = "source") 82 | install_local(pkg[, 2]) 83 | } 84 | } 85 | \seealso{ 86 | Other package installation: 87 | \code{\link{install_bioc}()}, 88 | \code{\link{install_bitbucket}()}, 89 | \code{\link{install_cran}()}, 90 | \code{\link{install_dev}()}, 91 | \code{\link{install_github}()}, 92 | \code{\link{install_gitlab}()}, 93 | \code{\link{install_git}()}, 94 | \code{\link{install_svn}()}, 95 | \code{\link{install_url}()}, 96 | \code{\link{install_version}()} 97 | } 98 | \concept{package installation} 99 | -------------------------------------------------------------------------------- /man/install_remote.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-remote.R 3 | \name{install_remote} 4 | \alias{install_remote} 5 | \alias{add_metadata} 6 | \alias{remote_download} 7 | \alias{remote_metadata} 8 | \alias{remote_package_name} 9 | \alias{remote_sha} 10 | \title{Install a remote package.} 11 | \usage{ 12 | install_remote( 13 | remote, 14 | dependencies, 15 | upgrade, 16 | force, 17 | quiet, 18 | build, 19 | build_opts, 20 | build_manual, 21 | build_vignettes, 22 | repos, 23 | type, 24 | ... 25 | ) 26 | 27 | add_metadata(pkg_path, meta) 28 | 29 | remote_download(x, quiet = FALSE) 30 | 31 | remote_metadata(x, bundle = NULL, source = NULL, sha = NULL) 32 | 33 | remote_package_name(remote, ...) 34 | 35 | remote_sha(remote, ...) 36 | } 37 | \arguments{ 38 | \item{dependencies}{Which dependencies do you want to check? 39 | Can be a character vector (selecting from "Depends", "Imports", 40 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 41 | 42 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 43 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 44 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 45 | just check this package, not its dependencies). 46 | 47 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 48 | 49 | You can also specify dependencies from one or more additional fields, 50 | common ones include: 51 | \itemize{ 52 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 53 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 54 | }} 55 | 56 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 57 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 58 | and falls back to "ask" if unset. "ask" prompts the user for which out of 59 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 60 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 61 | "always" and "never" respectively.} 62 | 63 | \item{force}{Force installation, even if the remote state has not changed 64 | since the previous install.} 65 | 66 | \item{quiet}{If \code{TRUE}, suppress output.} 67 | 68 | \item{build}{If \code{TRUE} build the package before installing.} 69 | 70 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 71 | 72 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 73 | 74 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 75 | 76 | \item{repos}{A character vector giving repositories to use.} 77 | 78 | \item{type}{Type of package to \code{update}.} 79 | 80 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 81 | } 82 | \description{ 83 | This: 84 | \enumerate{ 85 | \item downloads source bundle 86 | \item decompresses & checks that it's a package 87 | \item adds metadata to DESCRIPTION 88 | \item calls install 89 | } 90 | } 91 | \details{ 92 | It uses the additional S3 generic functions to work. Writing methods for 93 | these functions would allow 3rd party packages to define custom remotes. 94 | } 95 | \keyword{internal} 96 | -------------------------------------------------------------------------------- /man/install_svn.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-svn.R 3 | \name{install_svn} 4 | \alias{install_svn} 5 | \title{Install a package from a SVN repository} 6 | \usage{ 7 | install_svn( 8 | url, 9 | subdir = NULL, 10 | args = character(0), 11 | revision = NULL, 12 | dependencies = NA, 13 | upgrade = c("default", "ask", "always", "never"), 14 | force = FALSE, 15 | quiet = FALSE, 16 | build = TRUE, 17 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 18 | build_manual = FALSE, 19 | build_vignettes = FALSE, 20 | repos = getOption("repos"), 21 | type = getOption("pkgType"), 22 | ... 23 | ) 24 | } 25 | \arguments{ 26 | \item{url}{Location of package. The url should point to a public or 27 | private repository.} 28 | 29 | \item{subdir}{A sub-directory within a svn repository that contains the 30 | package we are interested in installing.} 31 | 32 | \item{args}{A character vector providing extra options to pass on to 33 | \command{svn}.} 34 | 35 | \item{revision}{svn revision, if omitted updates to latest} 36 | 37 | \item{dependencies}{Which dependencies do you want to check? 38 | Can be a character vector (selecting from "Depends", "Imports", 39 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 40 | 41 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 42 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 43 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 44 | just check this package, not its dependencies). 45 | 46 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 47 | 48 | You can also specify dependencies from one or more additional fields, 49 | common ones include: 50 | \itemize{ 51 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 52 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 53 | }} 54 | 55 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 56 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 57 | and falls back to "ask" if unset. "ask" prompts the user for which out of 58 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 59 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 60 | "always" and "never" respectively.} 61 | 62 | \item{force}{Force installation, even if the remote state has not changed 63 | since the previous install.} 64 | 65 | \item{quiet}{If \code{TRUE}, suppress output.} 66 | 67 | \item{build}{If \code{TRUE} build the package before installing.} 68 | 69 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 70 | 71 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 72 | 73 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 74 | 75 | \item{repos}{A character vector giving repositories to use.} 76 | 77 | \item{type}{Type of package to \code{update}.} 78 | 79 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 80 | } 81 | \description{ 82 | This function requires \command{svn} to be installed on your system in order to 83 | be used. 84 | } 85 | \details{ 86 | It is vectorised so you can install multiple packages with 87 | a single command. 88 | } 89 | \examples{ 90 | \dontrun{ 91 | install_svn("https://github.com/hadley/stringr/trunk") 92 | install_svn("https://github.com/hadley/httr/branches/oauth") 93 | } 94 | } 95 | \seealso{ 96 | Other package installation: 97 | \code{\link{install_bioc}()}, 98 | \code{\link{install_bitbucket}()}, 99 | \code{\link{install_cran}()}, 100 | \code{\link{install_dev}()}, 101 | \code{\link{install_github}()}, 102 | \code{\link{install_gitlab}()}, 103 | \code{\link{install_git}()}, 104 | \code{\link{install_local}()}, 105 | \code{\link{install_url}()}, 106 | \code{\link{install_version}()} 107 | } 108 | \concept{package installation} 109 | -------------------------------------------------------------------------------- /man/install_url.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-url.R 3 | \name{install_url} 4 | \alias{install_url} 5 | \title{Install a package from a url} 6 | \usage{ 7 | install_url( 8 | url, 9 | subdir = NULL, 10 | dependencies = NA, 11 | upgrade = c("default", "ask", "always", "never"), 12 | force = FALSE, 13 | quiet = FALSE, 14 | build = TRUE, 15 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 16 | build_manual = FALSE, 17 | build_vignettes = FALSE, 18 | repos = getOption("repos"), 19 | type = getOption("pkgType"), 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{url}{location of package on internet. The url should point to a 25 | zip file, a tar file or a bzipped/gzipped tar file.} 26 | 27 | \item{subdir}{subdirectory within url bundle that contains the R package.} 28 | 29 | \item{dependencies}{Which dependencies do you want to check? 30 | Can be a character vector (selecting from "Depends", "Imports", 31 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 32 | 33 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 34 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 35 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 36 | just check this package, not its dependencies). 37 | 38 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 39 | 40 | You can also specify dependencies from one or more additional fields, 41 | common ones include: 42 | \itemize{ 43 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 44 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 45 | }} 46 | 47 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 48 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 49 | and falls back to "ask" if unset. "ask" prompts the user for which out of 50 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 51 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 52 | "always" and "never" respectively.} 53 | 54 | \item{force}{Force installation, even if the remote state has not changed 55 | since the previous install.} 56 | 57 | \item{quiet}{If \code{TRUE}, suppress output.} 58 | 59 | \item{build}{If \code{TRUE} build the package before installing.} 60 | 61 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 62 | 63 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 64 | 65 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 66 | 67 | \item{repos}{A character vector giving repositories to use.} 68 | 69 | \item{type}{Type of package to \code{update}.} 70 | 71 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 72 | } 73 | \description{ 74 | This function is vectorised so you can install multiple packages in 75 | a single command. 76 | } 77 | \examples{ 78 | \dontrun{ 79 | install_url("https://github.com/hadley/stringr/archive/HEAD.zip") 80 | } 81 | } 82 | \seealso{ 83 | Other package installation: 84 | \code{\link{install_bioc}()}, 85 | \code{\link{install_bitbucket}()}, 86 | \code{\link{install_cran}()}, 87 | \code{\link{install_dev}()}, 88 | \code{\link{install_github}()}, 89 | \code{\link{install_gitlab}()}, 90 | \code{\link{install_git}()}, 91 | \code{\link{install_local}()}, 92 | \code{\link{install_svn}()}, 93 | \code{\link{install_version}()} 94 | } 95 | \concept{package installation} 96 | -------------------------------------------------------------------------------- /man/package_deps.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deps.R 3 | \name{package_deps} 4 | \alias{package_deps} 5 | \alias{local_package_deps} 6 | \alias{dev_package_deps} 7 | \alias{update.package_deps} 8 | \title{Find all dependencies of a CRAN or dev package.} 9 | \usage{ 10 | package_deps( 11 | packages, 12 | dependencies = NA, 13 | repos = getOption("repos"), 14 | type = getOption("pkgType") 15 | ) 16 | 17 | local_package_deps(pkgdir = ".", dependencies = NA) 18 | 19 | dev_package_deps( 20 | pkgdir = ".", 21 | dependencies = NA, 22 | repos = getOption("repos"), 23 | type = getOption("pkgType"), 24 | remote_precedence = TRUE, 25 | additional_repositories = TRUE 26 | ) 27 | 28 | \method{update}{package_deps}( 29 | object, 30 | dependencies = NA, 31 | upgrade = c("default", "ask", "always", "never"), 32 | force = FALSE, 33 | quiet = FALSE, 34 | build = TRUE, 35 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 36 | build_manual = FALSE, 37 | build_vignettes = FALSE, 38 | repos = getOption("repos"), 39 | type = getOption("pkgType"), 40 | ... 41 | ) 42 | } 43 | \arguments{ 44 | \item{packages}{A character vector of package names.} 45 | 46 | \item{dependencies}{Which dependencies do you want to check? 47 | Can be a character vector (selecting from "Depends", "Imports", 48 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 49 | 50 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 51 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 52 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 53 | just check this package, not its dependencies). 54 | 55 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 56 | 57 | You can also specify dependencies from one or more additional fields, 58 | common ones include: 59 | \itemize{ 60 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 61 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 62 | }} 63 | 64 | \item{repos}{A character vector giving repositories to use.} 65 | 66 | \item{type}{Type of package to \code{update}.} 67 | 68 | \item{pkgdir}{Path to a package directory, or to a package tarball.} 69 | 70 | \item{remote_precedence}{A logical flag specifying whether remote sources should take precedence over 71 | CRAN when both were found.} 72 | 73 | \item{additional_repositories}{A logical flag specifying whether \code{Additional_repositories} should 74 | be extracted from the DESCRIPTION and appended to \code{repos}.} 75 | 76 | \item{object}{A \code{package_deps} object.} 77 | 78 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 79 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 80 | and falls back to "ask" if unset. "ask" prompts the user for which out of 81 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 82 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 83 | "always" and "never" respectively.} 84 | 85 | \item{force}{Force installation, even if the remote state has not changed 86 | since the previous install.} 87 | 88 | \item{quiet}{If \code{TRUE}, suppress output.} 89 | 90 | \item{build}{If \code{TRUE} build the package before installing.} 91 | 92 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 93 | 94 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 95 | 96 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 97 | 98 | \item{...}{Additional arguments passed to \code{install_packages}.} 99 | } 100 | \value{ 101 | A \code{data.frame} with columns: 102 | 103 | \tabular{ll}{ 104 | \code{package} \tab The dependent package's name,\cr 105 | \code{installed} \tab The currently installed version,\cr 106 | \code{available} \tab The version available on CRAN,\cr 107 | \code{diff} \tab An integer denoting whether the locally installed version 108 | of the package is newer (1), the same (0) or older (-1) than the version 109 | currently available on CRAN.\cr 110 | } 111 | } 112 | \description{ 113 | Find all the dependencies of a package and determine whether they are ahead 114 | or behind CRAN. A \code{print()} method identifies mismatches (if any) 115 | between local and CRAN versions of each dependent package; an 116 | \code{update()} method installs outdated or missing packages from CRAN. 117 | } 118 | \examples{ 119 | \dontrun{ 120 | package_deps("devtools") 121 | # Use update to update any out-of-date dependencies 122 | update(package_deps("devtools")) 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /man/parse-git-repo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parse-git.R 3 | \name{parse-git-repo} 4 | \alias{parse-git-repo} 5 | \alias{parse_repo_spec} 6 | \alias{parse_github_repo_spec} 7 | \alias{parse_github_url} 8 | \title{Parse a remote git repo specification} 9 | \usage{ 10 | parse_repo_spec(repo) 11 | 12 | parse_github_repo_spec(repo) 13 | 14 | parse_github_url(repo) 15 | } 16 | \arguments{ 17 | \item{repo}{Character scalar, the repo specification.} 18 | } 19 | \value{ 20 | List with members: \code{username}, \code{repo}, \code{subdir} 21 | \code{ref}, \code{pull}, \code{release}, some which will be empty. 22 | } 23 | \description{ 24 | A remote repo can be specified in two ways: 25 | \describe{ 26 | \item{as a URL}{\code{parse_github_url()} handles HTTPS and SSH remote URLs 27 | and various GitHub browser URLs} 28 | \item{via a shorthand}{\code{parse_repo_spec()} handles this concise form: 29 | \verb{[username/]repo[/subdir][#pull|@ref|@*release]}} 30 | } 31 | } 32 | \examples{ 33 | parse_repo_spec("metacran/crandb") 34 | parse_repo_spec("jimhester/covr#47") ## pull request 35 | parse_repo_spec("jeroen/curl@v0.9.3") ## specific tag 36 | parse_repo_spec("tidyverse/dplyr@*release") ## shorthand for latest release 37 | parse_repo_spec("r-lib/remotes@550a3c7d3f9e1493a2ba") ## commit SHA 38 | parse_repo_spec("igraph=igraph/rigraph") ## Different package name from repo name 39 | 40 | parse_github_url("https://github.com/jeroen/curl.git") 41 | parse_github_url("git@github.com:metacran/crandb.git") 42 | parse_github_url("https://github.com/jimhester/covr") 43 | parse_github_url("https://github.example.com/user/repo.git") 44 | parse_github_url("git@github.example.com:user/repo.git") 45 | 46 | parse_github_url("https://github.com/r-lib/remotes/pull/108") 47 | parse_github_url("https://github.com/r-lib/remotes/tree/name-of-branch") 48 | parse_github_url("https://github.com/r-lib/remotes/commit/1234567") 49 | parse_github_url("https://github.com/r-lib/remotes/releases/latest") 50 | parse_github_url("https://github.com/r-lib/remotes/releases/tag/1.0.0") 51 | } 52 | -------------------------------------------------------------------------------- /man/remotes-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/remotes-package.R 3 | \docType{package} 4 | \name{remotes-package} 5 | \alias{remotes} 6 | \alias{remotes-package} 7 | \title{remotes: R Package Installation from Remote Repositories, Including 'GitHub'} 8 | \description{ 9 | Download and install R packages stored in 'GitHub', 'GitLab', 'Bitbucket', 'Bioconductor', or plain 'subversion' or 'git' repositories. This package provides the 'install_*' functions in 'devtools'. Indeed most of the code was copied over from 'devtools'. 10 | } 11 | \seealso{ 12 | Useful links: 13 | \itemize{ 14 | \item \url{https://remotes.r-lib.org} 15 | \item \url{https://github.com/r-lib/remotes#readme} 16 | \item Report bugs at \url{https://github.com/r-lib/remotes/issues} 17 | } 18 | 19 | } 20 | \author{ 21 | \strong{Maintainer}: Gábor Csárdi \email{csardi.gabor@gmail.com} 22 | 23 | Authors: 24 | \itemize{ 25 | \item Jim Hester 26 | \item Hadley Wickham 27 | \item Winston Chang 28 | \item Martin Morgan 29 | \item Dan Tenenbaum 30 | } 31 | 32 | Other contributors: 33 | \itemize{ 34 | \item Posit Software, PBC [copyright holder, funder] 35 | \item Ascent Digital Services [copyright holder] 36 | } 37 | 38 | } 39 | \keyword{internal} 40 | -------------------------------------------------------------------------------- /man/standardise_dep.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deps.R 3 | \name{standardise_dep} 4 | \alias{standardise_dep} 5 | \title{Standardise dependencies using the same logical as \link{install.packages}} 6 | \usage{ 7 | standardise_dep(x) 8 | } 9 | \arguments{ 10 | \item{x}{The dependencies to standardise. 11 | A character vector (selecting from "Depends", "Imports", 12 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 13 | 14 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 15 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 16 | and is the default. \code{FALSE} is shorthand for no dependencies. 17 | 18 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 19 | 20 | Any additional values that don't match one of the standard dependency 21 | types are filtered out.} 22 | } 23 | \description{ 24 | Standardise dependencies using the same logical as \link{install.packages} 25 | } 26 | \seealso{ 27 | \url{https://r-pkgs.org/description.html} for 28 | additional information on what each dependency type means. 29 | } 30 | \keyword{internal} 31 | -------------------------------------------------------------------------------- /man/system_requirements.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/system_requirements.R 3 | \name{system_requirements} 4 | \alias{system_requirements} 5 | \title{Query the system requirements for a package (and its dependencies)} 6 | \usage{ 7 | system_requirements( 8 | os, 9 | os_release = NULL, 10 | path = ".", 11 | package = NULL, 12 | curl = Sys.which("curl") 13 | ) 14 | } 15 | \arguments{ 16 | \item{os, os_release}{The operating system and operating system release version, see 17 | \url{https://github.com/rstudio/r-system-requirements#operating-systems} for the 18 | list of supported operating systems. 19 | 20 | If \code{os_release} is \code{NULL}, \code{os} must consist of the operating system 21 | and the version separated by a dash, e.g. \code{"ubuntu-18.04"}.} 22 | 23 | \item{path}{The path to the dev package's root directory.} 24 | 25 | \item{package}{CRAN package name(s) to lookup system requirements for. If not 26 | \code{NULL}, this is used and \code{path} is ignored.} 27 | 28 | \item{curl}{The location of the curl binary on your system.} 29 | } 30 | \value{ 31 | A character vector of commands needed to install the system requirements for the package. 32 | } 33 | \description{ 34 | Returns a character vector of commands to run that will install system 35 | requirements for the queried operating system. 36 | } 37 | -------------------------------------------------------------------------------- /man/update_packages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deps.R 3 | \name{update_packages} 4 | \alias{update_packages} 5 | \title{Update packages that are missing or out-of-date.} 6 | \usage{ 7 | update_packages( 8 | packages = TRUE, 9 | dependencies = NA, 10 | upgrade = c("default", "ask", "always", "never"), 11 | force = FALSE, 12 | quiet = FALSE, 13 | build = TRUE, 14 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 15 | build_manual = FALSE, 16 | build_vignettes = FALSE, 17 | repos = getOption("repos"), 18 | type = getOption("pkgType"), 19 | ... 20 | ) 21 | } 22 | \arguments{ 23 | \item{packages}{Character vector of packages to update.} 24 | 25 | \item{dependencies}{Which dependencies do you want to check? 26 | Can be a character vector (selecting from "Depends", "Imports", 27 | "LinkingTo", "Suggests", or "Enhances"), or a logical vector. 28 | 29 | \code{TRUE} is shorthand for "Depends", "Imports", "LinkingTo" and 30 | "Suggests". \code{NA} is shorthand for "Depends", "Imports" and "LinkingTo" 31 | and is the default. \code{FALSE} is shorthand for no dependencies (i.e. 32 | just check this package, not its dependencies). 33 | 34 | The value "soft" means the same as \code{TRUE}, "hard" means the same as \code{NA}. 35 | 36 | You can also specify dependencies from one or more additional fields, 37 | common ones include: 38 | \itemize{ 39 | \item Config/Needs/website - for dependencies used in building the pkgdown site. 40 | \item Config/Needs/coverage for dependencies used in calculating test coverage. 41 | }} 42 | 43 | \item{upgrade}{Should package dependencies be upgraded? One of "default", "ask", "always", or "never". "default" 44 | respects the value of the \code{R_REMOTES_UPGRADE} environment variable if set, 45 | and falls back to "ask" if unset. "ask" prompts the user for which out of 46 | date packages to upgrade. For non-interactive sessions "ask" is equivalent 47 | to "always". \code{TRUE} and \code{FALSE} are also accepted and correspond to 48 | "always" and "never" respectively.} 49 | 50 | \item{force}{Deprecated, this argument has no effect.} 51 | 52 | \item{quiet}{If \code{TRUE}, suppress output.} 53 | 54 | \item{build}{If \code{TRUE} build the package before installing.} 55 | 56 | \item{build_opts}{Options to pass to \verb{R CMD build}, only used when \code{build} is \code{TRUE}.} 57 | 58 | \item{build_manual}{If \code{FALSE}, don't build PDF manual ('--no-manual').} 59 | 60 | \item{build_vignettes}{If \code{FALSE}, don't build package vignettes ('--no-build-vignettes').} 61 | 62 | \item{repos}{A character vector giving repositories to use.} 63 | 64 | \item{type}{Type of package to \code{update}.} 65 | 66 | \item{...}{Other arguments passed on to \code{\link[utils:install.packages]{utils::install.packages()}}.} 67 | } 68 | \description{ 69 | Works similarly to \code{\link[utils:install.packages]{utils::install.packages()}} but doesn't install packages 70 | that are already installed, and also upgrades out dated dependencies. 71 | } 72 | \examples{ 73 | \dontrun{ 74 | update_packages("ggplot2") 75 | update_packages(c("plyr", "ggplot2")) 76 | } 77 | } 78 | \seealso{ 79 | \code{\link[=package_deps]{package_deps()}} to see which packages are out of date/ 80 | missing. 81 | } 82 | -------------------------------------------------------------------------------- /remotes.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: XeLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview 7 | # * https://testthat.r-lib.org/articles/special-files.html 8 | 9 | library(testthat) 10 | library(remotes) 11 | 12 | if (Sys.getenv("NOT_CRAN") == "true") { 13 | test_check("remotes") 14 | } 15 | -------------------------------------------------------------------------------- /tests/testthat/Biobase/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: Biobase 2 | Title: Biobase: Base functions for Bioconductor 3 | Version: 2.43.1 4 | Author: R. Gentleman, V. Carey, M. Morgan, S. Falcon 5 | Description: Functions that are needed by many other packages or which 6 | replace R functions. 7 | Suggests: tools, tkWidgets, ALL, RUnit, golubEsets 8 | Depends: R (>= 2.10), BiocGenerics (>= 0.27.1), utils 9 | Imports: methods 10 | Maintainer: Bioconductor Package Maintainer 11 | 12 | License: Artistic-2.0 13 | Collate: tools.R strings.R environment.R vignettes.R packages.R 14 | AllGenerics.R VersionsClass.R VersionedClasses.R 15 | methods-VersionsNull.R methods-VersionedClass.R DataClasses.R 16 | methods-aggregator.R methods-container.R methods-MIAxE.R 17 | methods-MIAME.R methods-AssayData.R 18 | methods-AnnotatedDataFrame.R methods-eSet.R 19 | methods-ExpressionSet.R methods-MultiSet.R methods-SnpSet.R 20 | methods-NChannelSet.R anyMissing.R rowOp-methods.R 21 | updateObjectTo.R methods-ScalarObject.R zzz.R 22 | LazyLoad: yes 23 | biocViews: Infrastructure 24 | -------------------------------------------------------------------------------- /tests/testthat/MASS/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: MASS 2 | Priority: recommended 3 | Version: 7.3-51 4 | Date: 2018-10-16 5 | Revision: $Rev: 3490 $ 6 | Depends: R (>= 3.1.0), grDevices, graphics, stats, utils 7 | Imports: methods 8 | Suggests: lattice, nlme, nnet, survival 9 | Authors@R: c(person("Brian", "Ripley", role = c("aut", "cre", "cph"), 10 | email = "ripley@stats.ox.ac.uk"), 11 | person("Bill", "Venables", role = "ctb"), 12 | person(c("Douglas", "M."), "Bates", role = "ctb"), 13 | person("Kurt", "Hornik", role = "trl", 14 | comment = "partial port ca 1998"), 15 | person("Albrecht", "Gebhardt", role = "trl", 16 | comment = "partial port ca 1998"), 17 | person("David", "Firth", role = "ctb")) 18 | Description: Functions and datasets to support Venables and Ripley, 19 | "Modern Applied Statistics with S" (4th edition, 2002). 20 | Title: Support Functions and Datasets for Venables and Ripley's MASS 21 | LazyData: yes 22 | ByteCompile: yes 23 | License: GPL-2 | GPL-3 24 | URL: http://www.stats.ox.ac.uk/pub/MASS4/ 25 | Contact: 26 | NeedsCompilation: yes 27 | Packaged: 2018-10-16 10:15:23 UTC; ripley 28 | Author: Brian Ripley [aut, cre, cph], 29 | Bill Venables [ctb], 30 | Douglas M. Bates [ctb], 31 | Kurt Hornik [trl] (partial port ca 1998), 32 | Albrecht Gebhardt [trl] (partial port ca 1998), 33 | David Firth [ctb] 34 | Maintainer: Brian Ripley 35 | Repository: CRAN 36 | Date/Publication: 2018-10-16 10:18:19 UTC 37 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/github.md: -------------------------------------------------------------------------------- 1 | # github_error 2 | 3 | Code 4 | conditionMessage(err) 5 | Output 6 | [1] "HTTP error 304.\n foobar\n\n Rate limit remaining: 0/5000\n Rate limit reset at: 2018-10-19 15:16:18 UTC\n\n To increase your GitHub API rate limit\n - Use `usethis::create_github_token()` to create a Personal Access Token.\n - Use `gitcreds::gitcreds_set()` to add the token." 7 | 8 | --- 9 | 10 | Code 11 | conditionMessage(err) 12 | Output 13 | [1] "HTTP error 304.\n foobar\n\n Rate limit remaining: 0/5000\n Rate limit reset at: 2018-10-19 15:16:18 UTC\n\n To increase your GitHub API rate limit\n - Use `usethis::create_github_token()` to create a Personal Access Token.\n - Add `GITHUB_PAT` to your travis settings as an encrypted variable." 14 | 15 | -------------------------------------------------------------------------------- /tests/testthat/archives/foo.tar: -------------------------------------------------------------------------------- 1 | foo/000755 000765 000024 00000000000 12643157623 013275 5ustar00gaborcsardistaff000000 000000 foo/DESCRIPTION000644 000765 000024 00000000264 12643157612 015003 0ustar00gaborcsardistaff000000 000000 Package: foo 2 | Title: Foo Bar 3 | Description: Seriously. Foo Bar. 4 | Version: 1.0.0 5 | Author: Gabor Csardi 6 | Maintainer: Gabor Csardi 7 | License: MIT + file LICENSE 8 | foo/R/000755 000765 000024 00000000000 12643157512 013473 5ustar00gaborcsardistaff000000 000000 foo/R/foo.R000644 000765 000024 00000000015 12643157512 014375 0ustar00gaborcsardistaff000000 000000 foo <- 1 + 1 9 | -------------------------------------------------------------------------------- /tests/testthat/archives/foo.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-lib/remotes/HEAD/tests/testthat/archives/foo.tar.bz2 -------------------------------------------------------------------------------- /tests/testthat/archives/foo.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-lib/remotes/HEAD/tests/testthat/archives/foo.tar.gz -------------------------------------------------------------------------------- /tests/testthat/archives/foo.tbz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-lib/remotes/HEAD/tests/testthat/archives/foo.tbz -------------------------------------------------------------------------------- /tests/testthat/archives/foo.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-lib/remotes/HEAD/tests/testthat/archives/foo.tgz -------------------------------------------------------------------------------- /tests/testthat/archives/foo.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-lib/remotes/HEAD/tests/testthat/archives/foo.zip -------------------------------------------------------------------------------- /tests/testthat/archives/foo/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: foo 2 | Title: Foo Bar 3 | Description: Seriously. Foo Bar. 4 | Version: 1.0.0 5 | Author: Gabor Csardi 6 | Maintainer: Gabor Csardi 7 | License: MIT + file LICENSE 8 | -------------------------------------------------------------------------------- /tests/testthat/archives/foo/R/foo.R: -------------------------------------------------------------------------------- 1 | foo <- 1 + 1 2 | -------------------------------------------------------------------------------- /tests/testthat/archives/foo/configure: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/testthat/helper.R: -------------------------------------------------------------------------------- 1 | 2 | skip_if_offline <- function(host = "httpbin.org", port = 80) { 3 | 4 | res <- tryCatch( 5 | pingr::ping_port(host, count = 1L, port = port), 6 | error = function(e) NA 7 | ) 8 | 9 | if (is.na(res)) skip("No internet connection") 10 | } 11 | 12 | skip_if_over_rate_limit <- function(by = 50) { 13 | 14 | tmp <- tempfile() 15 | download( 16 | tmp, 17 | "https://api.github.com/rate_limit", 18 | auth_token = github_pat() 19 | ) 20 | 21 | res <- json$parse_file(tmp)$rate$remaining 22 | if (is.null(res) || res <= by) skip("Over the GitHub rate limit") 23 | } 24 | 25 | expect_equal_named_lists <- function(object, expected, ...) { 26 | expect_true(!is.null(names(object)) && !is.null(names(expected))) 27 | expect_true(is.list(object) && is.list(expected)) 28 | object <- object[order(names(object))] 29 | expected <- expected[order(names(expected))] 30 | expect_equal(!!object, !!expected) 31 | } 32 | 33 | skip_without_package <- function(pkg) { 34 | if (!requireNamespace(pkg, quietly = TRUE)) { 35 | skip(paste("Need the", pkg, "package")) 36 | } 37 | } 38 | 39 | skip_without_program <- function(program) { 40 | if (Sys.which(program) == "") { 41 | skip(paste("Need the", program, "program")) 42 | } 43 | } 44 | 45 | test_temp_file <- function(fileext = "", pattern = "test-file-", 46 | envir = parent.frame()) { 47 | tmp <- tempfile(pattern = pattern, fileext = fileext) 48 | withr::defer( 49 | try(unlink(tmp, recursive = TRUE, force = TRUE), silent = TRUE), 50 | envir = envir) 51 | tmp 52 | } 53 | 54 | test_temp_dir <- function(pattern = "test-dir-", envir = parent.frame()) { 55 | tmp <- test_temp_file(pattern, envir = envir) 56 | dir.create(tmp, recursive = TRUE, showWarnings = FALSE) 57 | tmp 58 | } 59 | 60 | httpbin <- webfakes::new_app_process(webfakes::httpbin_app()) 61 | 62 | test_package_root <- function() { 63 | x <- tryCatch( 64 | rprojroot::find_package_root_file(), 65 | error = function(e) NULL) 66 | 67 | if (!is.null(x)) return(x) 68 | 69 | pkg <- testthat::testing_package() 70 | x <- tryCatch( 71 | rprojroot::find_package_root_file( 72 | path = file.path("..", "..", "00_pkg_src", pkg)), 73 | error = function(e) NULL) 74 | 75 | if (!is.null(x)) return(x) 76 | 77 | stop("Cannot find package root") 78 | } 79 | -------------------------------------------------------------------------------- /tests/testthat/invalidpkg/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: invalidpkg 2 | Title: Tools to make developing R code easier 3 | License: MIT 4 | Description: Package description. 5 | Author: Bugs Bunny 6 | Maintainer: Bugs Bunny 7 | Version: 1.0.0 8 | Suggests: 9 | testthat 10 | foobar 11 | -------------------------------------------------------------------------------- /tests/testthat/noremotes/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: noremotes 2 | Title: Tools to make developing R code easier 3 | License: MIT 4 | Description: Package description. 5 | Author: Bugs Bunny 6 | Maintainer: Bugs Bunny 7 | Version: 1.0.0 8 | Suggests: testthat 9 | -------------------------------------------------------------------------------- /tests/testthat/submodule/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: submodule 2 | Title: Foo Bar 3 | Description: Seriously. Foo Bar. 4 | Version: 1.0.0 5 | Author: Gabor Csardi 6 | Maintainer: Gabor Csardi 7 | License: MIT + file LICENSE 8 | -------------------------------------------------------------------------------- /tests/testthat/submodule/NAMESPACE: -------------------------------------------------------------------------------- 1 | exportPattern(".*") 2 | -------------------------------------------------------------------------------- /tests/testthat/test-bioc.R: -------------------------------------------------------------------------------- 1 | test_that("bioc is standalone", { 2 | ## baseenv() makes sure that the remotes package env is not used 3 | env <- new.env(parent = baseenv()) 4 | env$bioc <- bioconductor 5 | stenv <- env$bioc$.internal 6 | objs <- ls(stenv, all.names = TRUE) 7 | funs <- Filter(function(x) is.function(stenv[[x]]), objs) 8 | funobjs <- mget(funs, stenv) 9 | 10 | expect_message( 11 | mapply(codetools::checkUsage, funobjs, funs, 12 | MoreArgs = list(report = message)), 13 | NA) 14 | }) 15 | 16 | test_that("we can parse the YAML config", { 17 | skip_if_offline() 18 | expect_silent(yaml <- bioconductor$get_yaml_config(forget = TRUE)) 19 | expect_true(length(yaml) > 20) 20 | map <- bioconductor$get_version_map() 21 | expect_true("release" %in% map$bioc_status) 22 | expect_true("devel" %in% map$bioc_status) 23 | expect_true("future" %in% map$bioc_status) 24 | 25 | expect_true(inherits(bioconductor$get_release_version(), 26 | "package_version")) 27 | expect_true(inherits(bioconductor$get_devel_version(), 28 | "package_version")) 29 | }) 30 | 31 | test_that("internal map is current", { 32 | # If there is a new bioc version out, then we'll error. 33 | # This is to notify us that we need to update the package's 34 | # internal map. 35 | skip_on_cran() 36 | skip_if_offline() 37 | expect_equal( 38 | bioconductor$get_release_version(), 39 | package_version("3.20")) 40 | }) 41 | 42 | test_that("set of repos are correct", { 43 | # Compare our set of repos to the set returned by BiocManager. 44 | # They should match. If they don't we need to update the package. 45 | skip_if_offline() 46 | skip_on_cran() 47 | skip_without_package("BiocManager") 48 | withr::local_envvar(list(BIOC_VERSION = NA, BIOC_MIRROR = NA)) 49 | withr::local_options(list(Bioc_mirror = NULL)) 50 | 51 | # We can only run this if the matching R version is new enough, 52 | # so we skip on other platforms 53 | dev_ver <- bioconductor$get_devel_version() 54 | map <- bioconductor$get_version_map() 55 | required <- map$r_version[map$bioc_version == dev_ver] 56 | if (!getRversion()[, 1:2] %in% required) skip("Needs newer R version") 57 | 58 | my_repos <- bioconductor$get_repos(dev_ver) 59 | bm_repos <- asNamespace("BiocManager")$repositories(version = dev_ver) 60 | bm_repos <- bm_repos[names(bm_repos) != "CRAN"] 61 | expect_equal(sort(names(my_repos)), sort(names(bm_repos))) 62 | expect_equal(my_repos, bm_repos[names(my_repos)]) 63 | }) 64 | 65 | test_that("bioc_install_repos", { 66 | 67 | expect_equal( 68 | bioc_install_repos("3.1.0"), 69 | bioc_install_repos(bioc_ver = "3.0") 70 | ) 71 | 72 | expect_equal( 73 | bioc_install_repos("3.1.1"), 74 | bioc_install_repos(bioc_ver = "3.0") 75 | ) 76 | 77 | expect_equal( 78 | bioc_install_repos("3.2"), 79 | bioc_install_repos(bioc_ver = "3.2") 80 | ) 81 | 82 | expect_equal( 83 | bioc_install_repos("3.3"), 84 | bioc_install_repos(bioc_ver = "3.4") 85 | ) 86 | 87 | expect_equal( 88 | bioc_install_repos("3.4"), 89 | bioc_install_repos(bioc_ver = "3.6") 90 | ) 91 | 92 | expect_equal( 93 | bioc_install_repos("3.5"), 94 | bioc_install_repos(bioc_ver = "3.8") 95 | ) 96 | 97 | # This particular version needs to do a connection test for https support 98 | skip_on_cran() 99 | skip_if_offline() 100 | expect_equal( 101 | bioc_install_repos("3.2.2"), 102 | bioc_install_repos(bioc_ver = "3.2") 103 | ) 104 | }) 105 | 106 | test_that("CRANextras exists in versions prior to Bioc 3.6", { 107 | expect_equal( 108 | names(bioc_install_repos(bioc_ver = "3.5")), 109 | c("BioCsoft", "BioCann", "BioCexp", "BioCextra") 110 | ) 111 | 112 | expect_equal( 113 | names(bioc_install_repos(bioc_ver = "3.6")), 114 | c("BioCsoft", "BioCann", "BioCexp") 115 | ) 116 | }) 117 | -------------------------------------------------------------------------------- /tests/testthat/test-cran.R: -------------------------------------------------------------------------------- 1 | test_that("available_packages", { 2 | 3 | skip_on_cran() 4 | 5 | pkgs <- available_packages( 6 | repos = c(CRAN = "http://cran.rstudio.com"), 7 | type = "source" 8 | ) 9 | 10 | expect_true(inherits(pkgs, "matrix")) 11 | }) 12 | -------------------------------------------------------------------------------- /tests/testthat/test-dcf.R: -------------------------------------------------------------------------------- 1 | test_that("read_dcf and write_dcf", { 2 | 3 | DESC <- "Package: foobar 4 | Description: With continuation lines. 5 | Like 6 | . 7 | This one. 8 | . 9 | And this one. 10 | Title: Foo Bar 11 | " 12 | tmp <- tempfile() 13 | cat(DESC, file = tmp) 14 | dcf <- read_dcf(tmp) 15 | 16 | expect_equal(length(dcf), 3) 17 | expect_equal(names(dcf), c("Package", "Description", "Title")) 18 | 19 | tmp2 <- tempfile() 20 | on.exit(unlink(tmp2), add = TRUE) 21 | write_dcf(tmp2, dcf) 22 | 23 | DESC2 <- readChar(tmp2, nchars = file.info(tmp2)$size) 24 | 25 | ## This is a workaround for a write.dcf bug 26 | ## And also windows line ending characters 27 | DESC2 <- gsub("\r\n", "\n", DESC2) 28 | DESC2 <- gsub("\n .\n ", "\n .\n ", DESC2) 29 | expect_equal(DESC, DESC2) 30 | }) 31 | -------------------------------------------------------------------------------- /tests/testthat/test-decompress.R: -------------------------------------------------------------------------------- 1 | test_that("decompress various file types", { 2 | 3 | types <- c("zip", "tar", "tar.gz", "tgz") 4 | 5 | for (type in types) { 6 | 7 | fname <- paste0("foo.", type) 8 | archive <- file.path("archives", fname) 9 | dec <- tempfile() 10 | decompress(archive, dec) 11 | 12 | expect_true( 13 | file.exists(file.path(dec, "foo", "R", "foo.R")), 14 | info = type 15 | ) 16 | } 17 | 18 | }) 19 | 20 | test_that("decompress with internal unzip", { 21 | 22 | types <- c("zip", "tar", "tar.gz", "tgz") 23 | 24 | for (type in types) { 25 | 26 | fname <- paste0("foo.", type) 27 | archive <- file.path("archives", fname) 28 | 29 | dec <- tempfile() 30 | on.exit(unlink(dec, recursive = TRUE), add = TRUE) 31 | 32 | mockery::stub( 33 | decompress, 34 | "getOption", 35 | function(x, default = NULL) { 36 | if (x == "unzip") { 37 | "internal" 38 | } else { 39 | if (missing(default) || x %in% names(options())) { 40 | options()[[x]] 41 | } else { 42 | default 43 | } 44 | } 45 | } 46 | ) 47 | 48 | decompress(archive, dec) 49 | 50 | expect_true( 51 | file.exists(file.path(dec, "foo", "R", "foo.R")), 52 | info = type 53 | ) 54 | } 55 | 56 | }) 57 | 58 | test_that("decompress errors on unknown file types", { 59 | 60 | tmp <- tempfile(fileext = ".foobar") 61 | on.exit(unlink(tmp, recursive = TRUE), add = TRUE) 62 | cat("surprise!", file = tmp) 63 | expect_error( 64 | decompress(tmp, tempdir()), 65 | "Don't know how to decompress" 66 | ) 67 | 68 | }) 69 | 70 | test_that("source_pkg", { 71 | 72 | foo_dir <- file.path("archives", "foo") 73 | expect_equal(source_pkg(foo_dir), foo_dir) 74 | 75 | bad_dir <- "archives" 76 | expect_error( 77 | source_pkg(bad_dir), 78 | "Does not appear to be an R package" 79 | ) 80 | 81 | foo_tgz <- file.path("archives", "foo.tar.gz") 82 | pkg_dir <- source_pkg(foo_tgz) 83 | on.exit(unlink(pkg_dir, recursive = TRUE), add = TRUE) 84 | expect_true(file.exists(file.path(pkg_dir, "R", "foo.R"))) 85 | expect_true(file.exists(file.path(pkg_dir, "configure"))) 86 | 87 | skip_on_os("windows") 88 | 89 | expect_match( 90 | as.character(file.info(file.path(pkg_dir, "configure"))$mode), 91 | "7.." 92 | ) 93 | }) 94 | 95 | test_that("getrootdir", { 96 | cases <- list( 97 | list(c("foo/bar", "foo/"), "foo"), 98 | list(c("/foo/bar/baz", "/foo/bar"), "/foo"), 99 | list(c("this/foo/bar", "this/that"), "this"), 100 | list(c("", "yes"), ".") 101 | ) 102 | 103 | for (c in seq_along(cases)) { 104 | expect_identical(getrootdir(cases[[c]][[1]]), cases[[c]][[2]], info = c) 105 | } 106 | 107 | expect_error(getrootdir(character())) 108 | }) 109 | 110 | test_that("my_unzip respects options('unzip')", { 111 | mockery::stub(my_unzip, "utils::unzip", function(...) int <<- TRUE) 112 | mockery::stub(my_unzip, "system_check", function(...) int <<- FALSE) 113 | 114 | int <- NULL 115 | withr::with_options(c("unzip" = "internal"), my_unzip("blah", "tg")) 116 | expect_true(int) 117 | 118 | int <- NULL 119 | withr::with_options(c("unzip" = ""), my_unzip("blah", "tg")) 120 | expect_true(int) 121 | 122 | int <- NULL 123 | withr::with_options(c("unzip" = "somethingelse"), my_unzip("blah", "tg")) 124 | expect_false(int) 125 | }) 126 | -------------------------------------------------------------------------------- /tests/testthat/test-devel.R: -------------------------------------------------------------------------------- 1 | test_that("has_devel", { 2 | # All platforms when tests are run should have a compiler 3 | expect_true(has_devel()) 4 | 5 | # has_devel should return FALSE if an error occurs from has_devel2 6 | mockery::stub( 7 | has_devel, "has_devel2", function(...) stop("failed")) 8 | expect_false(has_devel()) 9 | }) 10 | 11 | test_that("has_devel2", { 12 | # has_devel2 should error if an error occurs from R CMD SHLIB 13 | mockery::stub( 14 | has_devel2, "R", function(...) stop("failed")) 15 | expect_error(has_devel2()) 16 | }) 17 | 18 | test_that("missing_devel_warning", { 19 | mockery::stub( 20 | missing_devel_warning, "has_devel2", function(...) FALSE) 21 | 22 | expect_warning( 23 | missing_devel_warning("noremotes"), "has compiled code, but no suitable compiler") 24 | 25 | # Windows 26 | mockery::stub( 27 | missing_devel_warning, "sys_type", function() "windows") 28 | expect_warning( 29 | missing_devel_warning("noremotes"), "Install Rtools") 30 | 31 | # MacOS 32 | mockery::stub( 33 | missing_devel_warning, "sys_type", function() "macos") 34 | expect_warning( 35 | missing_devel_warning("noremotes"), "Install XCode") 36 | 37 | # Linux 38 | mockery::stub( 39 | missing_devel_warning, "sys_type", function() "linux") 40 | expect_warning( 41 | missing_devel_warning("noremotes"), "Install compilers") 42 | }) 43 | -------------------------------------------------------------------------------- /tests/testthat/test-git.R: -------------------------------------------------------------------------------- 1 | test_that("git_extract_sha1_tar", { 2 | 3 | skip_on_cran() 4 | skip_if_offline() 5 | skip_if_over_rate_limit() 6 | 7 | sha <- "fbae60ced0afee0e7c0f8dc3b5b1bb48d303f3dd" 8 | url <- build_url( 9 | "api.github.com/repos/hadley/devtools/tarball", 10 | sha 11 | ) 12 | 13 | tmp <- tempfile() 14 | on.exit(unlink(tmp), add = TRUE) 15 | download(tmp, url, auth_token = github_pat()) 16 | 17 | expect_equal( 18 | git_extract_sha1_tar(tmp), 19 | sha 20 | ) 21 | }) 22 | 23 | 24 | test_that("git not quiet", { 25 | 26 | mockery::stub(git, "check_git_path", "/foo/git") 27 | mockery::stub(git, "system", "0") 28 | expect_message( 29 | git(args = c("arg1", "arg2"), quiet = FALSE), 30 | "['\"]/foo/git['\"] arg1arg2" 31 | ) 32 | }) 33 | 34 | 35 | test_that("git error", { 36 | 37 | mockery::stub(git, "check_git_path", "/foo/git") 38 | mockery::stub(git, "system", structure("foo", status = "1")) 39 | expect_error(git(args = "arg"), "Command failed") 40 | }) 41 | 42 | 43 | test_that("git_path", { 44 | 45 | tmp <- tempfile() 46 | expect_error( 47 | git_path(tmp), 48 | "does not exist" 49 | ) 50 | 51 | cat("Hello", file = tmp) 52 | expect_equal(git_path(tmp), tmp) 53 | 54 | mockery::stub(git_path, "Sys.which", "") 55 | mockery::stub(git_path, "os_type", "windows") 56 | mockery::stub(git_path, "file.exists", FALSE) 57 | expect_null(git_path()) 58 | }) 59 | 60 | 61 | test_that("check_git_path", { 62 | 63 | mockery::stub(check_git_path, "git_path", NULL) 64 | expect_error( 65 | check_git_path(), 66 | "Git does not seem to be installed on your system" 67 | ) 68 | }) 69 | -------------------------------------------------------------------------------- /tests/testthat/test-github.R: -------------------------------------------------------------------------------- 1 | test_that("github_pat", { 2 | withr::local_envvar(c(GITHUB_PAT="badcafe")) 3 | 4 | expect_equal(github_pat(), "badcafe") 5 | expect_message(github_pat(quiet = FALSE), "Using github PAT from envvar GITHUB_PAT") 6 | 7 | # Check standard GITHUB_PAT 8 | withr::with_envvar( 9 | c( 10 | GITHUB_PAT = NA, 11 | GITHUB_TOKEN = NA, 12 | CI = NA, 13 | GITHUB_PAT_GITHUB_COM = "FAIL" # make gitcreds fail 14 | ), 15 | { 16 | expect_equal(github_pat(), NULL) 17 | } 18 | ) 19 | 20 | # Check for embedded token 21 | withr::with_envvar(c(GITHUB_PAT=NA, CI="true"), { 22 | expect_true(nzchar(github_pat())) 23 | }) 24 | 25 | # Check for GITHUB_TOKEN 26 | withr::with_envvar(c(GITHUB_PAT=NA, GITHUB_TOKEN="hi!", CI=NA), { 27 | expect_true(nzchar(github_pat())) 28 | }) 29 | 30 | expect_true(nzchar(github_pat())) 31 | }) 32 | 33 | test_that("github_commit", { 34 | skip_on_cran() 35 | skip_if_offline() 36 | skip_if_over_rate_limit() 37 | 38 | # Without curl 39 | expect_equal( 40 | github_commit("r-lib", "remotes", "1.0.0", use_curl = FALSE), 41 | "92e5d5c061f181242cb877e4714bea76d94927da") 42 | 43 | # With curl 44 | expect_equal( 45 | github_commit("r-lib", "remotes", "1.0.0", use_curl = TRUE), 46 | "92e5d5c061f181242cb877e4714bea76d94927da") 47 | 48 | # With curl and different local sha 49 | expect_equal( 50 | github_commit("r-lib", "remotes", "1.0.0", use_curl = TRUE, current_sha = "xyz"), 51 | "92e5d5c061f181242cb877e4714bea76d94927da") 52 | 53 | # With curl and same local sha 54 | expect_equal( 55 | github_commit("r-lib", "remotes", "1.0.0", use_curl = TRUE, current_sha = "92e5d5c061f181242cb877e4714bea76d94927da"), 56 | "92e5d5c061f181242cb877e4714bea76d94927da") 57 | }) 58 | 59 | test_that("github_DESCRIPTION", { 60 | skip_on_cran() 61 | skip_if_offline() 62 | skip_if_over_rate_limit() 63 | 64 | tmp <- tempfile() 65 | on.exit(unlink(tmp)) 66 | 67 | download(tmp, "https://raw.githubusercontent.com/r-lib/remotes/1.0.0/DESCRIPTION") 68 | desc <- readChar(tmp, file.info(tmp)$size) 69 | 70 | # Without curl 71 | expect_equal( 72 | github_DESCRIPTION("r-lib", "remotes", ref = "1.0.0", use_curl = FALSE), 73 | desc) 74 | 75 | # With curl 76 | expect_equal( 77 | github_DESCRIPTION("r-lib", "remotes", ref = "1.0.0", use_curl = TRUE), 78 | desc) 79 | }) 80 | 81 | test_that("github_error", { 82 | mockery::stub( 83 | github_error, 84 | "curl::parse_headers_list", 85 | list(`x-ratelimit-remaining` = 0, `x-ratelimit-limit` = 5000, `x-ratelimit-reset` = "1539962178")) 86 | 87 | # Test without the TRAVIS envvar set 88 | withr::with_envvar(c(TRAVIS = NA), { 89 | err <- github_error(list(headers = "", status_code = "304", content = charToRaw('{"message": "foobar"}'))) 90 | expect_snapshot(conditionMessage(err)) 91 | }) 92 | 93 | # Test with the TRAVIS envvar set 94 | withr::with_envvar(c(TRAVIS = "true"), { 95 | err <- github_error(list(headers = "", status_code = "304", content = charToRaw('{"message": "foobar"}'))) 96 | expect_snapshot(conditionMessage(err)) 97 | }) 98 | 99 | }) 100 | -------------------------------------------------------------------------------- /tests/testthat/test-install-bioc.R: -------------------------------------------------------------------------------- 1 | test_that("bioc repo paths are parsed correctly", { 2 | expect_equal(parse_bioc_repo("devtools"), list(repo="devtools")) 3 | expect_equal(parse_bioc_repo("devtools#abc123"), list(repo="devtools", commit="abc123")) 4 | expect_equal(parse_bioc_repo("user:pass@devtools"), list(username = "user", password = "pass", repo="devtools")) 5 | expect_equal(parse_bioc_repo("devel/devtools"), list(release = "devel", repo="devtools")) 6 | expect_equal(parse_bioc_repo("3.1/devtools"), list(release = "3.1", repo="devtools")) 7 | expect_equal(parse_bioc_repo("release/devtools"), list(release = "release", repo="devtools")) 8 | expect_equal(parse_bioc_repo("user:pass@devtools#abc123"), list(username = "user", password = "pass", repo="devtools", commit = "abc123")) 9 | expect_error(parse_bioc_repo("user:pass@3.1/devtools#abc123"), "release and commit should not both be specified") 10 | expect_error(parse_bioc_repo("user@devtools"), "Invalid bioc repo") 11 | expect_error(parse_bioc_repo("user:@devtools"), "Invalid bioc repo") 12 | expect_error(parse_bioc_repo("@devtools"), "Invalid bioc repo") 13 | expect_error(parse_bioc_repo("devtools/"), "Invalid bioc repo") 14 | expect_error(parse_bioc_repo("junk/devtools"), "Invalid bioc repo") 15 | }) 16 | 17 | test_that("install_bioc with git2r", { 18 | 19 | skip_without_package("git2r") 20 | skip_on_cran() 21 | skip_if_offline() 22 | 23 | lib <- tempfile() 24 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 25 | dir.create(lib) 26 | 27 | mirror <- getOption("BioC_git", "https://git.bioconductor.org/packages") 28 | 29 | # This package has no dependencies or compiled code and is old 30 | install_bioc("MeasurementError.cor", mirror = mirror, git = "git2r", lib = lib, quiet = TRUE) 31 | 32 | expect_silent(packageDescription("MeasurementError.cor", lib.loc = lib)) 33 | expect_equal(packageDescription("MeasurementError.cor", lib.loc = lib)$RemoteType, "bioc_git2r") 34 | 35 | remote <- package2remote("MeasurementError.cor", lib = lib) 36 | expect_s3_class(remote, "remote") 37 | expect_s3_class(remote, "bioc_git2r_remote") 38 | expect_equal(format(remote), "Bioc") 39 | expect_equal(remote$mirror, mirror) 40 | expect_equal(remote$repo, "MeasurementError.cor") 41 | expect_equal(remote$release, "release") 42 | expect_true(!is.na(remote$sha) && nzchar(remote$sha)) 43 | expect_true(!is.na(remote$branch) && nzchar(remote$branch)) 44 | }) 45 | 46 | test_that("install_bioc with xgit", { 47 | 48 | skip_without_program("git") 49 | skip_on_cran() 50 | skip_if_offline() 51 | 52 | lib <- tempfile() 53 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 54 | dir.create(lib) 55 | 56 | mirror <- getOption("BioC_git", "https://git.bioconductor.org/packages") 57 | 58 | 59 | # This package has no dependencies or compiled code and is old 60 | install_bioc("MeasurementError.cor", mirror = mirror, git = "external", lib = lib, quiet = TRUE) 61 | 62 | expect_silent(packageDescription("MeasurementError.cor", lib.loc = lib)) 63 | expect_equal(packageDescription("MeasurementError.cor", lib.loc = lib)$RemoteType, "bioc_xgit") 64 | 65 | remote <- package2remote("MeasurementError.cor", lib = lib) 66 | expect_s3_class(remote, "remote") 67 | expect_s3_class(remote, "bioc_xgit_remote") 68 | expect_equal(format(remote), "Bioc") 69 | expect_equal(remote$mirror, mirror) 70 | expect_equal(remote$repo, "MeasurementError.cor") 71 | expect_equal(remote$release, "release") 72 | expect_true(!is.na(remote$sha) && nzchar(remote$sha)) 73 | expect_true(!is.na(remote$branch) && nzchar(remote$branch)) 74 | }) 75 | -------------------------------------------------------------------------------- /tests/testthat/test-install-bitbucket.R: -------------------------------------------------------------------------------- 1 | test_that("", { 2 | 3 | skip_on_cran() 4 | skip_if_offline() 5 | 6 | Sys.unsetenv("R_TESTS") 7 | 8 | lib <- tempfile() 9 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 10 | dir.create(lib) 11 | 12 | install_bitbucket("jimhester/withr", lib = lib, quiet = TRUE) 13 | 14 | expect_silent(packageDescription("withr", lib.loc = lib)) 15 | expect_equal( 16 | packageDescription("withr", lib.loc = lib)$RemoteRepo, 17 | "withr") 18 | 19 | remote <- package2remote("withr", lib = lib) 20 | expect_s3_class(remote, "remote") 21 | expect_s3_class(remote, "bitbucket_remote") 22 | expect_equal(format(remote), "Bitbucket") 23 | expect_equal(remote$host, "api.bitbucket.org/2.0") 24 | expect_equal(remote$repo, "withr") 25 | expect_equal(remote$username, "jimhester") 26 | expect_true(!is.na(remote$sha) && nzchar(remote$sha)) 27 | }) 28 | 29 | 30 | test_that("remote_download.bitbucket_remote", { 31 | 32 | x <- list(username = "csardigabor", repo = "pkgconfig", ref = "HEAD", 33 | host = "api.bitbucket.org/2.0") 34 | 35 | mockery::stub( 36 | remote_download.bitbucket_remote, "download", function(...) { } 37 | ) 38 | 39 | mockery::stub( 40 | remote_download.bitbucket_remote, "bitbucket_download_url", function(...) { } 41 | ) 42 | 43 | expect_message( 44 | remote_download.bitbucket_remote(x), 45 | "Downloading bitbucket repo csardigabor/pkgconfig@HEAD" 46 | ) 47 | }) 48 | 49 | 50 | test_that("remote_metadata.bitbucket_remote", { 51 | 52 | expect_equal( 53 | remote_metadata.bitbucket_remote(list(), sha = "foobar")$RemoteSha, 54 | "foobar" 55 | ) 56 | }) 57 | 58 | 59 | test_that("bitbucket passwords", { 60 | 61 | if (Sys.getenv("BITBUCKET_PASSWORD") == "") { 62 | skip("Need BitBucket credentials") 63 | } 64 | 65 | skip_on_cran() 66 | skip_if_offline() 67 | 68 | Sys.unsetenv("R_TESTS") 69 | 70 | lib <- tempfile() 71 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 72 | dir.create(lib) 73 | 74 | install_bitbucket("jimhester/falsy", lib = lib, quiet = TRUE) 75 | 76 | expect_silent(packageDescription("falsy", lib.loc = lib)) 77 | expect_equal( 78 | packageDescription("falsy", lib.loc = lib)$RemoteRepo, 79 | "falsy") 80 | }) 81 | 82 | 83 | test_that("more bitbucket password", { 84 | 85 | x <- list( 86 | username = "username", 87 | repo = "repo", 88 | ref = "HEAD", 89 | auth_user = "foo", 90 | password = "pass", 91 | host = "api.bitbucket.com/2.0" 92 | ) 93 | 94 | mockery::stub( 95 | remote_download.bitbucket_remote, 96 | "download", 97 | function(dest, src, basic_auth) basic_auth) 98 | 99 | mockery::stub( 100 | remote_download.bitbucket_remote, 101 | "bitbucket_download_url", 102 | function(...) { }) 103 | 104 | expect_equal( 105 | remote_download.bitbucket_remote(x), 106 | list(user = "foo", password = "pass") 107 | ) 108 | }) 109 | -------------------------------------------------------------------------------- /tests/testthat/test-install-cran.R: -------------------------------------------------------------------------------- 1 | test_that("", { 2 | 3 | skip_on_cran() 4 | skip_if_offline() 5 | 6 | repos <- getOption("repos") 7 | if (length(repos) == 0) repos <- character() 8 | repos[repos == "@CRAN@"] <- "http://cran.rstudio.com" 9 | 10 | Sys.unsetenv("R_TESTS") 11 | 12 | lib <- tempfile() 13 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 14 | dir.create(lib) 15 | 16 | # we'll get warnings when CRAN moves binary packages to the 17 | # cran-archive server. 18 | suppressWarnings( 19 | install_cran("pkgconfig", lib = lib, repos = repos, force = TRUE, quiet = TRUE) 20 | ) 21 | 22 | expect_silent(packageDescription("pkgconfig", lib.loc = lib)) 23 | }) 24 | -------------------------------------------------------------------------------- /tests/testthat/test-install-deps.R: -------------------------------------------------------------------------------- 1 | test_that("installing packages with dependencies", { 2 | 3 | skip_on_cran() 4 | skip_if_offline() 5 | skip_if_over_rate_limit() 6 | 7 | Sys.unsetenv("R_TESTS") 8 | 9 | lib <- tempfile() 10 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 11 | dir.create(lib) 12 | 13 | install_github("cran/desc", lib = lib, quiet = TRUE) 14 | 15 | expect_silent(packageDescription("desc", lib.loc = lib)) 16 | expect_equal( 17 | packageDescription("desc", lib.loc = lib)$RemoteRepo, 18 | "desc" 19 | ) 20 | }) 21 | -------------------------------------------------------------------------------- /tests/testthat/test-install-dev.R: -------------------------------------------------------------------------------- 1 | test_that("install_dev works with GitHub URLs", { 2 | skip_on_cran() 3 | skip_if_offline() 4 | 5 | mockery::stub(install_dev, "install_github", identity) 6 | 7 | expect_equal(install_dev("dplyr"), "tidyverse/dplyr") 8 | 9 | expect_equal(install_dev("reprex"), "tidyverse/reprex") 10 | 11 | expect_equal(install_dev("mongolite"), "jeroen/mongolite") 12 | 13 | # only has a GH URL in BugReports 14 | expect_equal(install_dev("digest"), "eddelbuettel/digest") 15 | }) 16 | 17 | test_that("install_dev works with uset CRAN mirrors", { 18 | skip_on_cran() 19 | skip_if_offline() 20 | 21 | mockery::stub(install_dev, "install_github", identity) 22 | 23 | expect_equal(install_dev("dplyr", cran_url = NULL), "tidyverse/dplyr") 24 | 25 | expect_equal(install_dev("dplyr", cran_url = "@CRAN@"), "tidyverse/dplyr") 26 | }) 27 | 28 | test_that("install_dev fails if there is no URL field", { 29 | skip_on_cran() 30 | skip_if_offline() 31 | 32 | expect_error(install_dev("primerTree"), "Could not determine development repository") 33 | }) 34 | 35 | test_that("install_dev fails if there is no URL field with a GitHub, GitLab or Bitbucket URL", { 36 | skip_on_cran() 37 | skip_if_offline() 38 | 39 | expect_error(install_dev("XML"), "Could not determine development repository") 40 | }) 41 | 42 | test_that("install_dev works with Bitbucket URLs", { 43 | skip_on_cran() 44 | skip_if_offline() 45 | 46 | mockery::stub(install_dev, "install_bitbucket", identity) 47 | 48 | expect_equal(install_dev("argparser"), "djhshih/argparser") 49 | }) 50 | -------------------------------------------------------------------------------- /tests/testthat/test-install-gitlab.R: -------------------------------------------------------------------------------- 1 | test_that("install_gitlab", { 2 | 3 | skip_on_cran() 4 | skip_if_offline() 5 | 6 | Sys.unsetenv("R_TESTS") 7 | 8 | lib <- tempfile() 9 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 10 | dir.create(lib) 11 | 12 | install_gitlab("jimhester/falsy", lib = lib, quiet = TRUE) 13 | 14 | expect_silent(packageDescription("falsy", lib.loc = lib)) 15 | expect_equal( 16 | packageDescription("falsy", lib.loc = lib)$RemoteRepo, 17 | "falsy") 18 | 19 | remote <- package2remote("falsy", lib = lib) 20 | expect_s3_class(remote, "remote") 21 | expect_s3_class(remote, "gitlab_remote") 22 | expect_equal(format(remote), "GitLab") 23 | expect_equal(remote$host, "gitlab.com") 24 | expect_equal(remote$username, "jimhester") 25 | expect_equal(remote$repo, "falsy") 26 | expect_equal(remote$ref, "HEAD") 27 | expect_equal(remote$subdir, NULL) 28 | expect_true(!is.na(remote$sha) && nzchar(remote$sha)) 29 | }) 30 | 31 | test_that("install_gitlab with subgroups and special characters", { 32 | 33 | skip_on_cran() 34 | skip_if_offline() 35 | 36 | Sys.unsetenv("R_TESTS") 37 | 38 | lib <- tempfile() 39 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 40 | dir.create(lib) 41 | 42 | install_gitlab("r-lib-grp/my-awesome-group/test.pkg", lib = lib, quiet = TRUE) 43 | 44 | expect_silent(packageDescription("test123", lib.loc = lib)) 45 | expect_equal( 46 | packageDescription("test123", lib.loc = lib)$RemoteRepo, 47 | "my-awesome-group/test.pkg") 48 | 49 | remote <- package2remote("test123", lib = lib) 50 | expect_equal(remote$username, "r-lib-grp") 51 | expect_equal(remote$repo, "my-awesome-group/test.pkg") 52 | expect_equal(remote$subdir, NULL) 53 | 54 | install_gitlab("r-lib-grp/test-pkg", lib = lib, quiet = TRUE) 55 | 56 | expect_silent(packageDescription("test123", lib.loc = lib)) 57 | expect_equal( 58 | packageDescription("test123", lib.loc = lib)$RemoteRepo, 59 | "test-pkg") 60 | 61 | remote <- package2remote("test123", lib = lib) 62 | expect_equal(remote$username, "r-lib-grp") 63 | expect_equal(remote$repo, "test-pkg") 64 | expect_equal(remote$subdir, NULL) 65 | }) 66 | 67 | test_that("error if not username, warning if given as argument", { 68 | 69 | skip_on_cran() 70 | skip_if_offline() 71 | 72 | Sys.unsetenv("R_TESTS") 73 | 74 | lib <- tempfile() 75 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 76 | dir.create(lib) 77 | 78 | expect_error( 79 | install_gitlab("falsy", lib = lib, quiet = TRUE) 80 | ) 81 | }) 82 | 83 | test_that("remote_download.gitlab_remote messages", { 84 | skip_on_cran() 85 | skip_if_offline() 86 | 87 | mockery::stub(remote_download.gitlab_remote, "download", TRUE) 88 | expect_message( 89 | remote_download.gitlab_remote( 90 | remote("gitlab", 91 | host = "https://gitlab.com", 92 | username = "jimhester", 93 | repo = "falsy", 94 | ref = "HEAD" 95 | ) 96 | ), 97 | "Downloading GitLab repo" 98 | ) 99 | }) 100 | 101 | test_that("remote_sha.gitlab_remote", { 102 | 103 | skip_on_cran() 104 | skip_if_offline() 105 | 106 | expect_equal( 107 | remote_sha( 108 | remote("gitlab", 109 | host = "https://gitlab.com", 110 | username = "jimhester", 111 | repo = "falsy", 112 | ref = "1.0" 113 | ) 114 | ), 115 | "0f39d9eb735bf16909831c0bb129063dda388375" 116 | ) 117 | 118 | }) 119 | 120 | test_that("gitlab_project_id", { 121 | 122 | skip_on_cran() 123 | skip_if_offline() 124 | 125 | expect_equal( 126 | gitlab_project_id( 127 | username = "jimhester", 128 | repo = "covr", 129 | host = "https://gitlab.com", 130 | ref = "HEAD" 131 | ), 132 | 1486846 133 | ) 134 | 135 | }) 136 | 137 | -------------------------------------------------------------------------------- /tests/testthat/test-install-local.R: -------------------------------------------------------------------------------- 1 | test_that("install_local", { 2 | 3 | skip_on_cran() 4 | skip_if_offline() 5 | 6 | Sys.unsetenv("R_TESTS") 7 | 8 | lib <- tempfile() 9 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 10 | dir.create(lib) 11 | 12 | dir <- tempfile() 13 | on.exit(unlink(dir), add = TRUE) 14 | dir.create(dir) 15 | 16 | repos <- getOption("repos") 17 | if (length(repos) == 0) repos <- character() 18 | repos[repos == "@CRAN@"] <- "http://cran.rstudio.com" 19 | 20 | pkg <- download.packages("pkgconfig", dir, repos = repos, type = "source", quiet = TRUE) 21 | 22 | install_local(pkg[, 2], lib = lib, quiet = TRUE) 23 | 24 | expect_silent(packageDescription("pkgconfig", lib.loc = lib)) 25 | expect_equal( 26 | packageDescription("pkgconfig", lib.loc = lib)$RemoteType, 27 | "local") 28 | 29 | remote <- package2remote("pkgconfig", lib = lib) 30 | expect_s3_class(remote, "remote") 31 | expect_s3_class(remote, "local_remote") 32 | expect_equal(format(remote), "local") 33 | expect_equal(remote$path, normalizePath(pkg[, 2])) 34 | expect_true(!is.na(remote$sha) && nzchar(remote$sha)) 35 | }) 36 | 37 | test_that("local remotes do not fail if the local install no longer exists", { 38 | 39 | skip_on_cran() 40 | skip_if_offline() 41 | 42 | Sys.unsetenv("R_TESTS") 43 | 44 | lib <- tempfile() 45 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 46 | dir.create(lib) 47 | 48 | dir <- tempfile() 49 | on.exit(unlink(dir, recursive = TRUE), add = TRUE) 50 | dir.create(dir) 51 | 52 | repos <- getOption("repos") 53 | if (length(repos) == 0) repos <- character() 54 | repos[repos == "@CRAN@"] <- "http://cran.rstudio.com" 55 | 56 | pkg <- download.packages("pkgconfig", dir, repos = repos, type = "source", quiet = TRUE) 57 | 58 | install_local(pkg[, 2], lib = lib, quiet = TRUE) 59 | 60 | unlink(dir, recursive = TRUE) 61 | 62 | withr::with_libpaths(lib, 63 | expect_error(update_packages(pkg[, 1], lib = lib, upgrade = TRUE, quiet = TRUE), NA) 64 | ) 65 | }) 66 | -------------------------------------------------------------------------------- /tests/testthat/test-install-remote.R: -------------------------------------------------------------------------------- 1 | test_that("different_sha returns TRUE if remote or local sha is NA not found", { 2 | expect_true(different_sha(remote_sha = NA, local_sha = "4a2ea2")) 3 | expect_true(different_sha(remote_sha = "4a2ea2", local_sha = NA)) 4 | expect_true(different_sha(remote_sha = NA, local_sha = NA)) 5 | }) 6 | 7 | test_that("different_sha returns TRUE if remote_sha and local_sha are different", { 8 | expect_true(different_sha(remote_sha = "5b3fb3", local_sha = "4a2ea2")) 9 | }) 10 | 11 | test_that("different_sha returns FALSE if remote_sha and local_sha are the same", { 12 | expect_false(different_sha(remote_sha = "4a2ea2", local_sha = "4a2ea2")) 13 | }) 14 | 15 | test_that("local_sha returns NA if package is not installed", { 16 | expect_equal(local_sha("tsrtarst"), NA_character_) 17 | }) 18 | 19 | test_that("package2remotes looks for the DESCRIPTION in .libPaths", { 20 | 21 | skip_on_cran() 22 | skip_if_offline() 23 | skip_if_over_rate_limit() 24 | 25 | lib <- tempfile() 26 | dir.create(lib) 27 | expect_equal(package2remote("noremotes", lib = lib)$sha, NA_character_) 28 | 29 | # This is not a real package, so we can't actually build it 30 | install("noremotes", lib = lib, quiet = TRUE, build = FALSE, 31 | dependencies = FALSE, 32 | upgrade = FALSE, 33 | force = FALSE, 34 | build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes"), 35 | repos = getOption("repos"), 36 | type = getOption("pkgType")) 37 | 38 | expect_equal(package2remote("noremotes", lib = lib)$sha, "1.0.0") 39 | 40 | # Load the namespace, as packageDescription looks in loaded namespaces 41 | # first. 42 | withr::with_libpaths(lib, 43 | loadNamespace("noremotes") 44 | ) 45 | 46 | expect_equal(package2remote("noremotes")$sha, NA_character_) 47 | }) 48 | -------------------------------------------------------------------------------- /tests/testthat/test-install-svn.R: -------------------------------------------------------------------------------- 1 | test_that("install_svn subdir", { 2 | 3 | skip_on_cran() 4 | skip_if_offline() 5 | 6 | Sys.unsetenv("R_TESTS") 7 | 8 | lib <- tempfile() 9 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 10 | dir.create(lib) 11 | 12 | mockery::stub( 13 | install_svn, 14 | "install_remotes", 15 | function(remotes, ...) remotes) 16 | 17 | rem <- install_svn( 18 | "https://github.com/dmlc/xgboost/trunk", 19 | subdir = "R-package" 20 | ) 21 | 22 | expect_equal(rem[[1]]$svn_subdir, "R-package") 23 | }) 24 | 25 | test_that("remote_download.svn_remote error", { 26 | 27 | skip_on_cran() 28 | if (Sys.which("svn") == "") skip("Subversion not installed") 29 | 30 | x <- list(url = "http://foo.bar.com") 31 | 32 | mockery::stub(remote_download.svn_remote, "system2", 1) 33 | expect_error( 34 | remote_download.svn_remote(x), 35 | "There seems to be a problem retrieving" 36 | ) 37 | }) 38 | 39 | test_that("downloading a wrong SVN revision", { 40 | 41 | skip_on_cran() 42 | skip_if_offline() 43 | 44 | x <- list( 45 | url = "https://github.com/gaborcsardi/simplegraph/trunk", 46 | revision = "xxx" 47 | ) 48 | 49 | expect_error( 50 | remote_download.svn_remote(x) 51 | ) 52 | }) 53 | 54 | 55 | test_that("svn_path", { 56 | 57 | tmp <- tempfile() 58 | expect_error( 59 | svn_path(tmp), 60 | "does not exist" 61 | ) 62 | 63 | cat("Hello", file = tmp) 64 | expect_equal(svn_path(tmp), tmp) 65 | 66 | mockery::stub(svn_path, "Sys.which", "") 67 | mockery::stub(svn_path, "os_type", "windows") 68 | mockery::stub(svn_path, "file.exists", FALSE) 69 | expect_error( 70 | svn_path(), 71 | "SVN does not seem to be installed on your system" 72 | ) 73 | }) 74 | -------------------------------------------------------------------------------- /tests/testthat/test-install-url.R: -------------------------------------------------------------------------------- 1 | test_that("install_url", { 2 | 3 | skip_on_cran() 4 | skip_if_offline() 5 | 6 | Sys.unsetenv("R_TESTS") 7 | 8 | lib <- tempfile() 9 | on.exit(unlink(lib, recursive = TRUE), add = TRUE) 10 | dir.create(lib) 11 | 12 | url <- "https://github.com/gaborcsardi/simplegraph/archive/HEAD.zip" 13 | install_url(url, lib = lib, quiet = TRUE) 14 | 15 | expect_silent(packageDescription("simplegraph", lib.loc = lib)) 16 | expect_equal( 17 | packageDescription("simplegraph", lib.loc = lib)$RemoteType, 18 | "url") 19 | expect_equal( 20 | trim_ws(packageDescription("simplegraph", lib.loc = lib)$RemoteUrl), 21 | url) 22 | 23 | remote <- package2remote("simplegraph", lib = lib) 24 | expect_s3_class(remote, "remote") 25 | expect_s3_class(remote, "url_remote") 26 | expect_equal(format(remote), "URL") 27 | expect_equal(remote$url, url) 28 | expect_equal(remote$subdir, NULL) 29 | }) 30 | -------------------------------------------------------------------------------- /tests/testthat/test-json.R: -------------------------------------------------------------------------------- 1 | test_that("JSON is standalone", { 2 | ## baseenv() makes sure that the remotes package env is not used 3 | env <- new.env(parent = baseenv()) 4 | env$json <- json 5 | stenv <- env$json$.internal 6 | objs <- ls(stenv, all.names = TRUE) 7 | funs <- Filter(function(x) is.function(stenv[[x]]), objs) 8 | funobjs <- mget(funs, stenv) 9 | 10 | expect_message( 11 | mapply(codetools::checkUsage, funobjs, funs, 12 | MoreArgs = list(report = message)), 13 | NA) 14 | }) 15 | 16 | test_that("JSON parser scalars", { 17 | 18 | expect_equal(json$parse('"foobar"'), "foobar" ) 19 | expect_equal(json$parse('""'), "") 20 | 21 | expect_equal(json$parse("42"), 42) 22 | expect_equal(json$parse("-42"), -42) 23 | expect_equal(json$parse("42.42"), 42.42) 24 | expect_equal(json$parse("1e2"), 1e2) 25 | expect_equal(json$parse("-0.1e-2"), -0.1e-2) 26 | 27 | expect_equal(json$parse('null'), NULL) 28 | expect_equal(json$parse('true'), TRUE) 29 | expect_equal(json$parse('false'), FALSE) 30 | 31 | }) 32 | 33 | test_that("JSON parser arrays", { 34 | 35 | cases <- list( 36 | list("[1,2,3]", list(1,2,3)), 37 | list("[1]", list(1)), 38 | list("[]", list()), 39 | list('["foo"]', list("foo")), 40 | list('["foo", 1, "bar", true]', list("foo", 1, "bar", TRUE)) 41 | ) 42 | 43 | for (c in cases) { 44 | r <- json$parse(c[[1]]) 45 | expect_equal(r, c[[2]], info = c[[1]]) 46 | } 47 | 48 | }) 49 | 50 | test_that("JSON parser nested arrays", { 51 | 52 | cases <- list( 53 | list('[1,2, ["foo", "bar"], 3]', list(1,2, list("foo","bar"), 3)), 54 | list('[ [ [ 1 ] ] ]', list(list(list(1)))), 55 | list('[ [ [ ] ] ]', list(list(list()))) 56 | ) 57 | 58 | for (c in cases) { 59 | r <- json$parse(c[[1]]) 60 | expect_equal(r, c[[2]], info = c[[1]]) 61 | } 62 | 63 | }) 64 | 65 | test_that("JSON parser, real examples", { 66 | 67 | inp <- ' 68 | { 69 | "sha": "e183ccdc515bbb8e7f32d8d16586aed9eea6de0b", 70 | "commit": { 71 | "author": { 72 | "name": "Hadley Wickham", 73 | "email": "h.wickham@gmail.com", 74 | "date": "2015-03-30T13:55:18Z" 75 | }, 76 | "committer": { 77 | "name": "Hadley Wickham", 78 | "email": "h.wickham@gmail.com", 79 | "date": "2015-03-30T13:55:18Z" 80 | }, 81 | "message": "Merge pull request #22 from paulstaab/HEAD\\n\\nImprove error message for assertions of length 0", 82 | "tree": { 83 | "sha": "f2e840b7a134fbc118597842992aa50048e0fa04", 84 | "url": "https://api.github.com/repos/hadley/assertthat/git/trees/f2e840b7a134fbc118597842992aa50048e0fa04" 85 | }, 86 | "url": "https://api.github.com/repos/hadley/assertthat/git/commits/e183ccdc515bbb8e7f32d8d16586aed9eea6de0b", 87 | "comment_count": 0 88 | } 89 | }' 90 | 91 | exp <- list( 92 | sha = "e183ccdc515bbb8e7f32d8d16586aed9eea6de0b", 93 | commit = list( 94 | author = list( 95 | name = "Hadley Wickham", 96 | email = "h.wickham@gmail.com", 97 | date = "2015-03-30T13:55:18Z"), 98 | committer = list( 99 | name = "Hadley Wickham", 100 | email = "h.wickham@gmail.com", 101 | date = "2015-03-30T13:55:18Z"), 102 | message = "Merge pull request #22 from paulstaab/HEAD\\n\\nImprove error message for assertions of length 0", 103 | tree = list( 104 | sha = "f2e840b7a134fbc118597842992aa50048e0fa04", 105 | url = "https://api.github.com/repos/hadley/assertthat/git/trees/f2e840b7a134fbc118597842992aa50048e0fa04" 106 | ), 107 | url = "https://api.github.com/repos/hadley/assertthat/git/commits/e183ccdc515bbb8e7f32d8d16586aed9eea6de0b", 108 | comment_count = 0 109 | ) 110 | ) 111 | 112 | expect_equal(json$parse(inp), exp) 113 | 114 | }) 115 | 116 | test_that("JSON parser, errors", { 117 | 118 | expect_error( 119 | json$parse("[1,2,3,"), 120 | "EXPECTED value GOT EOF" 121 | ) 122 | 123 | expect_error( 124 | json$parse('{ 123: "foo" }'), 125 | "EXPECTED string GOT 123" 126 | ) 127 | 128 | expect_error( 129 | json$parse('{ "foo" "foobar" }'), 130 | 'EXPECTED : GOT "foobar"' 131 | ) 132 | 133 | expect_error( 134 | json$parse('{ "foo": "foobar" "foo2": "foobar2" }'), 135 | 'EXPECTED , or } GOT "foo2"' 136 | ) 137 | 138 | expect_error( 139 | json$parse('[1,2,3 4]'), 140 | 'EXPECTED , GOT 4' 141 | ) 142 | 143 | }) 144 | 145 | test_that("get_json_sha", { 146 | 147 | inp <- ' 148 | { 149 | "sha": "e183ccdc515bbb8e7f32d8d16586aed9eea6de0b", 150 | "author": { 151 | "name": "Hadley Wickham", 152 | "email": "h.wickham@gmail.com", 153 | "date": "2015-03-30T13:55:18Z" 154 | }, 155 | }' 156 | 157 | expect_identical( 158 | get_json_sha(inp), 159 | "e183ccdc515bbb8e7f32d8d16586aed9eea6de0b") 160 | 161 | inp2 <- ' 162 | { 163 | "sha": 164 | "e183ccdc515bbb8e7f32d8d16586aed9eea6de0b", 165 | "author": { 166 | "name": "Hadley Wickham", 167 | "email": "h.wickham@gmail.com", 168 | "date": "2015-03-30T13:55:18Z" 169 | }, 170 | }' 171 | 172 | expect_identical( 173 | get_json_sha(inp2), 174 | "e183ccdc515bbb8e7f32d8d16586aed9eea6de0b") 175 | 176 | inp3 <- ' 177 | { 178 | "nosha": 179 | "e183ccdc515bbb8e7f32d8d16586aed9eea6de0b", 180 | "author": { 181 | "name": "Hadley Wickham", 182 | "email": "h.wickham@gmail.com", 183 | "date": "2015-03-30T13:55:18Z" 184 | }, 185 | }' 186 | 187 | expect_identical( 188 | get_json_sha(inp3), 189 | NA_character_) 190 | }) 191 | -------------------------------------------------------------------------------- /tests/testthat/test-package-deps.R: -------------------------------------------------------------------------------- 1 | test_that("parse_deps", { 2 | expect_null(parse_deps(NULL)) 3 | expect_null(parse_deps("")) 4 | expect_null(parse_deps(" ")) 5 | expect_null(parse_deps("\n")) 6 | 7 | expect_equal( 8 | parse_deps("devtools (>= 1.0.1)"), 9 | structure( 10 | list( 11 | name = "devtools", 12 | compare = ">=", 13 | version = "1.0.1" 14 | ), 15 | row.names = 1L, 16 | class = "data.frame" 17 | ) 18 | ) 19 | 20 | expect_equal( 21 | parse_deps("devtools (>= 1.0.1), foobar, foobar2 (== 0.0.1)"), 22 | structure( 23 | list( 24 | name = c("devtools", "foobar", "foobar2"), 25 | compare = c(">=", NA, "=="), 26 | version = c("1.0.1", NA, "0.0.1") 27 | ), 28 | row.names = 1:3, 29 | class = "data.frame" 30 | ) 31 | ) 32 | 33 | # Whitespace should be ignored 34 | expect_equal( 35 | parse_deps("devtools (>= 1.0.1) \n, foobar, foobar2 ( == 0.0.1 )"), 36 | structure( 37 | list( 38 | name = c("devtools", "foobar", "foobar2"), 39 | compare = c(">=", NA, "=="), 40 | version = c("1.0.1", NA, "0.0.1") 41 | ), 42 | row.names = 1:3, 43 | class = "data.frame" 44 | ) 45 | ) 46 | 47 | expect_equal( 48 | parse_deps("package (>= 1.0.1) , package2 (< 0.0.1 ) "), 49 | structure( 50 | list( 51 | name = c("package", "package2"), 52 | compare = c(">=", "<"), 53 | version = c("1.0.1", "0.0.1") 54 | ), 55 | row.names = 1:2, 56 | class = "data.frame" 57 | ) 58 | ) 59 | }) 60 | -------------------------------------------------------------------------------- /tests/testthat/test-package.R: -------------------------------------------------------------------------------- 1 | test_that("load_pkg_description", { 2 | pkg <- load_pkg_description("noremotes") 3 | expect_equal(pkg$package, "noremotes") 4 | }) 5 | 6 | test_that("load_pkg_description tarball", { 7 | 8 | skip_on_cran() 9 | skip_if_offline() 10 | 11 | repos <- getOption("repos") 12 | if (length(repos) == 0) repos <- character() 13 | repos[repos == "@CRAN@"] <- "http://cran.rstudio.com" 14 | 15 | tmp_dir <- tempfile() 16 | dir.create(tmp_dir) 17 | on.exit(unlink(tmp_dir, recursive = TRUE)) 18 | 19 | out <- download.packages("pkgconfig", repos = repos, destdir = tmp_dir, quiet = TRUE)[[2]] 20 | 21 | pkg <- load_pkg_description(out) 22 | 23 | expect_equal(pkg$package, "pkgconfig") 24 | }) 25 | -------------------------------------------------------------------------------- /tests/testthat/test-parse-git.R: -------------------------------------------------------------------------------- 1 | test_that("pull request and latest release, via spec and URL", { 2 | 3 | expect_equal( 4 | parse_git_repo("r-lib/remotes#7")$ref, 5 | github_pull("7") 6 | ) 7 | expect_equal( 8 | parse_git_repo("https://github.com/r-lib/remotes/pull/7")$ref, 9 | github_pull("7") 10 | ) 11 | 12 | expect_equal( 13 | parse_git_repo("r-lib/remotes@*release")$ref, 14 | github_release() 15 | ) 16 | expect_equal( 17 | parse_git_repo("https://github.com/r-lib/remotes/releases/latest")$ref, 18 | github_release() 19 | ) 20 | }) 21 | 22 | test_that("parse_repo_spec trailing slash, issue #54", { 23 | expect_equal( 24 | parse_repo_spec("foo/bar/baz/"), 25 | parse_repo_spec("foo/bar/baz") 26 | ) 27 | }) 28 | 29 | test_that("parse_github_url() accepts all forms of URL (github.com and GHE)", { 30 | ## HTTPS 31 | expect_identical( 32 | parse_github_url("https://github.com/r-lib/remotes.git"), 33 | list(username = "r-lib", repo = "remotes", ref = "", pull = "", release = "") 34 | ) 35 | expect_identical( 36 | parse_github_url("https://github.ubc.ca/user/repo.git"), 37 | list(username = "user", repo = "repo", ref = "", pull = "", release = "") 38 | ) 39 | 40 | ## SSH 41 | expect_identical( 42 | parse_github_url("git@github.com:r-lib/remotes.git"), 43 | list(username = "r-lib", repo = "remotes", ref = "", pull = "", release = "") 44 | ) 45 | expect_identical( 46 | parse_github_url("git@github.ubc.ca:user/repo.git"), 47 | list(username = "user", repo = "repo", ref = "", pull = "", release = "") 48 | ) 49 | 50 | ## browser URLs 51 | expect_identical( 52 | parse_github_url("https://github.com/r-lib/remotes"), 53 | list(username = "r-lib", repo = "remotes", ref = "", pull = "", release = "") 54 | ) 55 | expect_identical( 56 | parse_github_url("https://github.ubc.ca/user/repo"), 57 | list(username = "user", repo = "repo", ref = "", pull = "", release = "") 58 | ) 59 | 60 | expect_identical( 61 | parse_github_url("https://github.com/r-lib/remotes/tree/i-am-a-branch"), 62 | list(username = "r-lib", repo = "remotes", ref = "i-am-a-branch", pull = "", release = "") 63 | ) 64 | expect_identical( 65 | parse_github_url("https://github.com/r-lib/remotes/commit/1234567"), 66 | list(username = "r-lib", repo = "remotes", ref = "1234567", pull = "", release = "") 67 | ) 68 | expect_identical( 69 | parse_github_url("https://github.com/r-lib/remotes/pull/108"), 70 | list(username = "r-lib", repo = "remotes", ref = "", pull = "108", release = "") 71 | ) 72 | expect_identical( 73 | parse_github_url("https://github.com/r-lib/remotes/releases/tag/1.0.0"), 74 | list(username = "r-lib", repo = "remotes", ref = "1.0.0", pull = "", release = "") 75 | ) 76 | expect_identical( 77 | parse_github_url("https://github.com/r-lib/remotes/releases/latest"), 78 | list(username = "r-lib", repo = "remotes", ref = "", pull = "", release = "*release") 79 | ) 80 | }) 81 | 82 | test_that("parse_repo_spec catches invalid spec", { 83 | expect_error( 84 | parse_repo_spec("/$&@R64&3"), 85 | "Invalid git repo specification" 86 | ) 87 | }) 88 | 89 | test_that("parse_repo_spec, github", { 90 | 91 | cases <- list( 92 | list("user/repo"), 93 | list("pkg=user/repo", package = "pkg"), 94 | list("pkg=user/repo", package = "pkg"), 95 | list("user/repo/subdir", subdir = "subdir"), 96 | list("user/repo@badcafe", ref = "badcafe"), 97 | list("user/repo#123", ref = github_pull("123")), 98 | list("user/repo@*release", ref = github_release()), 99 | list("pkg=user/repo/subdir", package = "pkg", subdir = "subdir"), 100 | list("pkg=user/repo@badcafe", package = "pkg", ref = "badcafe"), 101 | list("pkg=user/repo#123", package = "pkg", ref = github_pull("123")), 102 | list("pkg=user/repo@*release", package = "pkg", ref = github_release()), 103 | 104 | # github url cases 105 | list("git@github.com:user/repo.git"), 106 | list("git@github.ubc.ca:user/repo.git"), 107 | list("https://github.com/user/repo"), 108 | list("https://github.ubc.ca/user/repo"), 109 | list("https://github.com/user/repo/tree/i-am-a-branch", ref = "i-am-a-branch"), 110 | list("https://github.com/user/repo/commit/1234567", ref = "1234567"), 111 | list("https://github.com/user/repo/pull/108", ref = github_pull("108")), 112 | list("https://github.com/user/repo/releases/tag/1.0.0", ref = "1.0.0"), 113 | list("https://github.com/user/repo/releases/latest", ref = github_release()), 114 | list("https://github.com/user/repo/releases/latest", ref = github_release()), 115 | list("https://github.com/foo/bar", username = "foo", repo = "bar"), 116 | list("git@github.com:foo/bar.git", username = "foo", repo = "bar"), 117 | 118 | # Username and repo can have hyphens in them 119 | list("git@github.com:foo-bar/baz-qux.git", username = "foo-bar", repo = "baz-qux") 120 | ) 121 | 122 | for (case in cases) { 123 | expect_equal_named_lists( 124 | p <- parse_git_repo(case[[1]]), 125 | utils::modifyList( 126 | list(username = "user", repo = "repo"), 127 | case[-1] 128 | ) 129 | ) 130 | } 131 | }) 132 | 133 | test_that("parse_git_repo errors on invalid GitHub input", { 134 | expect_error(parse_git_repo("https://github.com/r-lib"), "Invalid GitHub URL") 135 | }) 136 | -------------------------------------------------------------------------------- /tests/testthat/test-script.R: -------------------------------------------------------------------------------- 1 | test_that("install-github.R script is up to date", { 2 | skip_if(covr::in_covr()) 3 | skip_on_cran() 4 | 5 | root <- system.file(package = packageName()) 6 | tmp <- test_temp_file(".R") 7 | 8 | withr::with_dir( 9 | test_package_root(), 10 | brew::brew(file.path(root, "install-github.Rin"), tmp)) 11 | 12 | expect_equal( 13 | readLines(tmp), 14 | readLines(file.path(root, "install-github.R"))) 15 | }) 16 | 17 | test_that("use install-github.R script", { 18 | skip_on_cran() 19 | skip_if_offline() 20 | skip_if_over_rate_limit() 21 | 22 | script <- system.file(package = packageName(), "install-github.R") 23 | lib <- test_temp_dir() 24 | expect_error( 25 | source(script)$value("cran/falsy", lib = lib, quiet = TRUE), 26 | NA) 27 | expect_equal( 28 | packageDescription("falsy", lib.loc = lib)$RemoteRepo, 29 | "falsy") 30 | }) 31 | 32 | test_that("install-github.R script does not load any package", { 33 | skip_on_cran() 34 | skip_if_offline() 35 | skip_if_over_rate_limit() 36 | 37 | script <- system.file(package = packageName(), "install-github.R") 38 | lib <- test_temp_dir() 39 | 40 | pkgs <- callr::r( 41 | function(script, lib) { 42 | ## compiler and tools are ok to load 43 | library(compiler) 44 | library(tools) 45 | orig <- loadedNamespaces() 46 | 47 | source(script)$value("cran/falsy", lib = lib) 48 | 49 | new <- loadedNamespaces() 50 | 51 | ## Need to load curl on R < 3.2.0, for HTTPS, so we ignore this 52 | if (getRversion() < "3.2.0") new <- setdiff(new, "curl") 53 | list(orig, new) 54 | }, 55 | args = list(script = script, lib = lib), 56 | cmdargs = c("--vanilla", "--slave", "--no-save", "--no-restore"), 57 | timeout = 60 58 | ) 59 | 60 | expect_equal(pkgs[[1]], pkgs[[2]]) 61 | }) 62 | -------------------------------------------------------------------------------- /tests/testthat/test-submodule.R: -------------------------------------------------------------------------------- 1 | test_that("parse_submodules works with a single submodule", { 2 | x <- 3 | '[submodule "foobar"] 4 | path = baz 5 | url = http://foo/bar' 6 | 7 | expect_equal( 8 | parse_submodules(x), 9 | data.frame( 10 | submodule = "foobar", 11 | path = "baz", 12 | url = "http://foo/bar", 13 | branch = NA_character_, 14 | stringsAsFactors = FALSE)) 15 | }) 16 | 17 | test_that("parse_submodules works multiple submodules", { 18 | y <- 19 | '[submodule "foobar"] 20 | path = baz 21 | url = http://foo/bar 22 | 23 | [submodule "foofoo"] 24 | path = bunny 25 | url = http://little/bunny/foofoo 26 | branch = forest' 27 | 28 | expect_equal( 29 | parse_submodules(y), 30 | data.frame( 31 | submodule = c("foobar", "foofoo"), 32 | path = c("baz", "bunny"), 33 | url = c("http://foo/bar", "http://little/bunny/foofoo"), 34 | branch = c(NA_character_, "forest"), 35 | stringsAsFactors = FALSE)) 36 | }) 37 | 38 | test_that("parse_submodules warns and returns empty for invalid submodules", { 39 | x <- 40 | '[submodule "foobar"] 41 | path = baz' 42 | 43 | expect_warning(regexp = "Invalid submodule definition", 44 | expect_equal( 45 | parse_submodules(x), 46 | list() 47 | ) 48 | ) 49 | 50 | y <- 51 | '[submodule "foobar"] 52 | path = baz 53 | 54 | [submodule "foofoo"] 55 | path = bunny 56 | url = http://little/bunny/foofoo' 57 | 58 | expect_warning(regexp = "Invalid submodule definition", 59 | expect_equal( 60 | parse_submodules(y), 61 | list() 62 | ) 63 | ) 64 | 65 | z <- ' 66 | # [submodule "foobar"] this one is commented out 67 | # path = baz 68 | # url = https://foo/bar' 69 | 70 | expect_equal( 71 | parse_submodules(z), 72 | list() 73 | ) 74 | }) 75 | 76 | test_that("Can install a repo with a submodule", { 77 | 78 | if (is.null(git_path())) skip("git is not installed") 79 | 80 | dir <- tempfile() 81 | dir.create(dir) 82 | on.exit(unlink(dir, recursive = TRUE, force = TRUE)) 83 | writeLines("foo <- 1", file.path(dir, "foo.R")) 84 | 85 | in_dir(dir, { 86 | git("init") 87 | git(paste("add", "-A", ".")) 88 | git(paste( 89 | # We need to temporarily set the user name and user email, 90 | # in case they are not set 91 | "-c", "user.name=foobar", "-c", paste0("user.email=", shQuote("<>")), 92 | "commit", "-m", shQuote("Initial commit"))) 93 | }) 94 | 95 | sub <- tempfile() 96 | dir.create(sub) 97 | on.exit(unlink(sub,recursive=TRUE,force=TRUE),add=TRUE) 98 | 99 | module <- file.path(sub, ".gitmodules") 100 | 101 | writeLines(con = module, 102 | sprintf( 103 | '[submodule "foo"] 104 | path = R 105 | url = file://%s 106 | [submodule "bar"] 107 | path = bar 108 | url = file://%s', 109 | URLencode(dir), 110 | URLencode(dir) 111 | ) 112 | ) 113 | 114 | # The bar submodule is in .Rbuildignore, so we will not fetch it 115 | build_ignore <- file.path(sub, ".Rbuildignore") 116 | writeLines("^bar$", build_ignore) 117 | 118 | 119 | update_submodules(sub, NULL, quiet = TRUE) 120 | expect_true(dir.exists(file.path(sub, "R"))) 121 | expect_false(dir.exists(file.path(sub, "bar"))) 122 | 123 | # Now remove the R directory so we can try installing the full package 124 | unlink(file.path(sub, "R"), recursive = TRUE, force = TRUE) 125 | 126 | # Install the package to a temporary library and verify it works 127 | lib <- tempfile() 128 | on.exit(unlink(lib, recursive = TRUE, force = TRUE), add = TRUE) 129 | dir.create(lib) 130 | 131 | DESC_file <- file.path(sub,"DESCRIPTION") 132 | writeLines("Package: submodule\nVersion: 0.0.0.9000",DESC_file) 133 | 134 | install_local(sub, lib = lib, quiet = TRUE) 135 | withr::with_libpaths(lib, 136 | expect_equal(submodule::foo, 1) 137 | ) 138 | }) 139 | 140 | test_that("Can update a submodule with an empty .gitmodules submodule", { 141 | 142 | if (is.null(git_path())) skip("git is not installed") 143 | 144 | dir <- tempfile() 145 | dir.create(dir) 146 | on.exit(unlink(dir, recursive = TRUE, force = TRUE)) 147 | 148 | sub <- tempfile() 149 | dir.create(sub) 150 | on.exit(unlink(sub, recursive=TRUE, force=TRUE), add=TRUE) 151 | 152 | module <- file.path(sub, ".gitmodules") 153 | 154 | writeLines(con = module,text = "") 155 | 156 | # The bar submodule is in .Rbuildignore, so we will not fetch it 157 | build_ignore <- file.path(sub, ".Rbuildignore") 158 | 159 | writeLines("^bar$", build_ignore) 160 | 161 | expect_error( 162 | update_submodules(sub, NULL, quiet = TRUE), 163 | NA 164 | ) 165 | }) 166 | -------------------------------------------------------------------------------- /tests/testthat/test-system.R: -------------------------------------------------------------------------------- 1 | test_that("system_check", { 2 | 3 | mockery::stub(system_check, "system2", structure("output", status = 1)) 4 | expect_error( 5 | system_check("foobar", args = c("arg1", "arg2", quiet = TRUE)), 6 | "Command foobar failed" 7 | ) 8 | 9 | mockery::stub(system_check, "system2", 42) 10 | expect_error( 11 | system_check("foobar", args = c("arg1", "arg2", quiet = FALSE)), 12 | "Command foobar failed" 13 | ) 14 | }) 15 | -------------------------------------------------------------------------------- /tests/testthat/test-utils.R: -------------------------------------------------------------------------------- 1 | test_that("%||%", { 2 | expect_equal(NULL %||% "foo", "foo") 3 | expect_equal("foo" %||% "bar", "foo") 4 | expect_equal(NULL %||% NULL, NULL) 5 | }) 6 | 7 | test_that("trim_ws", { 8 | expect_equal(trim_ws("foobar"), "foobar") 9 | expect_equal(trim_ws(" foobar"), "foobar") 10 | expect_equal(trim_ws(" foobar"), "foobar") 11 | expect_equal(trim_ws("foobar "), "foobar") 12 | expect_equal(trim_ws("foobar "), "foobar") 13 | expect_equal(trim_ws(" foobar "), "foobar") 14 | expect_equal(trim_ws(" foobar "), "foobar") 15 | 16 | expect_equal(trim_ws(character()), character()) 17 | 18 | expect_equal(trim_ws(c("1", "2")), c("1", "2")) 19 | expect_equal(trim_ws(c(" 1", "2")), c("1", "2")) 20 | expect_equal(trim_ws(c("1 ", "2")), c("1", "2")) 21 | expect_equal(trim_ws(c(" 1 ", " 2")), c("1", "2")) 22 | expect_equal(trim_ws(c("1", " 2 ")), c("1", "2")) 23 | expect_equal(trim_ws(c("1 ", "2 ")), c("1", "2")) 24 | expect_equal(trim_ws(c("1 ", " 2")), c("1", "2")) 25 | }) 26 | 27 | test_that("is_bioconductor", { 28 | 29 | D <- load_pkg_description(test_path("Biobase")) 30 | expect_true(is_bioconductor(D)) 31 | 32 | D <- load_pkg_description(test_path("MASS")) 33 | expect_false(is_bioconductor(D)) 34 | 35 | }) 36 | 37 | test_that("pkg_installed", { 38 | 39 | expect_true(pkg_installed("methods")) 40 | expect_false(pkg_installed("there-is-no-such-package")) 41 | 42 | if (pkg_installed("codetools")) { 43 | tryCatch( 44 | { 45 | unloadNamespace("codetools") 46 | expect_true(pkg_installed("codetools")) 47 | expect_false("codetools" %in% loadedNamespaces()) 48 | }, 49 | error = function(e) { } 50 | ) 51 | } 52 | 53 | }) 54 | 55 | test_that("in_dir", { 56 | 57 | tmp <- tempfile() 58 | dir.create(tmp) 59 | 60 | ## We need the basename, because of the symbolic links 61 | 62 | wd <- getwd() 63 | expect_equal( 64 | basename(in_dir(tmp, getwd())), 65 | basename(tmp) 66 | ) 67 | expect_equal(getwd(), wd) 68 | 69 | in_dir2 <- with_something(setwd) 70 | wd <- getwd() 71 | expect_equal( 72 | basename(in_dir2(tmp, getwd())), 73 | basename(tmp) 74 | ) 75 | expect_equal(getwd(), wd) 76 | 77 | }) 78 | 79 | # Adapted from https://github.com/gisle/mime-base64/blob/cf23d49e517c6ed8f4b24295f63721e8c9935010/t/base64.t 80 | test_that("base64_decode", { 81 | 82 | decode_tests <- c( 83 | 'YWE=' = 'aa', 84 | ' YWE=' = 'aa', 85 | 'Y WE=' = 'aa', 86 | 'YWE= ' = 'aa', 87 | "Y\nW\r\nE=" = 'aa', 88 | 'YWE=====' = 'aa', # extra padding 89 | 'YWE' = 'aa', # missing padding 90 | 'YWFh====' = 'aaa', 91 | 'YQ' = 'a', 92 | 'Y' = '', 93 | 'x==' = '' 94 | ) 95 | 96 | for (i in seq_along(decode_tests)) { 97 | encoded <- names(decode_tests)[[i]] 98 | expected <- decode_tests[[i]] 99 | 100 | decoded <- base64_decode(encoded) 101 | expect_equal(decoded, expected) 102 | } 103 | }) 104 | 105 | test_that("windows untar, --force-local errors", { 106 | do <- function(has, tar_result) { 107 | withr::local_envvar(c(TAR = "")) 108 | calls <- 0 109 | mockery::stub(untar, "system2", if (has) "--force-local" else "nah") 110 | mockery::stub(untar, "os_type", "windows") 111 | mockery::stub(untar, "utils::untar", function(extras, ...) { 112 | calls <<- calls + 1L 113 | if (grepl("force-local", extras)) tar_result() else "ok" 114 | }) 115 | 116 | expect_equal(untar("foobar"), "ok") 117 | expect_equal(calls, 1 + has) 118 | } 119 | 120 | ## Has force-local but tar fails with it 121 | do(TRUE, function() stop("failed")) 122 | do(TRUE, function() 1L) 123 | do(TRUE, function() structure("blah", status = 1L)) 124 | 125 | ## Does not have force-local 126 | do(FALSE, function() stop("failed")) 127 | do(FALSE, function() 1L) 128 | do(FALSE, function() structure("blah", status = 1L)) 129 | }) 130 | 131 | test_that("directories works", { 132 | expect_equal(directories("foo"), character()) 133 | expect_equal(directories("foo/bar"), "foo") 134 | expect_equal(sort(directories("foo/bar/baz")), 135 | sort(c("foo", "foo/bar"))) 136 | 137 | expect_equal(directories(c("foo/bar", "foo/baz")), "foo") 138 | 139 | expect_equal(sort(directories(c("foo/bar/baz", "foo2/1", "foo3/bar/3"))), 140 | sort(c("foo", "foo/bar", "foo2", "foo3", "foo3/bar"))) 141 | }) 142 | 143 | test_that("in_r_build_ignore works", { 144 | tf <- tempfile() 145 | on.exit(unlink(tf)) 146 | writeLines( 147 | c("^foo$", 148 | "^blah/xyz" 149 | ), tf) 150 | 151 | expect_equal( 152 | unname( 153 | in_r_build_ignore(c("foo/bar/baz", "R/test.R"), tf) 154 | ), 155 | c(TRUE, FALSE) 156 | ) 157 | 158 | expect_equal( 159 | unname( 160 | in_r_build_ignore(c("foo", "blah", "blah/abc", "blah/xyz", "R/test.R"), tf) 161 | ), 162 | c(TRUE, FALSE, FALSE, TRUE, FALSE) 163 | ) 164 | }) 165 | 166 | test_that("dev_split_ref works", { 167 | expect_equal(dev_split_ref("DT")[["pkg"]], "DT") 168 | expect_equal(dev_split_ref("remotes")[["ref"]], "") 169 | expect_equal(dev_split_ref("with.dot")[["pkg"]], "with.dot") 170 | expect_equal(dev_split_ref("with2")[["pkg"]], "with2") 171 | expect_equal(dev_split_ref("with@v1.2.1")[["ref"]], "@v1.2.1") 172 | expect_equal(dev_split_ref("with@v1.0.0.999")[["ref"]], "@v1.0.0.999") 173 | expect_equal(dev_split_ref("with@v1.0.0.999")[["pkg"]], "with") 174 | expect_equal(dev_split_ref("with#279")[["ref"]], "#279") 175 | expect_equal(dev_split_ref("with#1")[["pkg"]], "with") 176 | }) 177 | -------------------------------------------------------------------------------- /tests/testthat/urlremotes/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: noremotes 2 | Title: Tools to make developing R code easier 3 | License: MIT 4 | Description: Package description. 5 | Author: Bugs Bunny 6 | Maintainer: Bugs Bunny 7 | Version: 1.0.0 8 | Suggests: testthat 9 | Imports: 10 | example, 11 | dtplyr 12 | Remotes: 13 | url::https://www.example.com/, 14 | url::https://github.com/tidyverse/dtplyr 15 | 16 | -------------------------------------------------------------------------------- /tests/testthat/withremotes/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: noremotes 2 | Title: Tools to make developing R code easier 3 | License: MIT 4 | Description: Package description. 5 | Author: Bugs Bunny 6 | Maintainer: Bugs Bunny 7 | Version: 1.0.0 8 | Suggests: testthat 9 | Imports: 10 | falsy 11 | Remotes: 12 | cran/falsy 13 | Config/Needs/coverage: covr 14 | Config/Needs/pkgdown: r-lib/pkgdown, tidyverse/tidytemplate 15 | -------------------------------------------------------------------------------- /vignettes/dependencies.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Dependency resolution for R package development" 3 | author: "Jim Hester, Hadley Wickham, Gábor Csárdi" 4 | date: "`r Sys.Date()`" 5 | output: 6 | rmarkdown::html_vignette: 7 | keep_md: true 8 | vignette: > 9 | %\VignetteIndexEntry{Dependency resolution for R package development} 10 | %\VignetteEngine{knitr::rmarkdown} 11 | %\VignetteEncoding{UTF-8} 12 | --- 13 | 14 | # Package remotes 15 | 16 | Remotes, just like devtools, supports package dependency installation for packages not 17 | yet in a standard package repository such as [CRAN](https://cran.r-project.org) 18 | or [Bioconductor](https://bioconductor.org). 19 | 20 | You can mark any regular dependency defined in the `Depends`, `Imports`, 21 | `Suggests` or `Enhances` fields as being installed from a remote location by 22 | adding the remote location to `Remotes` in your `DESCRIPTION` file. This will 23 | cause remotes to download and install them from the specified location, 24 | instead of CRAN. 25 | 26 | The remote dependencies specified in `Remotes` should be described in the following form. 27 | 28 | ``` 29 | Remotes: [type::], [type2::] 30 | ``` 31 | 32 | The `type` is an optional parameter. If the type is missing the default is 33 | to install from GitHub. Additional remote dependencies should be separated by 34 | commas, just like normal dependencies elsewhere in the `DESCRIPTION` file. 35 | 36 | ### GitHub 37 | 38 | Because GitHub is the most commonly used unofficial package distribution in R, it's the default: 39 | 40 | ```yaml 41 | Remotes: r-lib/testthat 42 | ``` 43 | 44 | You can also specify a specific hash, tag, or pull request (using the same syntax as `install_github()` if you want a particular commit. Otherwise the latest commit on the default branch is used. 45 | 46 | ```yaml 47 | Remotes: r-lib/httr@v0.4, 48 | klutometis/roxygen#142, 49 | r-lib/testthat@c67018fa4970 50 | ``` 51 | 52 | The special `@*release` syntax will install the latest release: 53 | 54 | ```yaml 55 | Remotes: r-lib/testthat@*release 56 | ``` 57 | 58 | A type of 'github' can be specified, but is not required 59 | 60 | ```yaml 61 | Remotes: github::tidyverse/ggplot2 62 | ``` 63 | 64 | ### Other sources 65 | 66 | All of the currently supported install sources are available, see the 'See 67 | Also' section in `?install_github` for a complete list. 68 | 69 | ```yaml 70 | # GitLab 71 | Remotes: gitlab::jimhester/covr 72 | 73 | # Git 74 | Remotes: git::git@bitbucket.org:djnavarro/lsr.git, 75 | git::https://github.com/igraph/rigraph.git@main 76 | 77 | # Bitbucket 78 | Remotes: bitbucket::sulab/mygene.r@default, djnavarro/lsr 79 | 80 | # Bioconductor 81 | Remotes: bioc::3.3/SummarizedExperiment#117513, bioc::release/Biobase 82 | 83 | # SVN 84 | Remotes: svn::https://github.com/tidyverse/stringr 85 | 86 | # URL 87 | Remotes: url::https://github.com/tidyverse/stringr/archive/HEAD.zip 88 | 89 | # Local 90 | Remotes: local::/pkgs/testthat 91 | ``` 92 | 93 | ### CRAN submission 94 | 95 | When you submit your package to CRAN, all of its dependencies must also be available on CRAN. For this reason, `devtools::release()` will warn you if you try to release a package with a `Remotes` field. 96 | --------------------------------------------------------------------------------