Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Homebrew/brew
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2.5.1
Choose a base ref
...
head repository: Homebrew/brew
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2.5.2
Choose a head ref

Commits on Sep 12, 2020

  1. Support bottle uploads to GitHub Releases

    Co-authored-by: Mike McQuaid <mike@mikemcquaid.com>
    dawidd6 and MikeMcQuaid committed Sep 12, 2020

    Partially verified

    This commit is signed with the committer’s verified signature.
    dawidd6’s contribution has been verified via GPG key.
    We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
    Copy the full SHA
    f6601ce View commit details

Commits on Sep 14, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e66227c View commit details
  2. Merge pull request #8720 from Homebrew/dependabot/bundler/Library/Hom…

    …ebrew/rubocop-ast-0.4.0
    
    build(deps): bump rubocop-ast from 0.3.0 to 0.4.0 in /Library/Homebrew
    MikeMcQuaid authored Sep 14, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c42146a View commit details
  3. Copy the full SHA
    e4356e8 View commit details
  4. Copy the full SHA
    b72e7ee View commit details
  5. Copy the full SHA
    c098ce5 View commit details
  6. Merge pull request #8719 from reitermarkus/cask-audit-errors

    Refactor `cask audit` warnings.
    reitermarkus authored Sep 14, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7589a35 View commit details

Commits on Sep 15, 2020

  1. Copy the full SHA
    5f0a55a View commit details
  2. Merge pull request #8722 from Homebrew/tapioca-update

    sorbet: update RBI files using Tapioca.
    MikeMcQuaid authored Sep 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fe40bd5 View commit details
  3. Merge pull request #8410 from dawidd6/github-releases

    Support bottle uploads to GitHub Releases
    dawidd6 authored Sep 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    14741e3 View commit details
  4. pr-pull: don't require bintray credentials to be set

    It blocks uploading to GitHub Releases where Bintray credentials are not needed.
    Also those checks are already performed in `bintray.rb`.
    dawidd6 committed Sep 15, 2020

    Verified

    This commit was signed with the committer’s verified signature.
    dawidd6 Dawid Dziurla
    Copy the full SHA
    0bf491b View commit details
  5. build(deps): bump rubocop from 0.90.0 to 0.91.0 in /Library/Homebrew

    Bumps [rubocop](https://github.com/rubocop-hq/rubocop) from 0.90.0 to 0.91.0.
    - [Release notes](https://github.com/rubocop-hq/rubocop/releases)
    - [Changelog](https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md)
    - [Commits](rubocop/rubocop@v0.90.0...v0.91.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored and MikeMcQuaid committed Sep 15, 2020

    Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    0c036a7 View commit details
  6. tapioca sync

    MikeMcQuaid committed Sep 15, 2020

    Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    828eb0b View commit details
  7. Fix brew style

    MikeMcQuaid committed Sep 15, 2020

    Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    3923d33 View commit details
  8. Merge pull request #8725 from Homebrew/dependabot/bundler/Library/Hom…

    …ebrew/rubocop-0.91.0
    
    build(deps): bump rubocop from 0.90.0 to 0.91.0 in /Library/Homebrew
    MikeMcQuaid authored Sep 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6e59c75 View commit details
  9. Merge pull request #8727 from dawidd6/pr-pull-gh-rel

    pr-pull: don't require bintray credentials to be set
    dawidd6 authored Sep 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1700214 View commit details
  10. Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    9943b3e View commit details
  11. Merge pull request #8728 from MikeMcQuaid/xquartz-prefix

    xquartz: unprivate prefix.
    MikeMcQuaid authored Sep 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    03bba5a View commit details
  12. Copy the full SHA
    01e4696 View commit details
  13. Merge pull request #8730 from reitermarkus/curl-language

    Set `Accept-Language` header for all `curl` requests.
    reitermarkus authored Sep 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3acb2e2 View commit details
  14. bump-cask-pr: fix branch name for versions with colon

    Replace commas and colons with hyphens
    SeekingMeaning committed Sep 15, 2020
    Copy the full SHA
    584c839 View commit details
  15. Merge pull request #8731 from SeekingMeaning/bump-cask-pr/version-wit…

    …h-colon
    
    bump-cask-pr: fix branch name for versions with colon
    SeekingMeaning authored Sep 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    16f936a View commit details
  16. Copy the full SHA
    871dc50 View commit details
  17. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    57c136e View commit details
  18. Merge pull request #8733 from SeekingMeaning/bump-formula-pr/disabled…

    …-formula
    
    bump-formula-pr: exit with error if formula is disabled
    SeekingMeaning authored Sep 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b46025f View commit details
  19. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    311e5f3 View commit details
  20. Merge pull request #8735 from Homebrew/fix-gh-get-rel

    pr-upload: fix getting existing github release
    dawidd6 authored Sep 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    21d4c1f View commit details

Commits on Sep 16, 2020

  1. Copy the full SHA
    875696d View commit details
  2. build(deps): bump tapioca from 0.4.5 to 0.4.6 in /Library/Homebrew

    Bumps [tapioca](https://github.com/Shopify/tapioca) from 0.4.5 to 0.4.6.
    - [Release notes](https://github.com/Shopify/tapioca/releases)
    - [Commits](Shopify/tapioca@v0.4.5...v0.4.6)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    adcdf24 View commit details
  3. Merge pull request #8736 from Homebrew/tapioca-update

    sorbet: update RBI files using Tapioca.
    vidusheeamoli authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9d98b0e View commit details
  4. build(deps): bump sorbet-runtime in /Library/Homebrew

    Bumps [sorbet-runtime](https://github.com/sorbet/sorbet) from 0.5.5909 to 0.5.5911.
    - [Release notes](https://github.com/sorbet/sorbet/releases)
    - [Commits](https://github.com/sorbet/sorbet/commits)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    68cbc4a View commit details
  5. Merge pull request #8740 from Homebrew/dependabot/bundler/Library/Hom…

    …ebrew/sorbet-runtime-0.5.5911
    
    build(deps): bump sorbet-runtime from 0.5.5909 to 0.5.5911 in /Library/Homebrew
    MikeMcQuaid authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d2342e8 View commit details
  6. Merge pull request #8738 from Homebrew/dependabot/bundler/Library/Hom…

    …ebrew/tapioca-0.4.6
    
    build(deps): bump tapioca from 0.4.5 to 0.4.6 in /Library/Homebrew
    MikeMcQuaid authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8444761 View commit details
  7. build(deps): bump sorbet from 0.5.5909 to 0.5.5911 in /Library/Homebrew

    Bumps [sorbet](https://github.com/sorbet/sorbet) from 0.5.5909 to 0.5.5911.
    - [Release notes](https://github.com/sorbet/sorbet/releases)
    - [Commits](https://github.com/sorbet/sorbet/commits)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    53706e6 View commit details
  8. language/python: build python binary names dynamically.

    Co-authored-by: Alexander Bayandin <a.bayandin@gmail.com>
    MikeMcQuaid and bayandin authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f04b014 View commit details
  9. Merge pull request #8734 from Homebrew/python39

    python.rb: prepare for Python 3.9
    MikeMcQuaid authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    76363be View commit details
  10. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    adb9922 View commit details
  11. Copy the full SHA
    7d29054 View commit details
  12. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fcd4c67 View commit details
  13. Copy the full SHA
    626e861 View commit details
  14. Merge pull request #8737 from SeekingMeaning/bump-formula-pr/audit-on…

    …line
    
    bump-formula-pr, bump-cask-pr: add `--online` switch for audit
    SeekingMeaning authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    22d908c View commit details
  15. build(deps): bump parallel_tests in /Library/Homebrew

    Bumps [parallel_tests](https://github.com/grosser/parallel_tests) from 3.2.0 to 3.3.0.
    - [Release notes](https://github.com/grosser/parallel_tests/releases)
    - [Changelog](https://github.com/grosser/parallel_tests/blob/master/CHANGELOG.md)
    - [Commits](grosser/parallel_tests@v3.2.0...v3.3.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8793199 View commit details
  16. Merge pull request #8745 from Homebrew/dependabot/bundler/Library/Hom…

    …ebrew/parallel_tests-3.3.0
    
    build(deps): bump parallel_tests from 3.2.0 to 3.3.0 in /Library/Homebrew
    reitermarkus authored Sep 16, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    871abe8 View commit details
  17. Verified

    This commit was signed with the committer’s verified signature.
    nandahkrishna Nanda H Krishna
    Copy the full SHA
    c1909e8 View commit details
  18. Copy the full SHA
    1c1ffc1 View commit details

Commits on Sep 17, 2020

  1. Merge pull request #8746 from 0az/fix-sha256-error

    cask/exceptions: Actually print actual hash
    reitermarkus authored Sep 17, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9dd5d42 View commit details
  2. Copy the full SHA
    5a8cc37 View commit details
  3. Copy the full SHA
    1710f0a View commit details
  4. Copy the full SHA
    86a838c View commit details
  5. build(deps): bump sorbet-runtime in /Library/Homebrew

    Bumps [sorbet-runtime](https://github.com/sorbet/sorbet) from 0.5.5911 to 0.5.5912.
    - [Release notes](https://github.com/sorbet/sorbet/releases)
    - [Commits](https://github.com/sorbet/sorbet/commits)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    dependabot-preview[bot] authored Sep 17, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4d2ef35 View commit details
Showing with 3,184 additions and 696 deletions.
  1. +1 −0 .github/PULL_REQUEST_TEMPLATE.md
  2. +1 −1 .github/workflows/tapioca.yml
  3. +0 −1 .gitignore
  4. +5 −0 Library/.rubocop.yml
  5. +13 −12 Library/Homebrew/Gemfile.lock
  6. +1 −5 Library/Homebrew/bintray.rb
  7. +37 −44 Library/Homebrew/cask/audit.rb
  8. +2 −2 Library/Homebrew/cask/cask.rb
  9. +1 −0 Library/Homebrew/cask/cask_loader.rb
  10. +1 −3 Library/Homebrew/cask/cmd/audit.rb
  11. +1 −1 Library/Homebrew/cask/exceptions.rb
  12. +1 −1 Library/Homebrew/cask/installer.rb
  13. +6 −0 Library/Homebrew/dev-cmd/audit.rb
  14. +9 −1 Library/Homebrew/dev-cmd/bump-cask-pr.rb
  15. +25 −6 Library/Homebrew/dev-cmd/bump-formula-pr.rb
  16. +7 −5 Library/Homebrew/dev-cmd/livecheck.rb
  17. +184 −30 Library/Homebrew/dev-cmd/pr-pull.rb
  18. +63 −18 Library/Homebrew/dev-cmd/pr-upload.rb
  19. +21 −1 Library/Homebrew/dev-cmd/typecheck.rb
  20. +7 −7 Library/Homebrew/diagnostic.rb
  21. +4 −2 Library/Homebrew/extend/ENV/shared.rb
  22. +2 −2 Library/Homebrew/extend/ENV/std.rb
  23. +1 −1 Library/Homebrew/extend/ENV/super.rb
  24. +11 −11 Library/Homebrew/extend/os/mac/extend/ENV/std.rb
  25. +8 −8 Library/Homebrew/extend/os/mac/extend/ENV/super.rb
  26. +2 −2 Library/Homebrew/formula.rb
  27. +2 −0 Library/Homebrew/global.rb
  28. +1 −1 Library/Homebrew/language/python.rb
  29. +35 −2 Library/Homebrew/livecheck/livecheck.rb
  30. +4 −4 Library/Homebrew/os/mac/xquartz.rb
  31. +1 −0 Library/Homebrew/rubocops.rb
  32. +251 −0 Library/Homebrew/rubocops/livecheck.rb
  33. +4 −6 Library/Homebrew/rubocops/shared/desc_helper.rb
  34. +189 −193 Library/Homebrew/sorbet/files.yaml
  35. 0 Library/Homebrew/sorbet/rbi/gems/{parallel_tests@3.2.0.rbi → parallel_tests@3.3.0.rbi}
  36. +38 −1 Library/Homebrew/sorbet/rbi/gems/{rubocop-ast@0.3.0.rbi → rubocop-ast@0.4.2.rbi}
  37. +12 −4 Library/Homebrew/sorbet/rbi/gems/{rubocop-performance@1.8.0.rbi → rubocop-performance@1.8.1.rbi}
  38. +259 −51 Library/Homebrew/sorbet/rbi/gems/{rubocop@0.90.0.rbi → rubocop@0.91.0.rbi}
  39. 0 Library/Homebrew/sorbet/rbi/gems/{tapioca@0.4.5.rbi → tapioca@0.4.6.rbi}
  40. +13 −8 Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi
  41. +1 −2 Library/Homebrew/sorbet/rbi/utils/inreplace.rbi
  42. +11 −9 Library/Homebrew/tap.rb
  43. +5 −0 Library/Homebrew/test.rb
  44. +1 −0 Library/Homebrew/test/.rubocop_todo.yml
  45. +137 −130 Library/Homebrew/test/cask/audit_spec.rb
  46. +2 −0 Library/Homebrew/test/cask/cmd/cat_spec.rb
  47. +1 −1 Library/Homebrew/test/cask/depends_on_spec.rb
  48. +2 −2 Library/Homebrew/test/cask/verify_spec.rb
  49. +1 −2 Library/Homebrew/test/cmd/tap_spec.rb
  50. +2 −2 Library/Homebrew/test/cmd/untap_spec.rb
  51. +1 −1 Library/Homebrew/test/language/java_spec.rb
  52. +22 −2 Library/Homebrew/test/rubocops/cask/desc_spec.rb
  53. +9 −1 Library/Homebrew/test/rubocops/formula_desc_spec.rb
  54. +270 −0 Library/Homebrew/test/rubocops/livecheck_spec.rb
  55. +2 −1 Library/Homebrew/test/support/fixtures/cask/Casks/adobe-air.rb
  56. +2 −0 Library/Homebrew/test/support/fixtures/cask/Casks/auto-updates.rb
  57. +2 −0 Library/Homebrew/test/support/fixtures/cask/Casks/basic-cask.rb
  58. +2 −0 Library/Homebrew/test/support/fixtures/cask/Casks/latest-with-auto-updates.rb
  59. +2 −0 Library/Homebrew/test/support/fixtures/cask/Casks/pkg-without-uninstall.rb
  60. +2 −0 Library/Homebrew/test/support/fixtures/cask/Casks/version-latest.rb
  61. +2 −0 Library/Homebrew/test/support/fixtures/cask/Casks/with-binary.rb
  62. +2 −0 Library/Homebrew/test/support/fixtures/cask/Casks/with-installer-manual.rb
  63. +1 −0 Library/Homebrew/test/support/fixtures/third-party/Casks/pharo.rb
  64. +8 −0 Library/Homebrew/test/utils/git_spec.rb
  65. +2 −2 Library/Homebrew/unpack_strategy/dmg.rb
  66. +1 −0 Library/Homebrew/upgrade.rb
  67. +6 −2 Library/Homebrew/utils.rb
  68. +2 −0 Library/Homebrew/utils/curl.rb
  69. +1 −1 Library/Homebrew/utils/gems.rb
  70. +29 −20 Library/Homebrew/utils/git.rb
  71. +33 −1 Library/Homebrew/utils/github.rb
  72. +2 −1 Library/Homebrew/utils/inreplace.rb
  73. +12 −8 Library/Homebrew/utils/pypi.rb
  74. +31 −1 Library/Homebrew/utils/tty.rb
  75. +8 −8 Library/Homebrew/vendor/bundle/bundler/setup.rb
  76. 0 ...bundle/ruby/2.6.0/gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/config/default.yml
  77. 0 ...uby/2.6.0/gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop-performance.rb
  78. 0 ...ocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/mixin/regexp_metacharacter.rb
  79. 0 .../gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/mixin/sort_block.rb
  80. 0 ...p-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/ancestors_include.rb
  81. 0 ...8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb
  82. 0 .../{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/bind_call.rb
  83. 0 ...ems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/caller.rb
  84. 0 ...cop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/case_when_splat.rb
  85. 0 ...ms/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/casecmp.rb
  86. 0 ...formance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/chain_array_allocation.rb
  87. +1 −1 ...ance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/collection_literal_in_loop.rb
  88. 0 ...-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/compare_with_block.rb
  89. 0 ...gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/count.rb
  90. 0 ...bocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/delete_prefix.rb
  91. 0 ...bocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/delete_suffix.rb
  92. +45 −16 ...ems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/detect.rb
  93. 0 ...rformance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/double_start_end_with.rb
  94. 0 ...s/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/end_with.rb
  95. 0 ...{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/fixed_size.rb
  96. 0 ...s/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/flat_map.rb
  97. 0 ...ormance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/inefficient_hash_search.rb
  98. 0 ...ubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/io_readlines.rb
  99. 0 ...rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/open_struct.rb
  100. 0 ...bocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/range_include.rb
  101. 0 ...erformance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/redundant_block_call.rb
  102. 0 ...cop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/redundant_match.rb
  103. 0 ...cop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/redundant_merge.rb
  104. 0 ...erformance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/redundant_sort_block.rb
  105. 0 ...formance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/redundant_string_chars.rb
  106. 0 ...ubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/regexp_match.rb
  107. 0 ...ubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/reverse_each.rb
  108. 0 ...bocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/reverse_first.rb
  109. 0 .../gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/size.rb
  110. 0 ...ubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/sort_reverse.rb
  111. 0 ...ms/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/squeeze.rb
  112. 0 ...{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/start_with.rb
  113. 0 ...ocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/string_include.rb
  114. 0 ...-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/string_replacement.rb
  115. +13 −8 ...0/gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/sum.rb
  116. 0 .../{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/times_map.rb
  117. 0 ...cop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/unfreeze_string.rb
  118. 0 ...-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance/uri_default_parser.rb
  119. 0 .../gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/cop/performance_cops.rb
  120. 0 ...uby/2.6.0/gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/performance.rb
  121. 0 ....0/gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/performance/inject.rb
  122. +1 −1 ...0/gems/{rubocop-performance-1.8.0 → rubocop-performance-1.8.1}/lib/rubocop/performance/version.rb
  123. +22 −0 Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar.rb
  124. +183 −0 Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/base.rb
  125. +100 −0 .../vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/calculators/length.rb
  126. +9 −0 ...undle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/calculators/running_average.rb
  127. +5 −0 ...Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/components.rb
  128. +102 −0 ...brew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/components/bar.rb
  129. +29 −0 ...ndor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/components/percentage.rb
  130. +43 −0 ...rew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/components/rate.rb
  131. +107 −0 ...rew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/components/time.rb
  132. +13 −0 ...ew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/components/title.rb
  133. +4 −0 ...dle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/errors/invalid_progress_error.rb
  134. +3 −0 ...ary/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/format.rb
  135. +27 −0 ...ew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/format/formatter.rb
  136. +60 −0 ...rew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/format/molecule.rb
  137. +36 −0 ...ebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/format/string.rb
  138. +68 −0 ...ary/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/output.rb
  139. +47 −0 ...rew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/outputs/non_tty.rb
  140. +33 −0 ...mebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/outputs/null.rb
  141. +32 −0 ...omebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/outputs/tty.rb
  142. +118 −0 ...y/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/progress.rb
  143. +1 −0 ...omebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/refinements.rb
  144. +23 −0 ...dor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/refinements/enumerator.rb
  145. +25 −0 ...y/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/throttle.rb
  146. +32 −0 Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/time.rb
  147. +72 −0 Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/timer.rb
  148. +3 −0 ...ry/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-progressbar-1.10.1/lib/ruby-progressbar/version.rb
  149. +12 −1 completions/bash/brew
  150. +10 −10 completions/fish/brew.fish
  151. +6 −6 completions/zsh/_brew
  152. +3 −3 docs/Brew-Test-Bot-For-Core-Contributors.md
  153. +1 −0 docs/Homebrew-homebrew-core-Merge-Checklist.md
  154. +19 −7 docs/Manpage.md
  155. +2 −2 docs/New-Maintainer-Checklist.md
  156. +1 −1 docs/Shell-Completion.md
  157. +33 −9 manpages/brew.1
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -4,5 +4,6 @@
- [ ] Have you written new tests for your changes? [Here's an example](https://github.com/Homebrew/brew/blob/HEAD/Library/Homebrew/test/PATH_spec.rb).
- [ ] Have you successfully run `brew style` with your changes locally?
- [ ] Have you successfully run `brew tests` with your changes locally?
- [ ] Have you successfully run `brew man` locally and committed any changes?

-----
2 changes: 1 addition & 1 deletion .github/workflows/tapioca.yml
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ jobs:
BRANCH_EXISTS="1"
fi
if brew typecheck --update-definitions --fail-if-not-changed; then
if brew typecheck --prune-files-list --update-definitions --fail-if-not-changed; then
git add "$GITHUB_WORKSPACE/Library/Homebrew/sorbet"
git commit -m "sorbet: update RBI files using Tapioca." -m "Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/master/.github/workflows/tapioca.yml)."
echo "::set-output name=committed::true"
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -130,7 +130,6 @@
**/vendor/bundle/ruby/*/gems/rubocop-0*/
**/vendor/bundle/ruby/*/gems/rubocop-ast-*/
**/vendor/bundle/ruby/*/gems/ruby-prof-*/
**/vendor/bundle/ruby/*/gems/ruby-progressbar-*/
**/vendor/bundle/ruby/*/gems/simplecov-*/
**/vendor/bundle/ruby/*/gems/simplecov-html-*/
**/vendor/bundle/ruby/*/gems/sorbet-*/
5 changes: 5 additions & 0 deletions Library/.rubocop.yml
Original file line number Diff line number Diff line change
@@ -194,6 +194,11 @@ Lint/AmbiguousRegexpLiteral:
Exclude:
- 'Taps/*/*/{Formula/,}*.rb'

# useful for metaprogramming in RSpec
Lint/ConstantDefinitionInBlock:
Exclude:
- '**/*_spec.rb'

# so many of these in formulae and can't be autocorrected
Lint/ParenthesesAsGroupedExpression:
Exclude:
25 changes: 13 additions & 12 deletions Library/Homebrew/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@ GEM
mini_portile2 (~> 2.4.0)
ntlm-http (0.1.1)
parallel (1.19.2)
parallel_tests (3.2.0)
parallel_tests (3.3.0)
parallel
parlour (4.0.1)
commander (~> 4.5)
@@ -72,7 +72,7 @@ GEM
method_source (~> 1.0)
rainbow (3.0.0)
rdiscount (2.2.0.2)
regexp_parser (1.7.1)
regexp_parser (1.8.0)
rexml (3.2.4)
ronn (0.7.3)
hpricot (>= 0.8.2)
@@ -98,19 +98,20 @@ GEM
rspec-support (3.9.3)
rspec-wait (0.0.9)
rspec (>= 3, < 4)
rubocop (0.90.0)
rubocop (0.91.0)
parallel (~> 1.10)
parser (>= 2.7.1.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
rexml
rubocop-ast (>= 0.3.0, < 1.0)
rubocop-ast (>= 0.4.0, < 1.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-ast (0.3.0)
rubocop-ast (0.4.2)
parser (>= 2.7.1.4)
rubocop-performance (1.8.0)
rubocop-performance (1.8.1)
rubocop (>= 0.87.0)
rubocop-ast (>= 0.4.0)
rubocop-rspec (1.43.2)
rubocop (~> 0.87)
ruby-macho (2.2.0)
@@ -119,16 +120,16 @@ GEM
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov-html (0.12.2)
sorbet (0.5.5909)
sorbet-static (= 0.5.5909)
sorbet-runtime (0.5.5909)
sorbet-static (0.5.5909-universal-darwin-14)
sorbet (0.5.5913)
sorbet-static (= 0.5.5913)
sorbet-runtime (0.5.5913)
sorbet-static (0.5.5913-universal-darwin-14)
spoom (1.0.4)
colorize
sorbet (~> 0.5.5)
sorbet-runtime
thor (>= 0.19.2)
tapioca (0.4.5)
tapioca (0.4.6)
parlour (>= 2.1.0)
pry (>= 0.12.2)
sorbet-runtime
@@ -173,4 +174,4 @@ DEPENDENCIES
tapioca

BUNDLED WITH
1.17.2
1.17.3
6 changes: 1 addition & 5 deletions Library/Homebrew/bintray.rb
Original file line number Diff line number Diff line change
@@ -148,11 +148,7 @@ def file_published?(repo:, remote_file:)
end
end

def upload_bottle_json(json_files, publish_package: false, warn_on_error: false)
bottles_hash = json_files.reduce({}) do |hash, json_file|
hash.deep_merge(JSON.parse(IO.read(json_file)))
end

def upload_bottles(bottles_hash, publish_package: false, warn_on_error: false)
formula_packaged = {}

bottles_hash.each do |formula_name, bottle_hash|
81 changes: 37 additions & 44 deletions Library/Homebrew/cask/audit.rb
Original file line number Diff line number Diff line change
@@ -30,8 +30,8 @@ def initialize(cask, appcast: nil, download: nil, quarantine: nil,
appcast = online if appcast.nil?
download = online if download.nil?

# `strict` implies `token_conflicts`
token_conflicts = strict if token_conflicts.nil?
# `new_cask` implies `token_conflicts`
token_conflicts = new_cask if token_conflicts.nil?

@cask = cask
@appcast = appcast
@@ -91,7 +91,11 @@ def add_error(message)
end

def add_warning(message)
warnings << message
if strict?
add_error message
else
warnings << message
end
end

def errors?
@@ -143,7 +147,7 @@ def check_untrusted_pkg

return unless cask.artifacts.any? { |k| k.is_a?(Artifact::Pkg) && k.stanza_options.key?(:allow_untrusted) }

add_warning "allow_untrusted is not permitted in official Homebrew Cask taps"
add_error "allow_untrusted is not permitted in official Homebrew Cask taps"
end

def check_stanza_requires_uninstall
@@ -152,14 +156,14 @@ def check_stanza_requires_uninstall
return if cask.artifacts.none? { |k| k.is_a?(Artifact::Pkg) || k.is_a?(Artifact::Installer) }
return if cask.artifacts.any? { |k| k.is_a?(Artifact::Uninstall) }

add_warning "installer and pkg stanzas require an uninstall stanza"
add_error "installer and pkg stanzas require an uninstall stanza"
end

def check_single_pre_postflight
odebug "Auditing preflight and postflight stanzas"

if cask.artifacts.count { |k| k.is_a?(Artifact::PreflightBlock) && k.directives.key?(:preflight) } > 1
add_warning "only a single preflight stanza is allowed"
add_error "only a single preflight stanza is allowed"
end

count = cask.artifacts.count do |k|
@@ -168,33 +172,33 @@ def check_single_pre_postflight
end
return unless count > 1

add_warning "only a single postflight stanza is allowed"
add_error "only a single postflight stanza is allowed"
end

def check_single_uninstall_zap
odebug "Auditing single uninstall_* and zap stanzas"

if cask.artifacts.count { |k| k.is_a?(Artifact::Uninstall) } > 1
add_warning "only a single uninstall stanza is allowed"
add_error "only a single uninstall stanza is allowed"
end

count = cask.artifacts.count do |k|
k.is_a?(Artifact::PreflightBlock) &&
k.directives.key?(:uninstall_preflight)
end

add_warning "only a single uninstall_preflight stanza is allowed" if count > 1
add_error "only a single uninstall_preflight stanza is allowed" if count > 1

count = cask.artifacts.count do |k|
k.is_a?(Artifact::PostflightBlock) &&
k.directives.key?(:uninstall_postflight)
end

add_warning "only a single uninstall_postflight stanza is allowed" if count > 1
add_error "only a single uninstall_postflight stanza is allowed" if count > 1

return unless cask.artifacts.count { |k| k.is_a?(Artifact::Zap) } > 1

add_warning "only a single zap stanza is allowed"
add_error "only a single zap stanza is allowed"
end

def check_required_stanzas
@@ -267,14 +271,14 @@ def check_latest_with_appcast
return unless cask.version.latest?
return unless cask.appcast

add_warning "Casks with an appcast should not use version :latest"
add_error "Casks with an appcast should not use version :latest"
end

def check_latest_with_auto_updates
return unless cask.version.latest?
return unless cask.auto_updates

add_warning "Casks with `version :latest` should not use `auto_updates`"
add_error "Casks with `version :latest` should not use `auto_updates`"
end

def check_hosting_with_appcast
@@ -286,21 +290,19 @@ def check_hosting_with_appcast
when %r{github.com/([^/]+)/([^/]+)/releases/download/(\S+)}
return if cask.version.latest?

add_warning "Download uses GitHub releases, #{add_appcast}"
add_error "Download uses GitHub releases, #{add_appcast}"
when %r{sourceforge.net/(\S+)}
return if cask.version.latest?

add_warning "Download is hosted on SourceForge, #{add_appcast}"
add_error "Download is hosted on SourceForge, #{add_appcast}"
when %r{dl.devmate.com/(\S+)}
add_warning "Download is hosted on DevMate, #{add_appcast}"
add_error "Download is hosted on DevMate, #{add_appcast}"
when %r{rink.hockeyapp.net/(\S+)}
add_warning "Download is hosted on HockeyApp, #{add_appcast}"
add_error "Download is hosted on HockeyApp, #{add_appcast}"
end
end

def check_desc
return unless new_cask?

return if cask.desc.present?

add_warning "Cask should have a description. Please add a `desc` stanza."
@@ -315,9 +317,9 @@ def check_url
def check_download_url_format
odebug "Auditing URL format"
if bad_sourceforge_url?
add_warning "SourceForge URL format incorrect. See https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls"
add_error "SourceForge URL format incorrect. See https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls"
elsif bad_osdn_url?
add_warning "OSDN URL format incorrect. See https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls"
add_error "OSDN URL format incorrect. See https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls"
end
end

@@ -363,42 +365,33 @@ def check_token_conflicts
end

def check_token_valid
return unless strict?

add_warning "cask token is not lowercase" if cask.token.downcase!

add_warning "cask token contains non-ascii characters" unless cask.token.ascii_only?

add_warning "cask token + should be replaced by -plus-" if cask.token.include? "+"

add_warning "cask token @ should be replaced by -at-" if cask.token.include? "@"

add_warning "cask token whitespace should be replaced by hyphens" if cask.token.include? " "

add_warning "cask token underscores should be replaced by hyphens" if cask.token.include? "_"
add_error "cask token contains non-ascii characters" unless cask.token.ascii_only?
add_error "cask token + should be replaced by -plus-" if cask.token.include? "+"
add_error "cask token whitespace should be replaced by hyphens" if cask.token.include? " "
add_error "cask token @ should be replaced by -at-" if cask.token.include? "@"
add_error "cask token underscores should be replaced by hyphens" if cask.token.include? "_"
add_error "cask token should not contain double hyphens" if cask.token.include? "--"

if cask.token.match?(/[^a-z0-9\-]/)
add_warning "cask token should only contain alphanumeric characters and hyphens"
add_error "cask token should only contain lowercase alphanumeric characters and hyphens"
end

add_warning "cask token should not contain double hyphens" if cask.token.include? "--"

return unless cask.token.end_with?("-") || cask.token.start_with?("-")
return unless cask.token.start_with?("-") || cask.token.end_with?("-")

add_warning "cask token should not have leading or trailing hyphens"
add_error "cask token should not have leading or trailing hyphens"
end

def check_token_bad_words
return unless strict?
return unless new_cask?

token = cask.token

add_warning "cask token contains .app" if token.end_with? ".app"
add_error "cask token contains .app" if token.end_with? ".app"

if /-(?<designation>alpha|beta|rc|release-candidate)$/ =~ cask.token &&
cask.tap&.official? &&
cask.tap != "homebrew/cask-versions"
add_warning "cask token contains version designation '#{designation}'"
add_error "cask token contains version designation '#{designation}'"
end

add_warning "cask token mentions launcher" if token.end_with? "launcher"
@@ -433,7 +426,7 @@ def check_download
downloaded_path = download.perform
Verify.all(cask, downloaded_path)
rescue => e
add_error "download not possible: #{e.message}"
add_error "download not possible: #{e}"
end

def check_appcast_contains_version
@@ -458,7 +451,7 @@ def check_appcast_contains_version
end
return if appcast_contents.include? adjusted_version_stanza

add_warning "appcast at URL '#{appcast_stanza}' does not contain"\
add_error "appcast at URL '#{appcast_stanza}' does not contain"\
" the version number '#{adjusted_version_stanza}':\n#{appcast_contents}"
end

4 changes: 2 additions & 2 deletions Library/Homebrew/cask/cask.rb
Original file line number Diff line number Diff line change
@@ -18,11 +18,11 @@ class Cask

attr_reader :token, :sourcefile_path, :config

def self.each
def self.each(&block)
return to_enum unless block_given?

Tap.flat_map(&:cask_files).each do |f|
yield CaskLoader::FromTapPathLoader.new(f).load
block.call CaskLoader::FromTapPathLoader.new(f).load
rescue CaskUnreadableError => e
opoo e.message
end
1 change: 1 addition & 0 deletions Library/Homebrew/cask/cask_loader.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require "cask/cache"
require "cask/cask"
require "uri"

4 changes: 1 addition & 3 deletions Library/Homebrew/cask/cmd/audit.rb
Original file line number Diff line number Diff line change
@@ -59,8 +59,6 @@ def run
odebug "Auditing Cask #{cask}"
result = Auditor.audit(cask, **options)

next true if result[:warnings].empty? && result[:errors].empty?

if ENV["GITHUB_ACTIONS"]
cask_path = cask.sourcefile_path
annotations = (result[:warnings].map { |w| [:warning, w] } + result[:errors].map { |e| [:error, e] })
@@ -71,7 +69,7 @@ def run
end
end

false
result[:errors].empty?
end

return if failed_casks.empty?
2 changes: 1 addition & 1 deletion Library/Homebrew/cask/exceptions.rb
Original file line number Diff line number Diff line change
@@ -184,7 +184,7 @@ class CaskSha256MissingError < CaskSha256Error
def to_s
<<~EOS
Cask '#{token}' requires a checksum:
#{Formatter.identifier('sha256 "#{actual}"')}
#{Formatter.identifier("sha256 \"#{actual}\"")}
EOS
end
end
2 changes: 1 addition & 1 deletion Library/Homebrew/cask/installer.rb
Original file line number Diff line number Diff line change
@@ -276,7 +276,7 @@ def arch_dependencies

def x11_dependencies
return unless @cask.depends_on.x11
raise CaskX11DependencyError, @cask.token unless MacOS::X11.installed?
raise CaskX11DependencyError, @cask.token unless MacOS::XQuartz.installed?
end

def graph_dependencies(cask_or_formula, acc = TopologicalHash.new)
6 changes: 6 additions & 0 deletions Library/Homebrew/dev-cmd/audit.rb
Original file line number Diff line number Diff line change
@@ -712,6 +712,11 @@ def get_repo_data(regex)
"vbindiff" => "3.0_beta",
}.freeze

# used for formulae that are unstable but need CI run without being in homebrew/core
UNSTABLE_DEVEL_ALLOWLIST = {
"python@3.9" => "3.9.0rc",
}.freeze

GNOME_DEVEL_ALLOWLIST = {
"libart" => "2.3",
"gtk-mac-integration" => "2.1",
@@ -784,6 +789,7 @@ def audit_specs
matched = Regexp.last_match(1)
version_prefix = stable_version_string.sub(/\d+$/, "")
return if UNSTABLE_ALLOWLIST[formula.name] == version_prefix
return if UNSTABLE_DEVEL_ALLOWLIST[formula.name] == version_prefix

problem "Stable version URLs should not contain #{matched}"
when %r{download\.gnome\.org/sources}, %r{ftp\.gnome\.org/pub/GNOME/sources}i
10 changes: 9 additions & 1 deletion Library/Homebrew/dev-cmd/bump-cask-pr.rb
Original file line number Diff line number Diff line change
@@ -27,6 +27,8 @@ def bump_cask_pr_args
"to the cask file."
switch "--no-audit",
description: "Don't run `brew cask audit` before opening the PR."
switch "--online",
description: "Run `brew cask audit --online` before opening the PR."
switch "--no-style",
description: "Don't run `brew cask style --fix` before opening the PR."
switch "--no-browse",
@@ -45,6 +47,7 @@ def bump_cask_pr_args
description: "Ignore duplicate open PRs."

conflicts "--dry-run", "--write"
conflicts "--no-audit", "--online"
named 1
end
end
@@ -193,7 +196,7 @@ def bump_cask_pr
sourcefile_path: cask.sourcefile_path,
old_contents: old_contents,
origin_branch: origin_branch,
branch_name: "bump-#{cask.token}-#{new_version}",
branch_name: "bump-#{cask.token}-#{new_version.tr(",:", "-")}",
commit_message: "Update #{cask.token} from #{old_version} to #{new_version}",
previous_branch: previous_branch,
tap: cask.tap,
@@ -225,6 +228,8 @@ def run_cask_audit(cask, old_contents, args:)
if args.dry_run?
if args.no_audit?
ohai "Skipping `brew cask audit`"
elsif args.online?
ohai "brew cask audit --online #{cask.sourcefile_path.basename}"
else
ohai "brew cask audit #{cask.sourcefile_path.basename}"
end
@@ -233,6 +238,9 @@ def run_cask_audit(cask, old_contents, args:)
failed_audit = false
if args.no_audit?
ohai "Skipping `brew cask audit`"
elsif args.online?
system HOMEBREW_BREW_FILE, "cask", "audit", "--online", cask.sourcefile_path
failed_audit = !$CHILD_STATUS.success?
else
system HOMEBREW_BREW_FILE, "cask", "audit", cask.sourcefile_path
failed_audit = !$CHILD_STATUS.success?
31 changes: 25 additions & 6 deletions Library/Homebrew/dev-cmd/bump-formula-pr.rb
Original file line number Diff line number Diff line change
@@ -42,6 +42,8 @@ def bump_formula_pr_args
description: "Don't run `brew audit` before opening the PR."
switch "--strict",
description: "Run `brew audit --strict` before opening the PR."
switch "--online",
description: "Run `brew audit --online` before opening the PR."
switch "--no-browse",
description: "Print the pull request URL instead of opening in a browser."
switch "--no-fork",
@@ -71,6 +73,7 @@ def bump_formula_pr_args

conflicts "--dry-run", "--write"
conflicts "--no-audit", "--strict"
conflicts "--no-audit", "--online"
conflicts "--url", "--tag"
max_named 1
end
@@ -133,6 +136,8 @@ def bump_formula_pr
formula ||= determine_formula_from_url(new_url) if new_url
raise FormulaUnspecifiedError unless formula

odie "This formula is disabled!" if formula.disabled?

tap_full_name, origin_branch, previous_branch = use_correct_linux_tap(formula, args: args)
check_open_pull_requests(formula, tap_full_name, args: args)

@@ -325,11 +330,22 @@ def bump_formula_pr
end

unless args.dry_run?
PyPI.update_python_resources! formula, new_formula_version, silent: args.quiet?, ignore_non_pypi_packages: true
resources_checked = PyPI.update_python_resources! formula, new_formula_version,
silent: args.quiet?, ignore_non_pypi_packages: true
end

run_audit(formula, alias_rename, old_contents, args: args)

pr_message = "Created with `brew bump-formula-pr`."
if resources_checked.nil? && formula.resources.present? &&
formula.resources.any? { |resource| resource.name != "homebrew-virtualenv" }
pr_message += <<~EOS
`resource` blocks may require updates.
EOS
end

pr_info = {
sourcefile_path: formula.path,
old_contents: old_contents,
@@ -340,7 +356,7 @@ def bump_formula_pr
previous_branch: previous_branch,
tap: formula.tap,
tap_full_name: tap_full_name,
pr_message: "Created with `brew bump-formula-pr`.",
pr_message: pr_message,
}
GitHub.create_bump_pr(pr_info, args: args)
end
@@ -438,11 +454,14 @@ def alias_update_pair(formula, new_formula_version)
end

def run_audit(formula, alias_rename, old_contents, args:)
audit_args = []
audit_args << "--strict" if args.strict?
audit_args << "--online" if args.online?
if args.dry_run?
if args.no_audit?
ohai "Skipping `brew audit`"
elsif args.strict?
ohai "brew audit --strict #{formula.path.basename}"
elsif audit_args.present?
ohai "brew audit #{audit_args.join(" ")} #{formula.path.basename}"
else
ohai "brew audit #{formula.path.basename}"
end
@@ -452,8 +471,8 @@ def run_audit(formula, alias_rename, old_contents, args:)
failed_audit = false
if args.no_audit?
ohai "Skipping `brew audit`"
elsif args.strict?
system HOMEBREW_BREW_FILE, "audit", "--strict", formula.path
elsif audit_args.present?
system HOMEBREW_BREW_FILE, "audit", *audit_args, formula.path
failed_audit = !$CHILD_STATUS.success?
else
system HOMEBREW_BREW_FILE, "audit", formula.path
12 changes: 7 additions & 5 deletions Library/Homebrew/dev-cmd/livecheck.rb
Original file line number Diff line number Diff line change
@@ -26,15 +26,17 @@ def livecheck_args
switch "--full-name",
description: "Print formulae with fully-qualified names."
flag "--tap=",
description: "Check the formulae within the given tap, specified as <user>`/`<repo>."
switch "--installed",
description: "Check formulae that are currently installed."
switch "--json",
description: "Output informations in JSON format."
description: "Check formulae within the given tap, specified as <user>`/`<repo>."
switch "--all",
description: "Check all available formulae."
switch "--installed",
description: "Check formulae that are currently installed."
switch "--newer-only",
description: "Show the latest version only if it's newer than the formula."
switch "--json",
description: "Output information in JSON format."
switch "-q", "--quiet",
description: "Suppress warnings, don't print a progress bar for JSON output."
conflicts "--debug", "--json"
conflicts "--tap=", "--all", "--installed"
end
214 changes: 184 additions & 30 deletions Library/Homebrew/dev-cmd/pr-pull.rb
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@
require "cli/parser"
require "utils/github"
require "tmpdir"
require "bintray"
require "formula"

module Homebrew
@@ -24,14 +23,17 @@ def pr_pull_args
"upload the bottles to Bintray, but don't publish them."
switch "--no-upload",
description: "Download the bottles and apply the bottle commit, "\
"but don't upload to Bintray."
"but don't upload to Bintray or GitHub Releases."
switch "-n", "--dry-run",
description: "Print what would be done rather than doing it."
switch "--clean",
description: "Do not amend the commits from pull requests."
switch "--keep-old",
description: "If the formula specifies a rebuild version, " \
"attempt to preserve its value in the generated DSL."
switch "--autosquash",
description: "Automatically reformat and reword commits in the pull request to our "\
"preferred format."
switch "--branch-okay",
description: "Do not warn if pulling to a branch besides master (useful for testing)."
switch "--resolve",
@@ -40,6 +42,9 @@ def pr_pull_args
switch "--warn-on-upload-failure",
description: "Warn instead of raising an error if the bottle upload fails. "\
"Useful for repairing bottle uploads that previously failed."
flag "--message=",
depends_on: "--autosquash",
description: "Message to include when autosquashing revision bumps, deletions, and rebuilds."
flag "--workflow=",
description: "Retrieve artifacts from the specified workflow (default: `tests.yml`)."
flag "--artifact=",
@@ -53,8 +58,8 @@ def pr_pull_args
flag "--bintray-mirror=",
description: "Use the specified Bintray repository to automatically mirror stable URLs "\
"defined in the formulae (default: `mirror`)."

min_named 1
conflicts "--clean", "--autosquash"
end
end

@@ -79,21 +84,29 @@ def setup_git_environment!
end
end

def signoff!(pr, tap:, args:)
message = Utils.popen_read "git", "-C", tap.path, "log", "-1", "--pretty=%B"
# Separates a commit message into subject, body, and trailers.
def separate_commit_message(message)
subject = message.lines.first.strip

# Skip the subject and separate lines that look like trailers (e.g. "Co-authored-by")
# from lines that look like regular body text.
trailers, body = message.lines.drop(1).partition { |s| s.match?(/^[a-z-]+-by:/i) }

# Approving reviewers also sign-off on merge
trailers += GitHub.approved_reviews(tap.user, "homebrew-#{tap.repo}", pr).map do |r|
"Signed-off-by: #{r["name"]} <#{r["email"]}>\n"
end
trailers = trailers.uniq.join.strip
body = body.join.strip.gsub(/\n{3,}/, "\n\n")

[subject, body, trailers]
end

def signoff!(pr, tap:, args:)
message = Utils.popen_read "git", "-C", tap.path, "log", "-1", "--pretty=%B"
subject, body, trailers = separate_commit_message(message)

# Approving reviewers also sign-off on merge.
trailers += GitHub.approved_reviews(tap.user, "homebrew-#{tap.repo}", pr).map do |r|
"Signed-off-by: #{r["name"]} <#{r["email"]}>"
end.join("\n")

close_message = "Closes ##{pr}."
body += "\n\n#{close_message}" unless body.include? close_message
new_message = [subject, body, trailers].join("\n\n").strip
@@ -105,6 +118,163 @@ def signoff!(pr, tap:, args:)
end
end

def determine_bump_subject(file, original_commit, path: ".", reason: nil)
full_path = Pathname.new(path)/file
formula_name = File.basename(file.chomp(".rb"))

new_formula = begin
Formulary::FormulaLoader.new(formula_name, full_path).get_formula(:stable)
rescue FormulaUnavailableError
return "#{formula_name}: delete #{reason}"
end

old_formula = begin
old_file = Utils.popen_read "git", "-C", path, "show", "#{original_commit}:#{file}"
Formulary.from_contents(formula_name, full_path, old_file, :stable)
rescue FormulaUnavailableError
return "#{formula_name} #{new_formula.stable.version} (new formula)"
end

if old_formula.stable.version != new_formula.stable.version
"#{formula_name} #{new_formula.stable.version}"
elsif old_formula.revision != new_formula.revision
"#{formula_name}: revision #{reason}"
else
"#{formula_name}: #{reason || "rebuild"}"
end
end

# Cherry picks a single commit that modifies a single file.
# Potentially rewords this commit using `determine_bump_subject`.
def reword_formula_commit(commit, file, args:, path: ".")
formula_name = File.basename(file.chomp(".rb"))
odebug "Cherry-picking #{file}: #{commit}"
Utils::Git.cherry_pick!(path, commit, verbose: args.verbose?, resolve: args.resolve?)

bump_subject = determine_bump_subject(file, "HEAD^", path: path, reason: args.message).strip
message = Utils.popen_read("git", "-C", path, "log", "-1", "--pretty=%B")
subject, body, trailers = separate_commit_message(message)

if subject != bump_subject && !subject.start_with?("#{formula_name}:")
safe_system("git", "-C", path, "commit", "--amend", "-q",
"-m", bump_subject, "-m", subject, "-m", body, "-m", trailers)
ohai bump_subject
else
ohai subject
end
end

# Cherry picks multiple commits that each modify a single file.
# Words the commit according to `determine_bump_subject` with the body
# corresponding to all the original commit messages combined.
def squash_formula_commits(commits, file, args:, path: ".")
odebug "Squashing #{file}: #{commits.join " "}"

# Format commit messages into something similar to `git fmt-merge-message`.
# * subject 1
# * subject 2
# optional body
# * subject 3
messages = []
trailers = []
commits.each do |commit|
original_message = Utils.safe_popen_read("git", "-C", path, "show", "--no-patch", "--pretty=%B", commit)
subject, body, trailer = separate_commit_message(original_message)
body = body.lines.map { |line| " #{line.strip}" }.join("\n")
messages << "* #{subject}\n#{body}".strip
trailers << trailer
end

# Get the set of authors in this series.
authors = Utils.safe_popen_read("git", "-C", path, "show",
"--no-patch", "--pretty=%an <%ae>", *commits).lines.map(&:strip).uniq.compact

# Get the author and date of the first commit of this series, which we use for the squashed commit.
original_author = authors.shift
original_date = Utils.safe_popen_read "git", "-C", path, "show", "--no-patch", "--pretty=%ad", commits.first

# Generate trailers for coauthors and combine them with the existing trailers.
co_author_trailers = authors.map { |au| "Co-authored-by: #{au}" }
trailers = [trailers + co_author_trailers].flatten.uniq.compact

# Apply the patch series but don't commit anything yet.
Utils::Git.cherry_pick!(path, "--no-commit", *commits, verbose: args.verbose?, resolve: args.resolve?)

# Determine the bump subject by comparing the original state of the tree to its current state.
bump_subject = determine_bump_subject(file, "#{commits.first}^", path: path, reason: args.message).strip

# Commit with the new subject, body, and trailers.
safe_system("git", "-C", path, "commit", "--quiet",
"-m", bump_subject, "-m", messages.join("\n"), "-m", trailers.join("\n"),
"--author", original_author, "--date", original_date, "--", file)
ohai bump_subject
end

def autosquash!(original_commit, path: ".", args: nil)
# Autosquash assumes we've already modified the current state of the git repository,
# so just exit early if we're in a dry run.
return if args.dry_run?

original_head = Utils.safe_popen_read("git", "-C", path, "rev-parse", "HEAD").strip

commits = Utils.safe_popen_read("git", "-C", path, "rev-list",
"--reverse", "#{original_commit}..HEAD").lines.map(&:strip)

# Generate a bidirectional mapping of commits <=> formula files.
files_to_commits = {}
commits_to_files = commits.map do |commit|
files = Utils.safe_popen_read("git", "-C", path, "diff-tree", "--diff-filter=AMD",
"-r", "--name-only", "#{commit}^", commit).lines.map(&:strip)
files.each do |file|
files_to_commits[file] ||= []
files_to_commits[file] << commit
next if %r{^Formula/.*\.rb$}.match?(file)

odie <<~EOS
Autosquash can't squash commits that modify non-formula files.
File: #{file}
Commit: #{commit}
EOS
end
[commit, files]
end.to_h

# Reset to state before cherry-picking.
safe_system "git", "-C", path, "reset", "--hard", original_commit

# Iterate over every commit in the pull request series, but if we have to squash
# multiple commits into one, ensure that we skip over commits we've already squashed.
processed_commits = []
commits.each do |commit|
next if processed_commits.include? commit

files = commits_to_files[commit]
if files.length == 1 && files_to_commits[files.first].length == 1
# If there's a 1:1 mapping of commits to files, just cherry pick and (maybe) reword.
reword_formula_commit(commit, files.first, path: path, args: args)
processed_commits << commit
elsif files.length == 1 && files_to_commits[files.first].length > 1
# If multiple commits modify a single file, squash them down into a single commit.
file = files.first
commits = files_to_commits[file]
squash_formula_commits(commits, file, path: path, args: args)
processed_commits += commits
else
# We can't split commits (yet) so just raise an error.
odie <<~EOS
Autosquash can't split commits that modify multiple files.
Commit: #{commit}
Files: #{files.join " "}
EOS
end
end
rescue
opoo "Autosquash encountered an error; resetting to original cherry-picked state at #{original_head}"
system "git", "-C", path, "reset", "--hard", original_head
system "git", "-C", path, "cherry-pick", "--abort"
raise
end

def cherry_pick_pr!(pr, args:, path: ".")
if args.dry_run?
puts <<~EOS
@@ -117,19 +287,9 @@ def cherry_pick_pr!(pr, args:, path: ".")
merge_base = Utils.popen_read("git", "-C", path, "merge-base", "HEAD", "FETCH_HEAD").strip
commit_count = Utils.popen_read("git", "-C", path, "rev-list", "#{merge_base}..FETCH_HEAD").lines.count

# git cherry-pick unfortunately has no quiet option
ohai "Cherry-picking #{commit_count} commit#{"s" unless commit_count == 1} from ##{pr}"
cherry_pick_args = "git", "-C", path, "cherry-pick", "--ff", "--allow-empty", "#{merge_base}..FETCH_HEAD"
result = args.verbose? ? system(*cherry_pick_args) : quiet_system(*cherry_pick_args)

unless result
if args.resolve?
odie "Cherry-pick failed: try to resolve it."
else
system "git", "-C", path, "cherry-pick", "--abort"
odie "Cherry-pick failed!"
end
end
ohai "Using #{commit_count} commit#{"s" unless commit_count == 1} from ##{pr}"
Utils::Git.cherry_pick!(path, "--ff", "--allow-empty", "#{merge_base}..FETCH_HEAD",
verbose: args.verbose?, resolve: args.resolve?)
end
end

@@ -211,16 +371,9 @@ def download_artifact(url, dir, pr)
def pr_pull
args = pr_pull_args.parse

bintray_user = ENV["HOMEBREW_BINTRAY_USER"]
bintray_key = ENV["HOMEBREW_BINTRAY_KEY"]
bintray_org = args.bintray_org || "homebrew"

if (bintray_user.blank? || bintray_key.blank?) && !args.dry_run? && !args.no_upload?
odie "Missing HOMEBREW_BINTRAY_USER or HOMEBREW_BINTRAY_KEY variables!"
end

workflow = args.workflow || "tests.yml"
artifact = args.artifact || "bottles"
bintray_org = args.bintray_org || "homebrew"
mirror_repo = args.bintray_mirror || "mirror"
tap = Tap.fetch(args.tap || CoreTap.instance.name)

@@ -239,6 +392,7 @@ def pr_pull
cd dir do
original_commit = Utils.popen_read("git", "-C", tap.path, "rev-parse", "HEAD").chomp
cherry_pick_pr!(pr, path: tap.path, args: args)
autosquash!(original_commit, path: tap.path, args: args) if args.autosquash?
signoff!(pr, tap: tap, args: args) unless args.clean?

unless args.no_upload?
81 changes: 63 additions & 18 deletions Library/Homebrew/dev-cmd/pr-upload.rb
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ def pr_upload_args
usage_banner <<~EOS
`pr-upload` [<options>]
Apply the bottle commit and publish bottles to Bintray.
Apply the bottle commit and publish bottles to Bintray or GitHub Releases.
EOS
switch "--no-publish",
description: "Apply the bottle commit and upload the bottles, but don't publish them."
@@ -30,30 +30,37 @@ def pr_upload_args
end
end

def check_bottled_formulae(json_files)
hashes = json_files.reduce({}) do |hash, json|
hash.deep_merge(JSON.parse(IO.read(json)))
end

hashes.each do |name, hash|
formula_path = HOMEBREW_REPOSITORY/hash["formula"]["path"]
def check_bottled_formulae(bottles_hash)
bottles_hash.each do |name, bottle_hash|
formula_path = HOMEBREW_REPOSITORY/bottle_hash["formula"]["path"]
formula_version = Formulary.factory(formula_path).pkg_version
bottle_version = PkgVersion.parse hash["formula"]["pkg_version"]
bottle_version = PkgVersion.parse bottle_hash["formula"]["pkg_version"]
next if formula_version == bottle_version

odie "Bottles are for #{name} #{bottle_version} but formula is version #{formula_version}!"
end
end

def github_releases?(bottles_hash)
@github_releases ||= bottles_hash.values.all? do |bottle_hash|
root_url = bottle_hash["bottle"]["root_url"]
url_match = root_url.match HOMEBREW_RELEASES_URL_REGEX
_, _, _, tag = *url_match

tag
end
end

def pr_upload
args = pr_upload_args.parse

bintray_org = args.bintray_org || "homebrew"
bintray = Bintray.new(org: bintray_org)

json_files = Dir["*.json"]
odie "No JSON files found in the current working directory" if json_files.empty?

bottles_hash = json_files.reduce({}) do |hash, json_file|
hash.deep_merge(JSON.parse(IO.read(json_file)))
end

bottle_args = ["bottle", "--merge", "--write"]
bottle_args << "--verbose" if args.verbose?
bottle_args << "--debug" if args.debug?
@@ -62,14 +69,52 @@ def pr_upload
bottle_args += json_files

if args.dry_run?
service = if github_releases?(bottles_hash)
"GitHub Releases"
else
"Bintray"
end
puts "brew #{bottle_args.join " "}"
puts "Upload bottles described by these JSON files to Bintray:\n #{json_files.join("\n ")}"
puts "Upload bottles described by these JSON files to #{service}:\n #{json_files.join("\n ")}"
return
end

check_bottled_formulae(bottles_hash)

safe_system HOMEBREW_BREW_FILE, *bottle_args

if github_releases?(bottles_hash)
# Handle uploading to GitHub Releases.
bottles_hash.each_value do |bottle_hash|
root_url = bottle_hash["bottle"]["root_url"]
url_match = root_url.match HOMEBREW_RELEASES_URL_REGEX
_, user, repo, tag = *url_match

# Ensure a release is created.
release = begin
rel = GitHub.get_release user, repo, tag
odebug "Existing GitHub release \"#{tag}\" found"
rel
rescue GitHub::HTTPNotFoundError
odebug "Creating new GitHub release \"#{tag}\""
GitHub.create_or_update_release user, repo, tag
end

# Upload bottles as release assets.
bottle_hash["bottle"]["tags"].each_value do |tag_hash|
remote_file = tag_hash["filename"]
local_file = tag_hash["local_filename"]
odebug "Uploading #{remote_file}"
GitHub.upload_release_asset user, repo, release["id"], local_file: local_file, remote_file: remote_file
end
end
else
check_bottled_formulae(json_files)
safe_system HOMEBREW_BREW_FILE, *bottle_args
bintray.upload_bottle_json(json_files,
publish_package: !args.no_publish?,
warn_on_error: args.warn_on_upload_failure?)
# Handle uploading to Bintray.
bintray_org = args.bintray_org || "homebrew"
bintray = Bintray.new(org: bintray_org)
bintray.upload_bottles(bottles_hash,
publish_package: !args.no_publish?,
warn_on_error: args.warn_on_upload_failure?)
end
end
end
22 changes: 21 additions & 1 deletion Library/Homebrew/dev-cmd/typecheck.rb
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@
module Homebrew
module_function

SORBET_FILES_YAML = "sorbet/files.yaml"

def typecheck_args
Homebrew::CLI::Parser.new do
usage_banner <<~EOS
@@ -16,6 +18,8 @@ def typecheck_args
description: "Silence all non-critical errors."
switch "--update-definitions",
description: "Update Tapioca gem definitions of recently bumped gems"
switch "--prune-files-list",
description: "Remove deleted filepaths from #{SORBET_FILES_YAML}"
switch "--fail-if-not-changed",
description: "Return a failing status code if all gems are up to date " \
"and gem definitions do not need a tapioca update"
@@ -37,6 +41,22 @@ def typecheck
Homebrew.install_bundler_gems!

HOMEBREW_LIBRARY_PATH.cd do
if args.prune_files_list?
lines_to_keep = []
sorbet_keywords = ["true:", "false:", "strict:", "strong:"]

File.readlines(SORBET_FILES_YAML).map(&:chomp).each do |line|
if sorbet_keywords.include?(line) || line.blank?
lines_to_keep << line
elsif line.end_with?(".rb")
filepath = line.split(" ").last
lines_to_keep << line if File.exist?(filepath)
end
end

File.write(SORBET_FILES_YAML, "#{lines_to_keep.join("\n")}\n")
end

if args.update_definitions?
system "bundle", "exec", "tapioca", "sync"
system "bundle", "exec", "srb", "rbi", "hidden-definitions"
@@ -55,7 +75,7 @@ def typecheck
srb_exec += ["--file", "../#{args.file}"] if args.file
srb_exec += ["--dir", "../#{args.dir}"] if args.dir
else
srb_exec += ["--typed-override", "sorbet/files.yaml"]
srb_exec += ["--typed-override", SORBET_FILES_YAML]
end
Homebrew.failed = !system(*srb_exec)
end
14 changes: 7 additions & 7 deletions Library/Homebrew/diagnostic.rb
Original file line number Diff line number Diff line change
@@ -915,11 +915,11 @@ def check_cask_taps
none_string
else
cask_count = begin
tap.cask_files.count
rescue
error_tap_paths << tap.path
0
end
tap.cask_files.count
rescue
error_tap_paths << tap.path
0
end

"#{tap.path} (#{cask_count} #{"cask".pluralize(cask_count)})"
end
@@ -968,9 +968,9 @@ def check_cask_xattr
return if result.status.success?

if result.stderr.include? "ImportError: No module named pkg_resources"
result = system_command "/usr/bin/python", "--version"
result = Utils.popen_read "/usr/bin/python", "--version", err: :out

if result.stdout.include? "Python 2.7"
if result.include? "Python 2.7"
<<~EOS
Your Python installation has a broken version of setuptools.
To fix, reinstall macOS or run 'sudo /usr/bin/python -m pip install -I setuptools'.
6 changes: 4 additions & 2 deletions Library/Homebrew/extend/ENV/shared.rb
Original file line number Diff line number Diff line change
@@ -166,10 +166,12 @@ def fcflags
# end</pre>
def compiler
@compiler ||= if (cc = @cc)
warn_about_non_apple_gcc($&) if cc =~ GNU_GCC_REGEXP
warn_about_non_apple_gcc(cc) if cc.match?(GNU_GCC_REGEXP)

fetch_compiler(cc, "--cc")
elsif (cc = homebrew_cc)
warn_about_non_apple_gcc($&) if cc =~ GNU_GCC_REGEXP
warn_about_non_apple_gcc(cc) if cc.match?(GNU_GCC_REGEXP)

compiler = fetch_compiler(cc, "HOMEBREW_CC")

if @formula
4 changes: 2 additions & 2 deletions Library/Homebrew/extend/ENV/std.rb
Original file line number Diff line number Diff line change
@@ -46,9 +46,9 @@ def setup_build_environment(**options)

send(compiler)

return unless cc =~ GNU_GCC_REGEXP
return unless cc.match?(GNU_GCC_REGEXP)

gcc_formula = gcc_version_formula($&)
gcc_formula = gcc_version_formula(cc)
append_path "PATH", gcc_formula.opt_bin.to_s
end
alias generic_setup_build_environment setup_build_environment
2 changes: 1 addition & 1 deletion Library/Homebrew/extend/ENV/super.rb
Original file line number Diff line number Diff line change
@@ -111,7 +111,7 @@ def determine_path
path.append("/usr/bin", "/bin", "/usr/sbin", "/sbin")

begin
path.append(gcc_version_formula($&).opt_bin) if homebrew_cc =~ GNU_GCC_REGEXP
path.append(gcc_version_formula(homebrew_cc).opt_bin) if homebrew_cc.match?(GNU_GCC_REGEXP)
rescue FormulaUnavailableError
# Don't fail and don't add these formulae to the path if they don't exist.
nil
22 changes: 11 additions & 11 deletions Library/Homebrew/extend/os/mac/extend/ENV/std.rb
Original file line number Diff line number Diff line change
@@ -11,25 +11,25 @@ def homebrew_extra_pkg_config_paths

def x11
# There are some config scripts here that should go in the PATH
append_path "PATH", MacOS::X11.bin.to_s
append_path "PATH", MacOS::XQuartz.bin.to_s

# Append these to PKG_CONFIG_LIBDIR so they are searched
# *after* our own pkgconfig directories, as we dupe some of the
# libs in XQuartz.
append_path "PKG_CONFIG_LIBDIR", "#{MacOS::X11.lib}/pkgconfig"
append_path "PKG_CONFIG_LIBDIR", "#{MacOS::X11.share}/pkgconfig"
append_path "PKG_CONFIG_LIBDIR", "#{MacOS::XQuartz.lib}/pkgconfig"
append_path "PKG_CONFIG_LIBDIR", "#{MacOS::XQuartz.share}/pkgconfig"

append "LDFLAGS", "-L#{MacOS::X11.lib}"
append_path "CMAKE_PREFIX_PATH", MacOS::X11.prefix.to_s
append_path "CMAKE_INCLUDE_PATH", MacOS::X11.include.to_s
append_path "CMAKE_INCLUDE_PATH", "#{MacOS::X11.include}/freetype2"
append "LDFLAGS", "-L#{MacOS::XQuartz.lib}"
append_path "CMAKE_PREFIX_PATH", MacOS::XQuartz.prefix.to_s
append_path "CMAKE_INCLUDE_PATH", MacOS::XQuartz.include.to_s
append_path "CMAKE_INCLUDE_PATH", "#{MacOS::XQuartz.include}/freetype2"

append "CPPFLAGS", "-I#{MacOS::X11.include}"
append "CPPFLAGS", "-I#{MacOS::X11.include}/freetype2"
append "CPPFLAGS", "-I#{MacOS::XQuartz.include}"
append "CPPFLAGS", "-I#{MacOS::XQuartz.include}/freetype2"

append_path "ACLOCAL_PATH", "#{MacOS::X11.share}/aclocal"
append_path "ACLOCAL_PATH", "#{MacOS::XQuartz.share}/aclocal"

append "CFLAGS", "-I#{MacOS::X11.include}" unless MacOS::CLT.installed?
append "CFLAGS", "-I#{MacOS::XQuartz.include}" unless MacOS::CLT.installed?
end

def setup_build_environment(**options)
16 changes: 8 additions & 8 deletions Library/Homebrew/extend/os/mac/extend/ENV/super.rb
Original file line number Diff line number Diff line change
@@ -24,21 +24,21 @@ def bin

def homebrew_extra_paths
paths = []
paths << MacOS::X11.bin.to_s if x11?
paths << MacOS::XQuartz.bin.to_s if x11?
paths
end

# @private
def homebrew_extra_pkg_config_paths
paths = \
["/usr/lib/pkgconfig", "#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}"]
paths << "#{MacOS::X11.lib}/pkgconfig" << "#{MacOS::X11.share}/pkgconfig" if x11?
paths << "#{MacOS::XQuartz.lib}/pkgconfig" << "#{MacOS::XQuartz.share}/pkgconfig" if x11?
paths
end

def homebrew_extra_aclocal_paths
paths = []
paths << "#{MacOS::X11.share}/aclocal" if x11?
paths << "#{MacOS::XQuartz.share}/aclocal" if x11?
paths
end

@@ -54,7 +54,7 @@ def homebrew_extra_isystem_paths
paths = []
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/libxml2" if libxml2_include_needed?
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/apache2" if MacOS::Xcode.without_clt?
paths << MacOS::X11.include.to_s << "#{MacOS::X11.include}/freetype2" if x11?
paths << MacOS::XQuartz.include.to_s << "#{MacOS::XQuartz.include}/freetype2" if x11?
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers"
paths
end
@@ -65,7 +65,7 @@ def homebrew_extra_library_paths
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/lib"
paths << Formula["llvm"].opt_lib.to_s
end
paths << MacOS::X11.lib.to_s if x11?
paths << MacOS::XQuartz.lib.to_s if x11?
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries"
paths
end
@@ -74,14 +74,14 @@ def homebrew_extra_cmake_include_paths
paths = []
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/libxml2" if libxml2_include_needed?
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/apache2" if MacOS::Xcode.without_clt?
paths << MacOS::X11.include.to_s << "#{MacOS::X11.include}/freetype2" if x11?
paths << MacOS::XQuartz.include.to_s << "#{MacOS::XQuartz.include}/freetype2" if x11?
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers"
paths
end

def homebrew_extra_cmake_library_paths
paths = []
paths << MacOS::X11.lib.to_s if x11?
paths << MacOS::XQuartz.lib.to_s if x11?
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries"
paths
end
@@ -102,7 +102,7 @@ def determine_cccfg
end

def set_x11_env_if_installed
ENV.x11 = MacOS::X11.installed?
ENV.x11 = MacOS::XQuartz.installed?
end

# @private
4 changes: 2 additions & 2 deletions Library/Homebrew/formula.rb
Original file line number Diff line number Diff line change
@@ -1459,9 +1459,9 @@ def self.full_names
end

# @private
def self.each
def self.each(&block)
files.each do |file|
yield Formulary.factory(file)
block.call Formulary.factory(file)
rescue FormulaUnavailableError, FormulaUnreadableError => e
# Don't let one broken formula break commands. But do complain.
onoe "Failed to import: #{file}"
2 changes: 2 additions & 0 deletions Library/Homebrew/global.rb
Original file line number Diff line number Diff line change
@@ -112,6 +112,8 @@ def auditing?
%r{https://api\.github\.com/repos/([\w-]+)/([\w-]+)?/pulls/(\d+)}.freeze
HOMEBREW_PULL_OR_COMMIT_URL_REGEX =
%r[https://github\.com/([\w-]+)/([\w-]+)?/(?:pull/(\d+)|commit/[0-9a-fA-F]{4,40})].freeze
HOMEBREW_RELEASES_URL_REGEX =
%r{https://github\.com/([\w-]+)/([\w-]+)?/releases/download/(.+)}.freeze

require "PATH"

2 changes: 1 addition & 1 deletion Library/Homebrew/language/python.rb
Original file line number Diff line number Diff line change
@@ -177,7 +177,7 @@ def needs_python?(python)
def virtualenv_install_with_resources(options = {})
python = options[:using]
if python.nil?
pythons = %w[python python3 python@3 python@3.7 python@3.8 pypy pypy3]
pythons = %w[python python3 pypy pypy3] + Formula.names.select { |name| name.start_with? "python@" }
wanted = pythons.select { |py| needs_python?(py) }
raise FormulaUnknownPythonError, self if wanted.empty?
raise FormulaAmbiguousPythonError, self if wanted.size > 1
37 changes: 35 additions & 2 deletions Library/Homebrew/livecheck/livecheck.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require "livecheck/strategy"
require "ruby-progressbar"

module Homebrew
# The `Livecheck` module consists of methods used by the `brew livecheck`
@@ -66,6 +67,27 @@ def livecheck_formulae(formulae_to_check, args)
@livecheck_strategy_names.freeze

has_a_newer_upstream_version = false

if args.json? && !args.quiet? && $stderr.tty?
total_formulae = if formulae_to_check == Formula
formulae_to_check.count
else
formulae_to_check.length
end

Tty.with($stderr) do |stderr|
stderr.puts Formatter.headline("Running checks", color: :blue)
end

progress = ProgressBar.create(
total: total_formulae,
progress_mark: "#",
remainder_mark: ".",
format: " %t: [%B] %c/%C ",
output: $stderr,
)
end

formulae_checked = formulae_to_check.sort.map.with_index do |formula, i|
if args.debug? && i.positive?
puts <<~EOS
@@ -78,7 +100,7 @@ def livecheck_formulae(formulae_to_check, args)
skip_result = skip_conditions(formula, args: args)
next skip_result if skip_result != false

formula.head.downloader.shutup! if formula.head?
formula.head&.downloader&.shutup!

current = if formula.head?
formula.any_installed_version.version.commit
@@ -136,6 +158,7 @@ def livecheck_formulae(formulae_to_check, args)
has_a_newer_upstream_version ||= true

if args.json?
progress&.increment
info.except!(:meta) unless args.verbose?
next info
end
@@ -146,6 +169,7 @@ def livecheck_formulae(formulae_to_check, args)
Homebrew.failed = true

if args.json?
progress&.increment
status_hash(formula, "error", [e.to_s], args: args)
elsif !args.quiet?
onoe "#{Tty.blue}#{formula_name(formula, args: args)}#{Tty.reset}: #{e}"
@@ -157,7 +181,16 @@ def livecheck_formulae(formulae_to_check, args)
puts "No newer upstream versions."
end

puts JSON.generate(formulae_checked.compact) if args.json?
return unless args.json?

if progress
progress.finish
Tty.with($stderr) do |stderr|
stderr.print "#{Tty.up}#{Tty.erase_line}" * 2
end
end

puts JSON.generate(formulae_checked.compact)
end

# Returns the fully-qualified name of a formula if the full_name argument is
8 changes: 4 additions & 4 deletions Library/Homebrew/os/mac/xquartz.rb
Original file line number Diff line number Diff line change
@@ -2,7 +2,10 @@

module OS
module Mac
X11 = XQuartz = Module.new do # rubocop:disable Style/MutableConstant
# Helper module for querying XQuartz information.
#
# @api private
module XQuartz
module_function

DEFAULT_BUNDLE_PATH = Pathname.new("Applications/Utilities/XQuartz.app").freeze
@@ -83,9 +86,6 @@ def version_from_pkgutil
PKGINFO_VERSION_MAP.fetch(str, str)
end

# This should really be private, but for compatibility reasons it must
# remain public. New code should use `MacOS::X11.bin`, `MacOS::X11.lib` and
# `MacOS::X11.include` instead, as that accounts for Xcode-only systems.
def prefix
@prefix ||= Pathname.new("/opt/X11") if Pathname.new("/opt/X11/lib/libpng.dylib").exist?
end
1 change: 1 addition & 0 deletions Library/Homebrew/rubocops.rb
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
require "rubocops/options"
require "rubocops/urls"
require "rubocops/lines"
require "rubocops/livecheck"
require "rubocops/class"
require "rubocops/uses_from_macos"
require "rubocops/files"
251 changes: 251 additions & 0 deletions Library/Homebrew/rubocops/livecheck.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# frozen_string_literal: true

require "rubocops/extend/formula"

module RuboCop
module Cop
module FormulaAudit
# This cop ensures that no other livecheck information is provided for
# skipped formulae.
#
# @api private
class LivecheckSkip < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank?

skip = find_every_method_call_by_name(livecheck_node, :skip).first
return if skip.blank?

return if find_every_method_call_by_name(livecheck_node).length < 3

offending_node(livecheck_node)
problem "Skipped formulae must not contain other livecheck information."
end

def autocorrect(node)
lambda do |corrector|
skip = find_every_method_call_by_name(node, :skip).first
skip = find_strings(skip).first
skip = string_content(skip) if skip.present?
corrector.replace(
node.source_range,
<<~EOS.strip,
livecheck do
skip#{" \"#{skip}\"" if skip.present?}
end
EOS
)
end
end
end

# This cop ensures that a `url` is specified in the livecheck block.
#
# @api private
class LivecheckUrlProvided < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank?

skip = find_every_method_call_by_name(livecheck_node, :skip).first
return if skip.present?

livecheck_url = find_every_method_call_by_name(livecheck_node, :url).first
return if livecheck_url.present?

offending_node(livecheck_node)
problem "A `url` must be provided to livecheck."
end
end

# This cop ensures that a supported symbol (`head`, `stable, `homepage`)
# is used when the livecheck `url` is identical to one of these formula URLs.
#
# @api private
class LivecheckUrlSymbol < FormulaCop
@offense = nil

def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank?

skip = find_every_method_call_by_name(livecheck_node, :skip).first.present?
return if skip.present?

livecheck_url_node = find_every_method_call_by_name(livecheck_node, :url).first
livecheck_url = find_strings(livecheck_url_node).first
return if livecheck_url.blank?

livecheck_url = string_content(livecheck_url)

head = find_every_method_call_by_name(body_node, :head).first
head_url = find_strings(head).first

if head.present? && head_url.blank?
head = find_every_method_call_by_name(head, :url).first
head_url = find_strings(head).first
end

head_url = string_content(head_url) if head_url.present?

stable = find_every_method_call_by_name(body_node, :url).first
stable_url = find_strings(stable).first

if stable_url.blank?
stable = find_every_method_call_by_name(body_node, :stable).first
stable = find_every_method_call_by_name(stable, :url).first
stable_url = find_strings(stable).first
end

stable_url = string_content(stable_url) if stable_url.present?

homepage = find_every_method_call_by_name(body_node, :homepage).first
homepage_url = string_content(find_strings(homepage).first) if homepage.present?

formula_urls = { head: head_url, stable: stable_url, homepage: homepage_url }.compact

formula_urls.each do |symbol, url|
next if url != livecheck_url && url != "#{livecheck_url}/" && "#{url}/" != livecheck_url

offending_node(livecheck_url_node)
@offense = symbol
problem "Use `url :#{symbol}`"
break
end
end

def autocorrect(node)
lambda do |corrector|
corrector.replace(node.source_range, "url :#{@offense}")
@offense = nil
end
end
end

# This cop ensures that the `regex` call in the livecheck block uses parentheses.
#
# @api private
class LivecheckRegexParentheses < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank?

skip = find_every_method_call_by_name(livecheck_node, :skip).first.present?
return if skip.present?

livecheck_regex_node = find_every_method_call_by_name(livecheck_node, :regex).first
return if livecheck_regex_node.blank?

return if parentheses?(livecheck_regex_node)

offending_node(livecheck_regex_node)
problem "The `regex` call should always use parentheses."
end

def autocorrect(node)
lambda do |corrector|
pattern = node.source.split(" ")[1..].join
corrector.replace(node.source_range, "regex(#{pattern})")
end
end
end

# This cop ensures that the pattern provided to livecheck's `regex` uses `\.t` instead of
# `\.tgz`, `\.tar.gz` and variants.
#
# @api private
class LivecheckRegexExtension < FormulaCop
TAR_PATTERN = /\\?\.t(ar|(g|l|x)z$|[bz2]{2,4}$)(\\?\.((g|l|x)z)|[bz2]{2,4}|Z)?$/i.freeze

def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank?

skip = find_every_method_call_by_name(livecheck_node, :skip).first.present?
return if skip.present?

livecheck_regex_node = find_every_method_call_by_name(livecheck_node, :regex).first
return if livecheck_regex_node.blank?

regex_node = livecheck_regex_node.descendants.first
pattern = string_content(find_strings(regex_node).first)
match = pattern.match(TAR_PATTERN)
return if match.blank?

offending_node(regex_node)
problem "Use `\\.t` instead of `#{match}`"
end

def autocorrect(node)
lambda do |corrector|
node = find_strings(node).first
correct = node.source.gsub(TAR_PATTERN, "\\.t")
corrector.replace(node.source_range, correct)
end
end
end

# This cop ensures that a `regex` is provided when `strategy :page_match` is specified
# in the livecheck block.
#
# @api private
class LivecheckRegexIfPageMatch < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank?

skip = find_every_method_call_by_name(livecheck_node, :skip).first.present?
return if skip.present?

livecheck_strategy_node = find_every_method_call_by_name(livecheck_node, :strategy).first
return if livecheck_strategy_node.blank?

strategy = livecheck_strategy_node.descendants.first.source
return if strategy != ":page_match"

livecheck_regex_node = find_every_method_call_by_name(livecheck_node, :regex).first
return if livecheck_regex_node.present?

offending_node(livecheck_node)
problem "A `regex` is required if `strategy :page_match` is present."
end
end

# This cop ensures that the `regex` provided to livecheck is case-insensitive,
# unless sensitivity is explicitly required for proper matching.
#
# @api private
class LivecheckRegexCaseInsensitive < FormulaCop
REGEX_CASE_SENSITIVE_ALLOWLIST = %w[].freeze

def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if REGEX_CASE_SENSITIVE_ALLOWLIST.include?(@formula_name)

livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank?

skip = find_every_method_call_by_name(livecheck_node, :skip).first.present?
return if skip.present?

livecheck_regex_node = find_every_method_call_by_name(livecheck_node, :regex).first
return if livecheck_regex_node.blank?

regex_node = livecheck_regex_node.descendants.first
options_node = regex_node.regopt
return if options_node.source.include?("i")

offending_node(regex_node)
problem "Regexes should be case-insensitive unless sensitivity is explicitly required for proper matching."
end

def autocorrect(node)
lambda do |corrector|
node = node.regopt
corrector.replace(node.source_range, "i#{node.source}".chars.sort.join)
end
end
end
end
end
end
10 changes: 4 additions & 6 deletions Library/Homebrew/rubocops/shared/desc_helper.rb
Original file line number Diff line number Diff line change
@@ -49,10 +49,8 @@ def audit_desc(type, name, desc_call)
problem "Description should use \"#{c}ommand-line\" instead of \"#{match}\"."
end

# Check if the desc starts with "A" or "An".
if match = regex_match_group(desc, /^(an?)(?=\s)/i)
problem "Description shouldn't start with an indefinite article, i.e. \"#{match}\"."
end
# Check if the desc starts with an article.
problem "Description shouldn't start with an article." if regex_match_group(desc, /^(the|an?)(?=\s)/i)

# Check if invalid lowercase words are at the start of a desc.
if !VALID_LOWERCASE_WORDS.include?(string_content(desc).split.first) &&
@@ -65,7 +63,7 @@ def audit_desc(type, name, desc_call)
problem "Description shouldn't start with the #{type} name." if regex_match_group(desc, /^#{name_regex}\b/i)

if type == :cask &&
(match = regex_match_group(desc, /\b(macOS|Mac( ?OS( ?X)?)?|OS ?X)\b/i)) &&
(match = regex_match_group(desc, /\b(macOS|Mac( ?OS( ?X)?)?|OS ?X)(?! virtual machines?)\b/i)) &&
match[1] != "MAC"
problem "Description shouldn't contain the platform."
end
@@ -91,7 +89,7 @@ def autocorrect_desc(node, name)
correction.gsub!(/^\s+/, "")
correction.gsub!(/\s+$/, "")

correction.sub!(/^an?\s+/i, "")
correction.sub!(/^(the|an?)\s+/i, "")

first_word = correction.split.first
unless VALID_LOWERCASE_WORDS.include?(first_word)
382 changes: 189 additions & 193 deletions Library/Homebrew/sorbet/files.yaml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DO NOT EDIT MANUALLY
# This is an autogenerated file for types exported from the `rubocop-ast` gem.
# Please instead update this file by running `tapioca generate --exclude json`.
# Please instead update this file by running `tapioca sync`.

# typed: true

@@ -215,6 +215,7 @@ module RuboCop::AST::CollectionNode
def rotate(*args, &block); end
def rotate!(*args, &block); end
def sample(*args, &block); end
def save_plist(*args, &block); end
def select(*args, &block); end
def select!(*args, &block); end
def shelljoin(*args, &block); end
@@ -236,6 +237,7 @@ module RuboCop::AST::CollectionNode
def take_while(*args, &block); end
def to_ary(*args, &block); end
def to_h(*args, &block); end
def to_plist(*args, &block); end
def to_set(*args, &block); end
def transpose(*args, &block); end
def union(*args, &block); end
@@ -256,6 +258,16 @@ module RuboCop::AST::ConditionalNode
def single_line_condition?; end
end

class RuboCop::AST::ConstNode < ::RuboCop::AST::Node
def absolute?; end
def class_name?; end
def each_path(&block); end
def module_name?; end
def namespace; end
def relative?; end
def short_name; end
end

class RuboCop::AST::DefNode < ::RuboCop::AST::Node
include(::RuboCop::AST::ParameterizedNode)
include(::RuboCop::AST::MethodIdentifierPredicates)
@@ -626,6 +638,8 @@ class RuboCop::AST::Node < ::Parser::AST::Node
def lambda_or_proc?(node = T.unsafe(nil)); end
def lambda_type?; end
def last_line; end
def left_sibling; end
def left_siblings; end
def line_count; end
def literal?; end
def loop_keyword?; end
@@ -692,6 +706,8 @@ class RuboCop::AST::Node < ::Parser::AST::Node
def restarg_type?; end
def retry_type?; end
def return_type?; end
def right_sibling; end
def right_siblings; end
def root_type?; end
def sclass_type?; end
def self_type?; end
@@ -911,7 +927,9 @@ class RuboCop::AST::ProcessedSource
def file_path; end
def find_comment(&block); end
def find_token(&block); end
def first_token_of(range_or_node); end
def following_line(token); end
def last_token_of(range_or_node); end
def line_indentation(line_number); end
def line_with_comment?(line); end
def lines; end
@@ -922,14 +940,19 @@ class RuboCop::AST::ProcessedSource
def ruby_version; end
def start_with?(string); end
def tokens; end
def tokens_within(range_or_node); end
def valid_syntax?; end

private

def comment_index; end
def create_parser(ruby_version); end
def first_token_index(range_or_node); end
def last_token_index(range_or_node); end
def parse(source, ruby_version); end
def parser_class(ruby_version); end
def sorted_tokens; end
def source_range(range_or_node); end
def tokenize(parser); end

class << self
@@ -945,6 +968,8 @@ class RuboCop::AST::RangeNode < ::RuboCop::AST::Node
end

class RuboCop::AST::RegexpNode < ::RuboCop::AST::Node
include(::RuboCop::Ext::RegexpNode)

def content; end
def delimiter?(char); end
def delimiters; end
@@ -968,7 +993,17 @@ RuboCop::AST::RegexpNode::OPTIONS = T.let(T.unsafe(nil), Hash)

class RuboCop::AST::ResbodyNode < ::RuboCop::AST::Node
def body; end
def branch_index; end
def exception_variable; end
def exceptions; end
end

class RuboCop::AST::RescueNode < ::RuboCop::AST::Node
def body; end
def branches; end
def else?; end
def else_branch; end
def resbody_branches; end
end

class RuboCop::AST::ReturnNode < ::RuboCop::AST::Node
@@ -1129,6 +1164,7 @@ module RuboCop::AST::Traversal
def on_match_with_trailing_comma(node); end
def on_mlhs(node); end
def on_module(node); end
def on_mrasgn(node); end
def on_next(node); end
def on_nil(node); end
def on_not(node); end
@@ -1143,6 +1179,7 @@ module RuboCop::AST::Traversal
def on_postexe(node); end
def on_preexe(node); end
def on_procarg0(node); end
def on_rasgn(node); end
def on_rational(node); end
def on_redo(node); end
def on_regexp(node); end
Original file line number Diff line number Diff line change
@@ -238,12 +238,20 @@ class RuboCop::Cop::Performance::Detect < ::RuboCop::Cop::Base
private

def accept_first_call?(receiver, body); end
def autocorrect(corrector, node); end
def autocorrect(corrector, node, replacement); end
def lazy?(node); end
def message_for_method(method, index); end
def preferred_method; end
def register_offense(node, receiver, second_method); end
def register_offense(node, receiver, second_method, index); end
def replacement(method, index); end
end

RuboCop::Cop::Performance::Detect::CANDIDATE_METHODS = T.let(T.unsafe(nil), Set)

RuboCop::Cop::Performance::Detect::INDEX_MSG = T.let(T.unsafe(nil), String)

RuboCop::Cop::Performance::Detect::INDEX_REVERSE_MSG = T.let(T.unsafe(nil), String)

RuboCop::Cop::Performance::Detect::MSG = T.let(T.unsafe(nil), String)

RuboCop::Cop::Performance::Detect::REVERSE_MSG = T.let(T.unsafe(nil), String)
@@ -677,8 +685,8 @@ class RuboCop::Cop::Performance::Sum < ::RuboCop::Cop::Base
def build_block_bad_method(method, init, var_acc, var_elem, body); end
def build_block_message(send, init, var_acc, var_elem, body); end
def build_good_method(init); end
def build_method_bad_method(init, method); end
def build_method_message(method, init); end
def build_method_bad_method(init, method, operation); end
def build_method_message(method, init, operation); end
def sum_block_range(send, node); end
def sum_method_range(node); end
end

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi
Original file line number Diff line number Diff line change
@@ -13372,6 +13372,7 @@ class Object
HOMEBREW_PRODUCT = ::T.let(nil, ::T.untyped)
HOMEBREW_PULL_API_REGEX = ::T.let(nil, ::T.untyped)
HOMEBREW_PULL_OR_COMMIT_URL_REGEX = ::T.let(nil, ::T.untyped)
HOMEBREW_RELEASES_URL_REGEX = ::T.let(nil, ::T.untyped)
HOMEBREW_REPOSITORY = ::T.let(nil, ::T.untyped)
HOMEBREW_REQUIRED_RUBY_VERSION = ::T.let(nil, ::T.untyped)
HOMEBREW_SHIMS_PATH = ::T.let(nil, ::T.untyped)
@@ -20081,14 +20082,10 @@ end
module RuboCop::AST::CollectionNode
def extract_options!(*args, &block); end

def save_plist(*args, &block); end

def to_default_s(*args, &block); end

def to_formatted_s(*args, &block); end

def to_plist(*args, &block); end

def to_sentence(*args, &block); end

def to_xml(*args, &block); end
@@ -20108,10 +20105,6 @@ class RuboCop::AST::Node
def val_node(node=T.unsafe(nil)); end
end

class RuboCop::AST::RegexpNode
include ::RuboCop::Ext::RegexpNode
end

class RuboCop::Cask::AST::CaskBlock
def cask_body(*args, &block); end
end
@@ -23802,10 +23795,18 @@ module Tty

def self.default(); end

def self.down(); end

def self.erase_char(); end

def self.erase_line(); end

def self.green(); end

def self.italic(); end

def self.left(); end

def self.magenta(); end

def self.no_underline(); end
@@ -23814,10 +23815,14 @@ module Tty

def self.reset(); end

def self.right(); end

def self.strikethrough(); end

def self.underline(); end

def self.up(); end

def self.yellow(); end
end

3 changes: 1 addition & 2 deletions Library/Homebrew/sorbet/rbi/utils/inreplace.rbi
Original file line number Diff line number Diff line change
@@ -3,9 +3,8 @@
module Utils::Inreplace
include Kernel

sig { params(paths: T::Array[T.untyped], before: T.nilable(String), after: T.nilable(String), audit_result: T::Boolean).void }
sig { params(paths: T::Array[T.untyped], before: T.nilable(String), after: T.nilable(T.any(String, Symbol)), audit_result: T::Boolean).void }
def inreplace(paths, before = nil, after = nil, audit_result = true); end

end

class StringInreplaceExtension
20 changes: 11 additions & 9 deletions Library/Homebrew/tap.rb
Original file line number Diff line number Diff line change
@@ -256,7 +256,7 @@ def install(full_clone: true, quiet: false, clone_target: nil, force_auto_update
return if !full_clone || !shallow?
end

ohai "Unshallowing #{name}" unless quiet
$stderr.ohai "Unshallowing #{name}" unless quiet
args = %w[fetch --unshallow]
args << "-q" if quiet
path.cd { safe_system "git", *args }
@@ -265,7 +265,7 @@ def install(full_clone: true, quiet: false, clone_target: nil, force_auto_update

clear_cache

ohai "Tapping #{name}" unless quiet
$stderr.ohai "Tapping #{name}" unless quiet
args = %W[clone #{requested_remote} #{path}]
args << "--depth=1" unless full_clone
args << "-q" if quiet
@@ -291,7 +291,7 @@ def install(full_clone: true, quiet: false, clone_target: nil, force_auto_update
link_completions_and_manpages

formatted_contents = contents.presence&.to_sentence&.dup&.prepend(" ")
puts "Tapped#{formatted_contents} (#{path.abv})." unless quiet
$stderr.puts "Tapped#{formatted_contents} (#{path.abv})." unless quiet
CacheStoreDatabase.use(:descriptions) do |db|
DescriptionCacheStore.new(db)
.update_from_formula_names!(formula_names)
@@ -301,7 +301,7 @@ def install(full_clone: true, quiet: false, clone_target: nil, force_auto_update
return unless private?
return if quiet

puts <<~EOS
$stderr.puts <<~EOS
It looks like you tapped a private repository. To avoid entering your
credentials each time you update, you can use git HTTP credential
caching or issue the following command:
@@ -321,7 +321,7 @@ def uninstall
require "descriptions"
raise TapUnavailableError, name unless installed?

puts "Untapping #{name}..."
$stderr.puts "Untapping #{name}..."

abv = path.abv
formatted_contents = contents.presence&.to_sentence&.dup&.prepend(" ")
@@ -335,7 +335,7 @@ def uninstall
Utils::Link.unlink_completions(path)
path.rmtree
path.parent.rmdir_if_possible
puts "Untapped#{formatted_contents} (#{abv})."
$stderr.puts "Untapped#{formatted_contents} (#{abv})."

Commands.rebuild_commands_completion_list
clear_cache
@@ -552,14 +552,14 @@ def ==(other)
self.class == other.class && name == other.name
end

def self.each
def self.each(&block)
return unless TAP_DIRECTORY.directory?

return to_enum unless block_given?

TAP_DIRECTORY.subdirs.each do |user|
user.subdirs.each do |repo|
yield fetch(user.basename.to_s, repo.basename.to_s)
block.call fetch(user.basename.to_s, repo.basename.to_s)
end
end
end
@@ -625,7 +625,9 @@ def self.ensure_installed!

def install(full_clone: true, quiet: false, clone_target: nil, force_auto_update: nil)
remote = Homebrew::EnvConfig.core_git_remote
puts "HOMEBREW_CORE_GIT_REMOTE set: using #{remote} for Homebrew/core Git remote URL." if remote != default_remote
if remote != default_remote
$stderr.puts "HOMEBREW_CORE_GIT_REMOTE set: using #{remote} for Homebrew/core Git remote URL."
end
super(full_clone: full_clone, quiet: quiet, clone_target: remote, force_auto_update: force_auto_update)
end

5 changes: 5 additions & 0 deletions Library/Homebrew/test.rb
Original file line number Diff line number Diff line change
@@ -24,6 +24,11 @@

trap("INT", old_trap)

if Homebrew::EnvConfig.developer? || ENV["CI"].present?
raise "cannot find child processes without `pgrep`, please install!" unless which("pgrep")
raise "cannot kill child processes without `pkill`, please install!" unless which("pkill")
end

formula = args.named.to_resolved_formulae.first
formula.extend(Homebrew::Assertions)
formula.extend(Homebrew::FreePort)
1 change: 1 addition & 0 deletions Library/Homebrew/test/.rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -96,6 +96,7 @@ RSpec/MultipleDescribes:
- 'rubocops/deprecate_disable_spec.rb'
- 'rubocops/formula_desc_spec.rb'
- 'rubocops/lines_spec.rb'
- 'rubocops/livecheck_spec.rb'
- 'rubocops/text_spec.rb'
- 'rubocops/urls_spec.rb'
- 'software_spec_spec.rb'
267 changes: 137 additions & 130 deletions Library/Homebrew/test/cask/audit_spec.rb

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Library/Homebrew/test/cask/cmd/cat_spec.rb
Original file line number Diff line number Diff line change
@@ -15,6 +15,8 @@
sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
url "https://brew.sh/TestCask.dmg"
name "Basic Cask"
desc "Cask for testing basic functionality"
homepage "https://brew.sh/"
app "TestCask.app"
2 changes: 1 addition & 1 deletion Library/Homebrew/test/cask/depends_on_spec.rb
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@

describe "depends_on x11" do
before do
allow(MacOS::X11).to receive(:installed?).and_return(x11_installed)
allow(MacOS::XQuartz).to receive(:installed?).and_return(x11_installed)
end

context "when satisfied" do
4 changes: 2 additions & 2 deletions Library/Homebrew/test/cask/verify_spec.rb
Original file line number Diff line number Diff line change
@@ -31,15 +31,15 @@ module Cask
let(:expected_sha256) { nil }

it "raises an error" do
expect { verification }.to raise_error CaskSha256MissingError
expect { verification }.to raise_error(CaskSha256MissingError, /sha256 "#{computed_sha256}"/)
end
end

context "when the expected checksum is empty" do
let(:expected_sha256) { "" }

it "raises an error" do
expect { verification }.to raise_error CaskSha256MissingError
expect { verification }.to raise_error(CaskSha256MissingError, /sha256 "#{computed_sha256}"/)
end
end

3 changes: 1 addition & 2 deletions Library/Homebrew/test/cmd/tap_spec.rb
Original file line number Diff line number Diff line change
@@ -11,8 +11,7 @@
path = setup_test_tap

expect { brew "tap", "--force-auto-update", "--full", "homebrew/bar", path/".git" }
.to output(/Tapped/).to_stdout
.and output(/Cloning/).to_stderr
.to output(/Tapped/).to_stderr
.and be_a_success
end
end
4 changes: 2 additions & 2 deletions Library/Homebrew/test/cmd/untap_spec.rb
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@
setup_test_tap

expect { brew "untap", "homebrew/foo" }
.to output(/Untapped/).to_stdout
.and not_to_output.to_stderr
.to output(/Untapped/).to_stderr
.and not_to_output.to_stdout
.and be_a_success
end
end
2 changes: 1 addition & 1 deletion Library/Homebrew/test/language/java_spec.rb
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
describe Language::Java do
describe "::java_home" do
it "returns valid JAVA_HOME if version is specified", :needs_java do
java_home = described_class.java_home("1.8+")
java_home = described_class.java_home("1.6+")
expect(java_home/"bin/java").to be_an_executable
end

24 changes: 22 additions & 2 deletions Library/Homebrew/test/rubocops/cask/desc_spec.rb
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
describe RuboCop::Cop::Cask::Desc do
subject(:cop) { described_class.new }

it "does not start with an indefinite article" do
it "does not start with an article" do
expect_no_offenses <<~RUBY
cask "foo" do
desc "Bar program"
@@ -16,7 +16,14 @@
expect_offense <<~RUBY, "/homebrew-cask/Casks/foo.rb"
cask 'foo' do
desc 'A bar program'
^ Description shouldn\'t start with an indefinite article, i.e. \"A\".
^ Description shouldn\'t start with an article.
end
RUBY

expect_offense <<~RUBY, "/homebrew-cask/Casks/foo.rb"
cask 'foo' do
desc 'The bar program'
^^^ Description shouldn\'t start with an article.
end
RUBY

@@ -93,6 +100,19 @@
end
RUBY

expect_no_offenses <<~RUBY
cask 'foo' do
desc 'Application for managing macOS virtual machines'
end
RUBY

expect_offense <<~RUBY
cask 'foo' do
desc 'Application for managing macOS virtual machines on macOS'
^^^^^ Description shouldn\'t contain the platform.
end
RUBY

expect_no_offenses <<~RUBY
cask 'foo' do
desc 'MAC address changer'
10 changes: 9 additions & 1 deletion Library/Homebrew/test/rubocops/formula_desc_spec.rb
Original file line number Diff line number Diff line change
@@ -84,7 +84,15 @@ class Foo < Formula
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
desc 'An aardvark'
^^ Description shouldn\'t start with an indefinite article, i.e. \"An\".
^^ Description shouldn\'t start with an article.
end
RUBY

expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
desc 'The aardvark'
^^^ Description shouldn\'t start with an article.
end
RUBY
end
270 changes: 270 additions & 0 deletions Library/Homebrew/test/rubocops/livecheck_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
# frozen_string_literal: true

require "rubocops/livecheck"

describe RuboCop::Cop::FormulaAudit::LivecheckSkip do
subject(:cop) { described_class.new }

it "reports an offense when a skipped formula's livecheck block contains other information" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
^^^^^^^^^^^^ Skipped formulae must not contain other livecheck information.
skip "Not maintained"
url :stable
end
end
RUBY

expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
skip "Not maintained"
end
end
RUBY
end

it "reports no offenses when a skipped formula's livecheck block contains no other information" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
skip "Not maintained"
end
end
RUBY
end
end

describe RuboCop::Cop::FormulaAudit::LivecheckUrlProvided do
subject(:cop) { described_class.new }

it "reports an offense when a `url` is not specified in the livecheck block" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
^^^^^^^^^^^^ A `url` must be provided to livecheck.
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end

it "reports no offenses when a `url` is specified in the livecheck block" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

describe RuboCop::Cop::FormulaAudit::LivecheckUrlSymbol do
subject(:cop) { described_class.new }

it "reports an offense when the `url` specified in the livecheck block is identical to a formula URL" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url "https://brew.sh/foo-1.0.tgz"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `url :stable`
end
end
RUBY

expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
end
end
RUBY
end

it "reports no offenses when the `url` specified in the livecheck block is not identical to a formula URL" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url "https://brew.sh/foo/releases/"
end
end
RUBY
end
end

describe RuboCop::Cop::FormulaAudit::LivecheckRegexParentheses do
subject(:cop) { described_class.new }

it "reports an offense when the `regex` call in the livecheck block does not use parentheses" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex %r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The `regex` call should always use parentheses.
end
end
RUBY

expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end

it "reports no offenses when the `regex` call in the livecheck block uses parentheses" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

describe RuboCop::Cop::FormulaAudit::LivecheckRegexExtension do
subject(:cop) { described_class.new }

it "reports an offense when the `regex` does not use `\\.t` for archive file extensions" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.tgz}i)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `\\.t` instead of `\\.tgz`
end
end
RUBY

expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end

it "reports no offenses when the `regex` uses `\\.t` for archive file extensions" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

describe RuboCop::Cop::FormulaAudit::LivecheckRegexIfPageMatch do
subject(:cop) { described_class.new }

it "reports an offense when there is no `regex` for `strategy :page_match`" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
^^^^^^^^^^^^ A `regex` is required if `strategy :page_match` is present.
url :stable
strategy :page_match
end
end
RUBY
end

it "rreports no offenses when a `regex` is specified for `strategy :page_match`" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
strategy :page_match
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

describe RuboCop::Cop::FormulaAudit::LivecheckRegexCaseInsensitive do
subject(:cop) { described_class.new }

it "reports an offense when the `regex` is not case-insensitive" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t})
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Regexes should be case-insensitive unless sensitivity is explicitly required for proper matching.
end
end
RUBY

expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end

it "reports no offenses when the `regex` is case-insensitive" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end
Original file line number Diff line number Diff line change
@@ -3,7 +3,8 @@
sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"

url "https://brew.sh/TestCask.dmg"
name "Adobe Air"
name "Adobe AIR"
desc "Cross-platform application runtime"
homepage "https://brew.sh/"

app "TestCask.app"
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
sha256 "5633c3a0f2e572cbf021507dec78c50998b398c343232bdfc7e26221d0a5db4d"

url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyApp.zip"
name "Auto-Updates"
desc "Cask which auto-updates"
homepage "https://brew.sh/MyFancyApp"

auto_updates true
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"

url "https://brew.sh/TestCask.dmg"
name "Basic Cask"
desc "Cask for testing basic functionality"
homepage "https://brew.sh/"

app "TestCask.app"
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
sha256 :no_check

url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
name "Latest with Auto-Updates"
desc "Unversioned cask which auto-updates"
homepage "https://brew.sh/latest-with-auto-updates"

auto_updates true
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"

url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyPkg.zip"
name "PKG without Uninstall"
desc "Cask with a package installer and no uninstall stanza"
homepage "https://brew.sh/fancy-pkg"

pkg "Fancy.pkg"
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
sha256 :no_check

url "file://#{TEST_FIXTURE_DIR}/cask/caffeines.zip"
name "Version Latest"
desc "Unversioned cask"
homepage "https://brew.sh/"

app "Caffeine Mini.app"
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
sha256 "d5b2dfbef7ea28c25f7a77cd7fa14d013d82b626db1d82e00e25822464ba19e2"

url "file://#{TEST_FIXTURE_DIR}/cask/AppWithBinary.zip"
name "With Binary"
desc "Cask with a binary stanza"
homepage "https://brew.sh/with-binary"

app "App.app"
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94"

url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
name "With Installer Manual"
desc "Cask with a manual installer"
homepage "https://brew.sh/"

installer manual: "Caffeine.app"
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@

url "https://brew.sh/ThirdParty.dmg"
name "Pharo"
desc "Cask from a third-party tap"
homepage "https://brew.sh/"

app "ThirdParty.app"
8 changes: 8 additions & 0 deletions Library/Homebrew/test/utils/git_spec.rb
Original file line number Diff line number Diff line change
@@ -44,6 +44,14 @@
let(:files_hash1) { [@h3[0..6], ["LICENSE.txt"]] }
let(:files_hash2) { [@h2[0..6], ["README.md"]] }

describe "#cherry_pick!" do
it "aborts when cherry picking an existing hash" do
expect {
described_class.cherry_pick!(HOMEBREW_CACHE, file_hash1)
}.to raise_error(ErrorDuringExecution, /Merge conflict in README.md/)
end
end

describe "#last_revision_commit_of_file" do
it "gives last revision commit when before_commit is nil" do
expect(
4 changes: 2 additions & 2 deletions Library/Homebrew/unpack_strategy/dmg.rb
Original file line number Diff line number Diff line change
@@ -132,7 +132,7 @@ def mount(verbose: false)
without_eula = system_command(
"hdiutil",
args: [
"attach", "-plist", "-nobrowse", "-readonly", "-noidme",
"attach", "-plist", "-nobrowse", "-readonly",
"-mountrandom", mount_dir, path
],
input: "qn\n",
@@ -159,7 +159,7 @@ def mount(verbose: false)
with_eula = system_command!(
"hdiutil",
args: [
"attach", "-plist", "-nobrowse", "-readonly", "-noidme",
"attach", "-plist", "-nobrowse", "-readonly",
"-mountrandom", mount_dir, cdr_path
],
verbose: verbose,
1 change: 1 addition & 0 deletions Library/Homebrew/upgrade.rb
Original file line number Diff line number Diff line change
@@ -142,6 +142,7 @@ def check_installed_dependents(args:)

outdated_dependents =
installed_formulae.flat_map(&:runtime_installed_formula_dependents)
.uniq
.select(&:outdated?)
return if outdated_dependents.blank? && already_broken_dependents.blank?

8 changes: 6 additions & 2 deletions Library/Homebrew/utils.rb
Original file line number Diff line number Diff line change
@@ -131,11 +131,15 @@ def oh1(title, truncate: :auto)

# Print a warning (do this rarely)
def opoo(message)
$stderr.puts Formatter.warning(message, label: "Warning")
Tty.with($stderr) do |stderr|
stderr.puts Formatter.warning(message, label: "Warning")
end
end

def onoe(message)
$stderr.puts Formatter.error(message, label: "Error")
Tty.with($stderr) do |stderr|
stderr.puts Formatter.error(message, label: "Error")
end
end

def ofail(error)
2 changes: 2 additions & 0 deletions Library/Homebrew/utils/curl.rb
Original file line number Diff line number Diff line change
@@ -32,6 +32,8 @@ def curl_args(*extra_args, show_output: false, user_agent: :default)
user_agent
end

args << "--header" << "Accept-Language: en"

unless show_output
args << "--fail"
args << "--progress-bar" unless Context.current.verbose?
2 changes: 1 addition & 1 deletion Library/Homebrew/utils/gems.rb
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@

module Homebrew
# Keep in sync with the Gemfile.lock's BUNDLED WITH.
HOMEBREW_BUNDLER_VERSION = "1.17.2"
HOMEBREW_BUNDLER_VERSION = "1.17.3"

module_function

49 changes: 29 additions & 20 deletions Library/Homebrew/utils/git.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require "open3"

module Utils
# Helper functions for querying Git information.
#
@@ -16,15 +14,21 @@ def available?
def version
return @version if defined?(@version)

stdout, _, status = system_command(HOMEBREW_SHIMS_PATH/"scm/git", args: ["--version"], print_stderr: false)
stdout, _, status = system_command(git, args: ["--version"], print_stderr: false)
@version = status.success? ? stdout.chomp[/git version (\d+(?:\.\d+)*)/, 1] : nil
end

def path
return unless available?
return @path if defined?(@path)

@path = Utils.popen_read(HOMEBREW_SHIMS_PATH/"scm/git", "--homebrew=print-path").chomp.presence
@path = Utils.popen_read(git, "--homebrew=print-path").chomp.presence
end

def git
return @git if defined?(@git)

@git = HOMEBREW_SHIMS_PATH/"scm/git"
end

def remote_exists?(url)
@@ -36,6 +40,7 @@ def remote_exists?(url)
def clear_available_cache
remove_instance_variable(:@version) if defined?(@version)
remove_instance_variable(:@path) if defined?(@path)
remove_instance_variable(:@git) if defined?(@git)
end

def last_revision_commit_of_file(repo, file, before_commit: nil)
@@ -45,12 +50,7 @@ def last_revision_commit_of_file(repo, file, before_commit: nil)
[before_commit.split("..").first]
end

out, = Open3.capture3(
HOMEBREW_SHIMS_PATH/"scm/git", "-C", repo,
"log", "--format=%h", "--abbrev=7", "--max-count=1",
*args, "--", file
)
out.chomp
Utils.popen_read(git, "-C", repo, "log", "--format=%h", "--abbrev=7", "--max-count=1", *args, "--", file).chomp
end

def last_revision_commit_of_files(repo, files, before_commit: nil)
@@ -66,24 +66,19 @@ def last_revision_commit_of_files(repo, files, before_commit: nil)
# <file_path2>
# ...
# return [<commit_hash>, [file_path1, file_path2, ...]]
out, = Open3.capture3(
HOMEBREW_SHIMS_PATH/"scm/git", "-C", repo, "log",
rev, *paths = Utils.popen_read(
git, "-C", repo, "log",
"--pretty=format:%h", "--abbrev=7", "--max-count=1",
"--diff-filter=d", "--name-only", *args, "--", *files
)
rev, *paths = out.chomp.split(/\n/).reject(&:empty?)
).lines.map(&:chomp).reject(&:empty?)
[rev, paths]
end

def last_revision_of_file(repo, file, before_commit: nil)
relative_file = Pathname(file).relative_path_from(repo)

commit_hash = last_revision_commit_of_file(repo, relative_file, before_commit: before_commit)
out, = Open3.capture3(
HOMEBREW_SHIMS_PATH/"scm/git", "-C", repo,
"show", "#{commit_hash}:#{relative_file}"
)
out
Utils.popen_read(git, "-C", repo, "show", "#{commit_hash}:#{relative_file}")
end

def ensure_installed!
@@ -121,8 +116,22 @@ def set_name_email!(author: true, committer: true)
end

def origin_branch(repo)
Utils.popen_read("git", "-C", repo, "symbolic-ref", "-q", "--short",
Utils.popen_read(git, "-C", repo, "symbolic-ref", "-q", "--short",
"refs/remotes/origin/HEAD").chomp.presence
end

# Special case of `git cherry-pick` that permits non-verbose output and
# optional resolution on merge conflict.
def cherry_pick!(repo, *args, resolve: false, verbose: false)
cmd = [git, "-C", repo, "cherry-pick"] + args
output = Utils.popen_read(*cmd, err: :out)
if $CHILD_STATUS.success?
puts output if verbose
output
else
system git, "-C", repo, "cherry-pick", "--abort" unless resolve
raise ErrorDuringExecution.new(cmd, status: $CHILD_STATUS, output: [[:stdout, output]])
end
end
end
end
34 changes: 33 additions & 1 deletion Library/Homebrew/utils/github.rb
Original file line number Diff line number Diff line change
@@ -175,7 +175,7 @@ def api_credentials_error_message(response_headers, needed_scopes)
end
end

def open_api(url, data: nil, request_method: nil, scopes: [].freeze, parse_json: true)
def open_api(url, data: nil, data_binary_path: nil, request_method: nil, scopes: [].freeze, parse_json: true)
# This is a no-op if the user is opting out of using the GitHub API.
return block_given? ? yield({}) : {} if Homebrew::EnvConfig.no_github_api?

@@ -200,6 +200,11 @@ def open_api(url, data: nil, request_method: nil, scopes: [].freeze, parse_json:
end
end

if data_binary_path.present?
args += ["--data-binary", "@#{data_binary_path}"]
args += ["--header", "Content-Type: application/gzip"]
end

headers_tmpfile = Tempfile.new("github_api_headers", HOMEBREW_TEMP)
begin
if data
@@ -468,6 +473,33 @@ def workflow_dispatch_event(user, repo, workflow, ref, **inputs)
scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES)
end

def get_release(user, repo, tag)
url = "#{API_URL}/repos/#{user}/#{repo}/releases/tags/#{tag}"
open_api(url, request_method: :GET)
end

def create_or_update_release(user, repo, tag, id: nil, name: nil, draft: false)
url = "#{API_URL}/repos/#{user}/#{repo}/releases"
method = if id
url += "/#{id}"
:PATCH
else
:POST
end
data = {
tag_name: tag,
name: name || tag,
draft: draft,
}
open_api(url, data: data, request_method: method, scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES)
end

def upload_release_asset(user, repo, id, local_file: nil, remote_file: nil)
url = "https://uploads.github.com/repos/#{user}/#{repo}/releases/#{id}/assets"
url += "?name=#{remote_file}" if remote_file
open_api(url, data_binary_path: local_file, request_method: :POST, scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES)
end

def get_artifact_url(user, repo, pr, workflow_id: "tests.yml", artifact_name: "bottles")
scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES
base_url = "#{API_URL}/repos/#{user}/#{repo}"
3 changes: 2 additions & 1 deletion Library/Homebrew/utils/inreplace.rb
Original file line number Diff line number Diff line change
@@ -28,6 +28,8 @@ def initialize(errors)
#
# @api public
def inreplace(paths, before = nil, after = nil, audit_result = true) # rubocop:disable Style/OptionalBooleanParameter
after = after.to_s if after.is_a? Symbol

errors = {}

errors["`paths` (first) parameter"] = ["`paths` was empty"] if paths.blank?
@@ -39,7 +41,6 @@ def inreplace(paths, before = nil, after = nil, audit_result = true) # rubocop:d
if before.nil? && after.nil?
yield s
else
after = after.to_s if after.is_a? Symbol
s.gsub!(before, after, audit_result)
end

20 changes: 12 additions & 8 deletions Library/Homebrew/utils/pypi.rb
Original file line number Diff line number Diff line change
@@ -12,15 +12,12 @@ module PyPI
AUTOMATIC_RESOURCE_UPDATE_BLOCKLIST = %w[
ansible
ansible@2.8
cdk8s
cloudformation-cli
diffoscope
dxpy
ipython
molecule
pulumi
salt
xonsh
].freeze
private_constant :AUTOMATIC_RESOURCE_UPDATE_BLOCKLIST

@@ -59,6 +56,7 @@ def get_pypi_info(package, version)
[json["info"]["name"], sdist["url"], sdist["digests"]["sha256"]]
end

# Return true if resources were checked (even if no change)
def update_python_resources!(formula, version = nil, print_only: false, silent: false,
ignore_non_pypi_packages: false)

@@ -67,11 +65,15 @@ def update_python_resources!(formula, version = nil, print_only: false, silent:
return
end

# PyPI package name isn't always the same as the formula name. Try to infer from the URL.
pypi_name = if formula.stable.url.start_with?(PYTHONHOSTED_URL_PREFIX)
url_to_pypi_package_name formula.stable.url
else
formula.name
pypi_name = url_to_pypi_package_name formula.stable.url

if pypi_name.nil?
return if ignore_non_pypi_packages

odie <<~EOS
Could not infer PyPI package name from URL:
#{Formatter.url(formula.stable.url)}
EOS
end

version ||= formula.version
@@ -159,5 +161,7 @@ def update_python_resources!(formula, version = nil, print_only: false, silent:
end
s.sub! inreplace_regex, new_resource_blocks
end

true
end
end
32 changes: 31 additions & 1 deletion Library/Homebrew/utils/tty.rb
Original file line number Diff line number Diff line change
@@ -4,8 +4,19 @@
#
# @api private
module Tty
@stream = $stdout

module_function

def with(stream)
previous_stream = @stream
@stream = stream

yield stream
ensure
@stream = previous_stream
end

def strip_ansi(string)
string.gsub(/\033\[\d+(;\d+)*m/, "")
end
@@ -42,6 +53,15 @@ def truncate(string)
no_underline: 24,
}.freeze

SPECIAL_CODES = {
up: "1A",
down: "1B",
right: "1C",
left: "1D",
erase_line: "K",
erase_char: "P",
}.freeze

CODES = COLOR_CODES.merge(STYLE_CODES).freeze

def append_to_escape_sequence(code)
@@ -66,6 +86,16 @@ def reset_escape_sequence!
end
end

SPECIAL_CODES.each do |name, code|
define_singleton_method(name) do
if @stream.tty?
"\033[#{code}"
else
""
end
end
end

def to_s
return "" unless color?

@@ -78,6 +108,6 @@ def color?
return false if Homebrew::EnvConfig.no_color?
return true if Homebrew::EnvConfig.color?

$stdout.tty?
@stream.tty?
end
end
16 changes: 8 additions & 8 deletions Library/Homebrew/vendor/bundle/bundler/setup.rb
Original file line number Diff line number Diff line change
@@ -48,10 +48,10 @@
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/method_source-1.0.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mustache-1.1.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.19.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.2.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.3.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.1.4/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.5895/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.5913/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parlour-4.0.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/patchelf-1.3.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib"
@@ -69,15 +69,15 @@
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-its-1.3.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-retry-0.6.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-wait-0.0.9/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-0.3.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-0.4.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.90.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.8.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.91.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.8.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.43.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.5898-universal-darwin-19/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.5898/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.5913-universal-darwin-19/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.5913/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/spoom-1.0.4/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tapioca-0.4.4/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tapioca-0.4.6/lib"
Original file line number Diff line number Diff line change
@@ -115,7 +115,7 @@ def keyword_loop?(type)

def node_within_enumerable_loop?(node, ancestor)
enumerable_loop?(ancestor) do |receiver|
receiver != node && !receiver.descendants.include?(node)
receiver != node && !receiver&.descendants&.include?(node)
end
end

Original file line number Diff line number Diff line change
@@ -3,8 +3,8 @@
module RuboCop
module Cop
module Performance
# This cop is used to identify usages of
# `select.first`, `select.last`, `find_all.first`, `find_all.last`, `filter.first`, and `filter.last`
# This cop is used to identify usages of `first`, `last`, `[0]` or `[-1]`
# chained to `select`, `find_all`, or `find_all`
# and change them to use `detect` instead.
#
# @example
@@ -15,6 +15,8 @@ module Performance
# [].find_all { |item| true }.last
# [].filter { |item| true }.first
# [].filter { |item| true }.last
# [].filter { |item| true }[0]
# [].filter { |item| true }[-1]
#
# # good
# [].detect { |item| true }
@@ -27,27 +29,40 @@ module Performance
class Detect < Base
extend AutoCorrector

CANDIDATE_METHODS = Set[:select, :find_all, :filter].freeze

MSG = 'Use `%<prefer>s` instead of ' \
'`%<first_method>s.%<second_method>s`.'
REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
'`%<first_method>s.%<second_method>s`.'
INDEX_MSG = 'Use `%<prefer>s` instead of ' \
'`%<first_method>s[%<index>i]`.'
INDEX_REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
'`%<first_method>s[%<index>i]`.'

def_node_matcher :detect_candidate?, <<~PATTERN
{
(send $(block (send _ {:select :find_all :filter}) ...) ${:first :last} $...)
(send $(send _ {:select :find_all :filter} ...) ${:first :last} $...)
(send $(block (send _ %CANDIDATE_METHODS) ...) ${:first :last} $...)
(send $(block (send _ %CANDIDATE_METHODS) ...) $:[] (int ${0 -1}))
(send $(send _ %CANDIDATE_METHODS ...) ${:first :last} $...)
(send $(send _ %CANDIDATE_METHODS ...) $:[] (int ${0 -1}))
}
PATTERN

def on_send(node)
detect_candidate?(node) do |receiver, second_method, args|
if second_method == :[]
index = args
args = {}
end

return unless args.empty?
return unless receiver

receiver, _args, body = *receiver if receiver.block_type?
return if accept_first_call?(receiver, body)

register_offense(node, receiver, second_method)
register_offense(node, receiver, second_method, index)
end
end

@@ -62,28 +77,31 @@ def accept_first_call?(receiver, body)
lazy?(caller)
end

def register_offense(node, receiver, second_method)
def register_offense(node, receiver, second_method, index)
_caller, first_method, _args = *receiver
range = receiver.loc.selector.join(node.loc.selector)

message = second_method == :last ? REVERSE_MSG : MSG
message = message_for_method(second_method, index)
formatted_message = format(message, prefer: preferred_method,
first_method: first_method,
second_method: second_method)
second_method: second_method,
index: index)

add_offense(range, message: formatted_message) do |corrector|
autocorrect(corrector, node)
autocorrect(corrector, node, replacement(second_method, index))
end
end

def autocorrect(corrector, node)
receiver, first_method = *node
def replacement(method, index)
if method == :last || method == :[] && index == -1
"reverse.#{preferred_method}"
else
preferred_method
end
end

replacement = if first_method == :last
"reverse.#{preferred_method}"
else
preferred_method
end
def autocorrect(corrector, node, replacement)
receiver, _first_method = *node

first_range = receiver.source_range.end.join(node.loc.selector)

@@ -93,6 +111,17 @@ def autocorrect(corrector, node)
corrector.replace(receiver.loc.selector, replacement)
end

def message_for_method(method, index)
case method
when :[]
index == -1 ? INDEX_REVERSE_MSG : INDEX_MSG
when :last
REVERSE_MSG
else
MSG
end
end

def preferred_method
config.for_cop('Style/CollectionMethods')['PreferredMethods']['detect'] || 'detect'
end
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ module Performance
# # bad
# [1, 2, 3].inject(:+)
# [1, 2, 3].reduce(10, :+)
# [1, 2, 3].inject(&:+)
# [1, 2, 3].reduce { |acc, elem| acc + elem }
#
# # good
@@ -24,7 +25,7 @@ class Sum < Base
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'

def_node_matcher :sum_candidate?, <<~PATTERN
(send _ ${:inject :reduce} $_init ? (sym :+))
(send _ ${:inject :reduce} $_init ? ${(sym :+) (block_pass (sym :+))})
PATTERN

def_node_matcher :sum_with_block_candidate?, <<~PATTERN
@@ -40,9 +41,9 @@ class Sum < Base
alias elem_plus_acc? acc_plus_elem?

def on_send(node)
sum_candidate?(node) do |method, init|
sum_candidate?(node) do |method, init, operation|
range = sum_method_range(node)
message = build_method_message(method, init)
message = build_method_message(method, init, operation)

add_offense(range, message: message) do |corrector|
autocorrect(corrector, init, range)
@@ -81,9 +82,9 @@ def sum_block_range(send, node)
range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
end

def build_method_message(method, init)
def build_method_message(method, init, operation)
good_method = build_good_method(init)
bad_method = build_method_bad_method(init, method)
bad_method = build_method_bad_method(init, method, operation)
format(MSG, good_method: good_method, bad_method: bad_method)
end

@@ -98,18 +99,22 @@ def build_good_method(init)

unless init.empty?
init = init.first
good_method += "(#{init.source})" if init.source.to_i != 0
good_method += "(#{init.source})" unless init.int_type? && init.value.zero?
end
good_method
end

def build_method_bad_method(init, method)
def build_method_bad_method(init, method, operation)
bad_method = "#{method}("
unless init.empty?
init = init.first
bad_method += "#{init.source}, "
end
bad_method += ':+)'
bad_method += if operation.block_pass_type?
'&:+)'
else
':+)'
end
bad_method
end

Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
module RuboCop
module Performance
module Version
STRING = '1.8.0'
STRING = '1.8.1'
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require 'ruby-progressbar/output'
require 'ruby-progressbar/outputs/tty'
require 'ruby-progressbar/outputs/non_tty'
require 'ruby-progressbar/timer'
require 'ruby-progressbar/progress'
require 'ruby-progressbar/throttle'
require 'ruby-progressbar/calculators/length'
require 'ruby-progressbar/calculators/running_average'
require 'ruby-progressbar/components'
require 'ruby-progressbar/format'
require 'ruby-progressbar/base'
require 'ruby-progressbar/refinements' if Module.
private_instance_methods.
include?(:using)

class ProgressBar
def self.create(*args)
ProgressBar::Base.new(*args)
end
end
Loading