diff --git a/.actrc b/.actrc deleted file mode 100644 index cd64307fd..000000000 --- a/.actrc +++ /dev/null @@ -1,8 +0,0 @@ ---action-offline-mode ---eventpath .github/event.json ---container-architecture linux/amd64 ---log-prefix-job-id ---platform macos-15=-self-hosted ---pull=false ---reuse ---secret-file .secrets diff --git a/.editorconfig b/.editorconfig index 1f913cdf8..653f5cbd0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,39 +1,27 @@ -# http://editorconfig.org +# https://editorconfig.org root = true [*] -indent_style = space -indent_size = 4 -end_of_line = lf charset = utf-8 -trim_trailing_whitespace = true +end_of_line = lf +indent_size = 4 +indent_style = space insert_final_newline = true +trim_trailing_whitespace = true -[script/*] -indent_size = 2 - -[*.{yml,yaml}] +[*.json] indent_size = 2 -# Use 2 spaces for Ruby files -[{Podfile,Rakefile,script/*,*.{podspec,rb,yml}}] -indent_size = 2 -indent_style = space -max_line_length = 80 +# Trailing spaces have meaning in Markdown +[*.md] +trim_trailing_whitespace = false -# Use tabs for property lists [*.plist] indent_style = tab -# JSON files contain newlines inconsistently -[*.json] +[*.yml] indent_size = 2 -insert_final_newline = ignore - -# Makefiles always use tabs for indentation -[Makefile] -indent_style = tab -# Trailing spaces have meaning in Markdown -[*.md] -trim_trailing_whitespace = false +[script/*] +indent_size = 2 +max_line_length = 80 diff --git a/.gitattributes b/.gitattributes index 0b591edf3..39e2514b6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ # Trailing spaces may be intentional in markdown documents, so these should not # be removed. -# https://gist.github.com/shaunlebron/746476e6e7a4d698b373 **/*.md whitespace=-blank-at-eol diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 254c41818..e2d80fc2c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,4 +1,4 @@ -# https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file --- version: 2 updates: diff --git a/.github/event.json b/.github/event.json deleted file mode 100644 index 85ba787b1..000000000 --- a/.github/event.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "inputs": { - "NAME": "Manual Workflow", - "SOME_VALUE": "ABC" - }, - "release": { - "name": "v1.8.6-beta.1: macOS only test build", - "tag_name": "v1.8.7-beta.1", - "target_commitish": "f8be3e9aaa6c78490277976f17041f2577f5dc21", - "body": "This is a pre-release to facilitate testing for the following fix:\n\n - ๐Ÿ–ฅ๏ธ Only search, outdated and update macOS apps (#505, #496, #491, #336)" - } -} \ No newline at end of file diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 451d38a20..6bfc533de 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,43 +1,32 @@ # # .github/workflows/build-test.yml # -# https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables --- name: Build, Test, and Lint - on: pull_request: branches: [main] push: branches: [main] - concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{github.workflow}}-${{github.ref}} cancel-in-progress: true - jobs: build-test: name: Build, Test, and Lint - - # https://github.com/actions/runner-images#available-images runs-on: macos-15 - defaults: run: - # Prefixes all `run` commands with the following command to force them to run outside Rosetta. - # https://github.com/actions/runner/issues/805#issuecomment-942784948 - # https://github.com/rolpdog/cffi-mirror/blob/release-1.15/.github/workflows/ci.yaml#L81-L141 - # https://github.com/actions/virtual-environments/issues/2187#issuecomment-790507204 - shell: arch -arm64 bash --noprofile --norc -eo pipefail {0} - + # Force all run commands to not use Rosetta 2 + shell: arch -arm64 /bin/zsh -Negku {0} steps: - uses: actions/checkout@v4 with: - # A fetch-depth of 0 includes all history and tags for script/version + # Include all history & tags for script/version fetch-depth: 0 - name: Bootstrap - run: script/bootstrap -f + run: script/bootstrap - name: Build run: script/build diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index f278c8df3..0eecad573 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -1,7 +1,6 @@ # # .github/workflows/danger.yml # -# https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables --- name: danger on: @@ -11,11 +10,12 @@ jobs: danger: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@v4 + - name: Danger - # https://github.com/orgs/danger/packages/container/package/danger-swift - uses: docker://ghcr.io/danger/danger-swift:3.18.0 + uses: docker://ghcr.io/danger/danger-swift:3.20.2 with: args: --failOnErrors --no-publish-check env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/release-published.yml b/.github/workflows/release-published.yml new file mode 100644 index 000000000..807f0bb7c --- /dev/null +++ b/.github/workflows/release-published.yml @@ -0,0 +1,39 @@ +# +# .github/workflows/release-published.yml +# +--- +name: release-published +on: + release: + types: [published] +defaults: + run: + # Force all run commands to not use Rosetta 2 + shell: arch -arm64 /bin/zsh -Negku {0} +jobs: + release-published: + if: ${{!github.event.repository.fork}} + runs-on: macos-15 + steps: + - name: ๐Ÿšฐ Apply pr-pull label to custom tap formula bump PR + env: + GH_TOKEN: ${{secrets.HOMEBREW_GITHUB_API_TOKEN}} + run: | + gh release -R "${GITHUB_REPOSITORY}" download "${GITHUB_REF_NAME}" -p bump.url + gh pr edit "$(>"$GITHUB_OUTPUT" - - - id: mas_version - run: | - echo "MAS_VERSION=${{ github.event.release.tag_name }}" >>"$GITHUB_OUTPUT" - - - id: pre_release - run: | - echo "PRE_RELEASE=$(grep -q '-' <<<$MAS_VERSION && echo 'true' || echo 'false')" >>"$GITHUB_OUTPUT" - - - id: release_branch - run: | - echo "RELEASE_BRANCH=releases/release-${{ github.event.release.tag_name }}" >>"$GITHUB_OUTPUT" - - prepare-release: - runs-on: macos-15 - needs: [start] - steps: - - uses: actions/checkout@v4 - with: - # A fetch-depth of 0 includes all history and tags for script/version - fetch-depth: 0 - - - name: ๐Ÿ‘ข Bootstrap - run: | - script/bootstrap -f - - - name: ๐Ÿ”€ Create mas release branch - env: - RELEASE_BRANCH: ${{ needs.start.outputs.release_branch }} - run: | - git branch "${RELEASE_BRANCH}" - git switch "${RELEASE_BRANCH}" - - - name: ๐Ÿ”– Update version - env: - MAS_VERSION: ${{ needs.start.outputs.mas_version }} - run: | - script/version_bump "${MAS_VERSION}" - - - name: ๐Ÿ”ง Configure Git Author - run: | - git config --global user.name 'masclibot' - git config --global user.email 'masclibot@users.noreply.github.com' - - - name: ๐Ÿ’พ Commit changes - env: - MAS_VERSION: ${{ needs.start.outputs.mas_version }} - RELEASE_BRANCH: ${{ needs.start.outputs.release_branch }} - run: | - git add \ - "Homebrew/mas.rb" \ - "Homebrew/mas-tap.rb" \ - "Package.swift" - git commit \ - --message="๐Ÿ”– Version ${MAS_VERSION}" - git push \ - --set-upstream origin "${RELEASE_BRANCH}" - - pkg-installer: - runs-on: macos-15 - needs: [start, prepare-release] - steps: - - uses: actions/checkout@v4 - with: - # A fetch-depth of 0 includes all history and tags for script/version - fetch-depth: 0 - ref: ${{ needs.start.outputs.release_branch }} - - - name: ๐Ÿ‘ข Bootstrap - run: | - script/bootstrap -f - - # Important to trigger a universal build first as package just works with - # the `mas` binary in finds in the build dir. - - name: ๐Ÿ—๏ธ Build Universal - run: | - script/build --universal - - - name: ๐Ÿ“ฆ macOS Package - run: | - script/package - - - name: ๐Ÿš€ Upload mas.pkg - env: - GH_TOKEN: ${{ github.token }} - DRY_RUN: ${{ needs.start.outputs.dry_run }} - MAS_VERSION: ${{ needs.start.outputs.mas_version }} - if: ${{ needs.start.outputs.dry_run == 'false' }} - run: | - gh release upload ${MAS_VERSION} \ - .build/mas.pkg - - homebrew-tap: - runs-on: macos-15 - needs: [start, prepare-release] - steps: - - name: ๐Ÿ“บ Checkout mas repo - uses: actions/checkout@v4 - with: - # A fetch-depth of 0 includes all history and tags for script/version - fetch-depth: 0 - ref: ${{ needs.start.outputs.release_branch }} - - - name: ๐Ÿ‘ข Bootstrap - run: | - script/bootstrap -f - - # The mas-cli/homebrew-tap repo needs to be checked out using the current - # GitHub credentials in order to open a PR. However, the `brew tap` command - # must be run for Homebrew to see the dir as a tap. - # This is necessary to avoid the following error: - # Error: No available formula or cask with the name "mas-cli/tap/mas". - - name: ๐Ÿšฐ Checkout mas tap - run: | - rm -rf /opt/homebrew/Library/Taps - mkdir Taps - ln -s $(realpath Taps) /opt/homebrew/Library/Taps - ls -l /opt/homebrew/Library/Taps - brew tap mas-cli/tap - brew tap - - # Checkout with a token for write access - - name: ๐Ÿšฐ Re-clone mas tap - uses: actions/checkout@v4 - with: - repository: mas-cli/homebrew-tap - token: ${{ secrets.DEPLOY_TOKEN }} - # brew --repository mas-cli/tap - path: Taps/mas-cli/homebrew-tap - - - name: ๐Ÿ”ง Configure Git Author - run: | - git config --global user.name 'masclibot' - git config --global user.email 'masclibot@users.noreply.github.com' - - - name: โคด๏ธ Open mas tap PR - env: - GITHUB_TOKEN: ${{ secrets.DEPLOY_TOKEN }} - DRY_RUN: ${{ needs.start.outputs.dry_run }} - RELEASE_BRANCH: ${{ needs.start.outputs.release_branch }} - MAS_VERSION: ${{ needs.start.outputs.mas_version }} - working-directory: /opt/homebrew/Library/Taps/mas-cli/homebrew-tap - run: | - git branch "${RELEASE_BRANCH}" - git switch "${RELEASE_BRANCH}" - - cp -v \ - ${GITHUB_WORKSPACE}/Homebrew/mas-tap.rb \ - Formula/mas.rb - - git add Formula/mas.rb - git commit --message="๐Ÿ”– Version ${MAS_VERSION}" - - git push \ - --set-upstream origin "${RELEASE_BRANCH}" - - gh pr create \ - --assignee phatblat \ - --base main \ - --head "${RELEASE_BRANCH}" \ - --title "๐Ÿ”– Version ${MAS_VERSION}" \ - --body "This PR contains the changes from releasing version \ - [${MAS_VERSION}](https://github.com/mas-cli/mas/releases/tag/${MAS_VERSION})." - - - name: ๐Ÿšฐ Update mas tap formula - env: - GH_TOKEN: ${{ github.token }} - DRY_RUN: ${{ needs.start.outputs.dry_run }} - MAS_VERSION: ${{ needs.start.outputs.mas_version }} - run: | - DRY_RUN=${DRY_RUN} \ - script/brew_tap_update ${MAS_VERSION} - - - name: ๐Ÿš€ Upload Bottles - env: - GH_TOKEN: ${{ github.token }} - DRY_RUN: ${{ needs.start.outputs.dry_run }} - MAS_VERSION: ${{ needs.start.outputs.mas_version }} - if: ${{ needs.start.outputs.dry_run == 'false' }} - run: | - gh release upload ${MAS_VERSION} \ - .build/bottles/mas-*.bottle.tar.gz - - homebrew-core: - runs-on: macos-15 - needs: [start, prepare-release, homebrew-tap] - env: - PRE_RELEASE: ${{ needs.start.outputs.pre_release }} - steps: - - uses: actions/checkout@v4 - if: env.PRE_RELEASE == 'false' - with: - # A fetch-depth of 0 includes all history and tags for script/version - fetch-depth: 0 - ref: ${{ needs.start.outputs.release_branch }} - - - name: ๐Ÿ‘ข Bootstrap - if: env.PRE_RELEASE == 'false' - run: | - script/bootstrap -f - - - name: ๐Ÿ”ง Configure Git Author - if: env.PRE_RELEASE == 'false' - run: | - git config --global user.name 'masclibot' - git config --global user.email 'masclibot@users.noreply.github.com' - - - name: ๐Ÿบ Update Homebrew mas formula - env: - GH_TOKEN: ${{ github.token }} - HOMEBREW_GITHUB_API_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }} - DRY_RUN: ${{ needs.start.outputs.dry_run }} - MAS_VERSION: ${{ needs.start.outputs.mas_version }} - if: env.PRE_RELEASE == 'false' - run: | - DRY_RUN=${DRY_RUN} \ - script/brew_core_update ${MAS_VERSION} diff --git a/.github/workflows/tag-pushed.yml b/.github/workflows/tag-pushed.yml new file mode 100644 index 000000000..d67640ace --- /dev/null +++ b/.github/workflows/tag-pushed.yml @@ -0,0 +1,94 @@ +# +# .github/workflows/tag-pushed.yml +# +--- +name: tag-pushed +on: + push: + tags: ["**"] +defaults: + run: + # Force all run commands to not use Rosetta 2 + shell: arch -arm64 /bin/zsh -Negku {0} +jobs: + tag-pushed: + if: ${{!github.event.repository.fork}} + runs-on: macos-15 + permissions: + contents: write + steps: + - name: ๐Ÿ›’ Checkout repo + env: + GIT_CONFIG_COUNT: 1 + GIT_CONFIG_KEY_0: init.defaultBranch + GIT_CONFIG_VALUE_0: ${{github.event.repository.default_branch}} + uses: actions/checkout@v4 + + - name: ๐Ÿ–‹ Delete tag lacking valid signature + run: | + git fetch --force origin "${GITHUB_REF}:${GITHUB_REF}" + if [[\ + "$(git cat-file tag "${GITHUB_REF_NAME}")" != *'-----BEGIN SSH SIGNATURE-----'*'-----END SSH SIGNATURE-----'\ + ]]; then + printf $'Error: Deleting tag %s because it does not have a valid signature\n' "${GITHUB_REF_NAME}" >&2 + git push -d origin "${GITHUB_REF_NAME}" + exit 1 + fi + + - name: ๐Ÿท Exit if not a version tag + run: | + if [[ ! "${GITHUB_REF_NAME}" =~ '^v[[:digit:]]+(\.[[:digit:]]+)*(-(alpha|beta|rc)\.[[:digit:]]+)?$' ]]; then + printf $'Exiting because %s is not a version tag\n' "${GITHUB_REF_NAME}" + exit 2 + fi + + - name: ๐ŸŒณ Delete version tag not on main + env: + DEFAULT_BRANCH_NAME: ${{github.event.repository.default_branch}} + run: | + git fetch --force origin "${DEFAULT_BRANCH_NAME}:${DEFAULT_BRANCH_NAME}" + if ! git merge-base --is-ancestor "${GITHUB_REF_NAME}" "${DEFAULT_BRANCH_NAME}"; then + printf $'Error: Deleting version tag %s because it is not on the %s branch\n' "${GITHUB_REF_NAME}"\ + "${DEFAULT_BRANCH_NAME}" >&2 + git push -d origin "${GITHUB_REF_NAME}" + exit 3 + fi + + - name: ๐Ÿ“ฆ Build universal executable & package it in an installer + run: | + script/package + + - name: ๐Ÿšฐ Bump custom tap formula + env: + HOMEBREW_GITHUB_API_TOKEN: ${{secrets.HOMEBREW_GITHUB_API_TOKEN}} + run: | + brew tap "${GITHUB_REPOSITORY_OWNER}/tap" + unsetopt errexit + bump_output="$(brew bump-formula-pr\ + --tag "${GITHUB_REF_NAME}"\ + --revision "${GITHUB_SHA}"\ + --no-fork\ + --no-browse\ + --online\ + --strict\ + --verbose\ + "${GITHUB_REPOSITORY_OWNER}/tap/mas"\ + 2>&1)" + exit_code="${?}" + setopt errexit + printf %s "${bump_output}" + printf %s "${${(f)bump_output}[-1]}" > .build/bump.url + exit "${exit_code}" + + - name: ๐Ÿ“ Create draft release + env: + GH_TOKEN: ${{github.token}} + run: | + gh release create\ + "${GITHUB_REF_NAME}"\ + ".build/mas-${GITHUB_REF_NAME#v}.pkg"\ + .build/bump.url\ + -d\ + -t "${GITHUB_REF_NAME}: ${$(git tag -l "${GITHUB_REF_NAME}" --format='%(contents)')%%$'\n'*}"\ + --generate-notes\ + ${"${GITHUB_REF_NAME//[^-]/}":+ -p} diff --git a/.gitignore b/.gitignore index 2b6a070d7..820092c4b 100644 --- a/.gitignore +++ b/.gitignore @@ -34,7 +34,6 @@ Carthage/ DerivedData Pods/ Sources/mas/Package.swift -Sources/MasKit/Package.swift Temporary Items bin/ build/ diff --git a/.hound.yml b/.hound.yml index 79acba67b..c6167cf74 100644 --- a/.hound.yml +++ b/.hound.yml @@ -2,7 +2,7 @@ # .hound.yml # mas # -# http://help.houndci.com/configuration/swiftlint +# http://help.houndci.com/en/articles/2138528-swiftlint # --- fail_on_violations: false diff --git a/.mise.toml b/.mise.toml deleted file mode 100644 index c0c7b45af..000000000 --- a/.mise.toml +++ /dev/null @@ -1,11 +0,0 @@ -# -# .mise.toml -# https://mise.jdx.dev/configuration.html -# - -[tools] -act = "0.2.60" -"npm:prettier" = "3.2.5" - -[settings] -experimental = true diff --git a/.swiftlint.yml b/.swiftlint.yml index 10d31447b..da0b88578 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -36,10 +36,11 @@ disabled_rules: - unused_capture_list - vertical_whitespace_between_cases file_types_order: - order: [ - [main_type], - [supporting_type], - [extension], - [preview_provider], - [library_content_provider] - ] + order: + [ + [main_type], + [supporting_type], + [extension], + [preview_provider], + [library_content_provider], + ] diff --git a/.yamllint.yml b/.yamllint.yml index bf64f88ce..d7927e407 100644 --- a/.yamllint.yml +++ b/.yamllint.yml @@ -13,5 +13,5 @@ rules: truthy: allowed-values: ["true", "false"] check-keys: false - # Disables fallse positives on GHA workflow `on:` + # Disable false positives on GHA workflow `on:` level: warning diff --git a/Brewfile b/Brewfile index f39a5c1ab..a664c4421 100644 --- a/Brewfile +++ b/Brewfile @@ -1,14 +1,11 @@ brew "markdownlint-cli" -brew "mise" -brew "sd" +brew "prettier" brew "shellcheck" -brew "shfmt" -brew "swift-format" brew "swiftformat" -brew "trash" brew "yamllint" if OS.mac? && MacOS.version >= :ventura + brew "swift-format" brew "swiftlint" tap "peripheryapp/periphery" cask "periphery" diff --git a/Brewfile.lock.json b/Brewfile.lock.json deleted file mode 100644 index 2f0d39161..000000000 --- a/Brewfile.lock.json +++ /dev/null @@ -1,419 +0,0 @@ -{ - "entries": { - "brew": { - "markdownlint-cli": { - "version": "0.42.0", - "bottle": { - "rebuild": 0, - "root_url": "https://ghcr.io/v2/homebrew/core", - "files": { - "arm64_sequoia": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/markdownlint-cli/blobs/sha256:a3e5181a75b8fb131ac22c9c63635573d403a3d720ef0c72bd58cecfb3c2fe3e", - "sha256": "a3e5181a75b8fb131ac22c9c63635573d403a3d720ef0c72bd58cecfb3c2fe3e" - }, - "arm64_sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/markdownlint-cli/blobs/sha256:a3e5181a75b8fb131ac22c9c63635573d403a3d720ef0c72bd58cecfb3c2fe3e", - "sha256": "a3e5181a75b8fb131ac22c9c63635573d403a3d720ef0c72bd58cecfb3c2fe3e" - }, - "arm64_ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/markdownlint-cli/blobs/sha256:a3e5181a75b8fb131ac22c9c63635573d403a3d720ef0c72bd58cecfb3c2fe3e", - "sha256": "a3e5181a75b8fb131ac22c9c63635573d403a3d720ef0c72bd58cecfb3c2fe3e" - }, - "sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/markdownlint-cli/blobs/sha256:758ba29dba62e69b33801d519cbf6186a84320adf3e8e08bda862c9b057c22e5", - "sha256": "758ba29dba62e69b33801d519cbf6186a84320adf3e8e08bda862c9b057c22e5" - }, - "ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/markdownlint-cli/blobs/sha256:758ba29dba62e69b33801d519cbf6186a84320adf3e8e08bda862c9b057c22e5", - "sha256": "758ba29dba62e69b33801d519cbf6186a84320adf3e8e08bda862c9b057c22e5" - }, - "x86_64_linux": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/markdownlint-cli/blobs/sha256:a3e5181a75b8fb131ac22c9c63635573d403a3d720ef0c72bd58cecfb3c2fe3e", - "sha256": "a3e5181a75b8fb131ac22c9c63635573d403a3d720ef0c72bd58cecfb3c2fe3e" - } - } - } - }, - "mise": { - "version": "2024.10.11", - "bottle": { - "rebuild": 0, - "root_url": "https://ghcr.io/v2/homebrew/core", - "files": { - "arm64_sequoia": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/mise/blobs/sha256:3d1ce9664736b5039466ceeb8286f87150a220d76cf62e5c5538ed4c42c01ff0", - "sha256": "3d1ce9664736b5039466ceeb8286f87150a220d76cf62e5c5538ed4c42c01ff0" - }, - "arm64_sonoma": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/mise/blobs/sha256:d28afbc2017aa2d5904da9ca14e1fc9d01d341bfd0adc5168ace961e326b5b1c", - "sha256": "d28afbc2017aa2d5904da9ca14e1fc9d01d341bfd0adc5168ace961e326b5b1c" - }, - "arm64_ventura": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/mise/blobs/sha256:c4005d63d073861cef944841aa88925b1b929bc150d94bebe65322a4c7a6886f", - "sha256": "c4005d63d073861cef944841aa88925b1b929bc150d94bebe65322a4c7a6886f" - }, - "sonoma": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/mise/blobs/sha256:d392eae34949295556f9c3598ce97bf44f5392b996b02ea31956169332a41f1c", - "sha256": "d392eae34949295556f9c3598ce97bf44f5392b996b02ea31956169332a41f1c" - }, - "ventura": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/mise/blobs/sha256:fd1afe999715d971c78f4bfa90b74fae7b7f8688477b07ea89c67ee36ea8463a", - "sha256": "fd1afe999715d971c78f4bfa90b74fae7b7f8688477b07ea89c67ee36ea8463a" - }, - "x86_64_linux": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/mise/blobs/sha256:22601cf4faf8764cf29d6cea72ef0e0789b10da581d899a229aace4e0069b2c4", - "sha256": "22601cf4faf8764cf29d6cea72ef0e0789b10da581d899a229aace4e0069b2c4" - } - } - } - }, - "sd": { - "version": "1.0.0", - "bottle": { - "rebuild": 0, - "root_url": "https://ghcr.io/v2/homebrew/core", - "files": { - "arm64_sequoia": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/sd/blobs/sha256:3cf7ab4495f622a4f245bb1c7c30225ef881dc390ee5edc59a1d3c4381cecca1", - "sha256": "3cf7ab4495f622a4f245bb1c7c30225ef881dc390ee5edc59a1d3c4381cecca1" - }, - "arm64_sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/sd/blobs/sha256:6bc773a70934364157591cd888e617601a42ed1f615fda8f77364fa45631d08d", - "sha256": "6bc773a70934364157591cd888e617601a42ed1f615fda8f77364fa45631d08d" - }, - "arm64_ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/sd/blobs/sha256:946a44f567e3528d380fbbee742c3abeed9952f53f7de172a846b63d2e21d5b1", - "sha256": "946a44f567e3528d380fbbee742c3abeed9952f53f7de172a846b63d2e21d5b1" - }, - "arm64_monterey": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/sd/blobs/sha256:60f079d38aa238a1e7109c6a0f988fe7033449d20f05db3b87219cbfd945fe58", - "sha256": "60f079d38aa238a1e7109c6a0f988fe7033449d20f05db3b87219cbfd945fe58" - }, - "sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/sd/blobs/sha256:f83ebe2505106e8c94c4b92d15c0ac3390dc637039043dbafad3e382fa8c61b0", - "sha256": "f83ebe2505106e8c94c4b92d15c0ac3390dc637039043dbafad3e382fa8c61b0" - }, - "ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/sd/blobs/sha256:0200b81c386198d39ed7b03e85c771e141d9604075d82aa4caed5d5a775486c8", - "sha256": "0200b81c386198d39ed7b03e85c771e141d9604075d82aa4caed5d5a775486c8" - }, - "monterey": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/sd/blobs/sha256:a8fee9e7b0202a27d8dcc599ebd391637107134f139dbe88d6b22c880e63d8a1", - "sha256": "a8fee9e7b0202a27d8dcc599ebd391637107134f139dbe88d6b22c880e63d8a1" - }, - "x86_64_linux": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/sd/blobs/sha256:4c098bdfaff013f7a6b6b96a65b9cfef86926e1cd901b363e1bdb84734ee6e3f", - "sha256": "4c098bdfaff013f7a6b6b96a65b9cfef86926e1cd901b363e1bdb84734ee6e3f" - } - } - } - }, - "shellcheck": { - "version": "0.10.0", - "bottle": { - "rebuild": 0, - "root_url": "https://ghcr.io/v2/homebrew/core", - "files": { - "arm64_sequoia": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shellcheck/blobs/sha256:5045be1e530288251353848343322f5a423617d061830b7ea7465fe550787364", - "sha256": "5045be1e530288251353848343322f5a423617d061830b7ea7465fe550787364" - }, - "arm64_sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shellcheck/blobs/sha256:ef742b6992cfcdcd7289718ac64b27174e421d29ce3ad9b81e1856349059b117", - "sha256": "ef742b6992cfcdcd7289718ac64b27174e421d29ce3ad9b81e1856349059b117" - }, - "arm64_ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shellcheck/blobs/sha256:6e60ee03edb09ac5bc852b8eb813849fa654400e21ffb4c746989678172f5a26", - "sha256": "6e60ee03edb09ac5bc852b8eb813849fa654400e21ffb4c746989678172f5a26" - }, - "arm64_monterey": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shellcheck/blobs/sha256:d5e8407806dbf757e71930ce2cb9b0d23bae286f0c058d9ff246d851dd7aa871", - "sha256": "d5e8407806dbf757e71930ce2cb9b0d23bae286f0c058d9ff246d851dd7aa871" - }, - "sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shellcheck/blobs/sha256:b53cf1e5464406ee49743fc2db84850b6d34d3a2098cf729e629b23f9d6dd6e0", - "sha256": "b53cf1e5464406ee49743fc2db84850b6d34d3a2098cf729e629b23f9d6dd6e0" - }, - "ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shellcheck/blobs/sha256:15ba88c48a5ae3b08e085791e3c5e514d9d78ce88414c96bd21ed33f29fb4aca", - "sha256": "15ba88c48a5ae3b08e085791e3c5e514d9d78ce88414c96bd21ed33f29fb4aca" - }, - "monterey": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shellcheck/blobs/sha256:b3d14cb62e325d0f7221cd24a7fb4533936feae4ed4dce00e8983ec6e55123f8", - "sha256": "b3d14cb62e325d0f7221cd24a7fb4533936feae4ed4dce00e8983ec6e55123f8" - }, - "x86_64_linux": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shellcheck/blobs/sha256:6d0867f144686a5caa025cb15ecac49286654b78e7b89979a54eedc9a0cc9b6b", - "sha256": "6d0867f144686a5caa025cb15ecac49286654b78e7b89979a54eedc9a0cc9b6b" - } - } - } - }, - "shfmt": { - "version": "3.10.0", - "bottle": { - "rebuild": 0, - "root_url": "https://ghcr.io/v2/homebrew/core", - "files": { - "arm64_sequoia": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shfmt/blobs/sha256:88d60bca61406671618ecf94f2d81104882f9dd8db838a70d0c2cd6c0fa46863", - "sha256": "88d60bca61406671618ecf94f2d81104882f9dd8db838a70d0c2cd6c0fa46863" - }, - "arm64_sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shfmt/blobs/sha256:88d60bca61406671618ecf94f2d81104882f9dd8db838a70d0c2cd6c0fa46863", - "sha256": "88d60bca61406671618ecf94f2d81104882f9dd8db838a70d0c2cd6c0fa46863" - }, - "arm64_ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shfmt/blobs/sha256:88d60bca61406671618ecf94f2d81104882f9dd8db838a70d0c2cd6c0fa46863", - "sha256": "88d60bca61406671618ecf94f2d81104882f9dd8db838a70d0c2cd6c0fa46863" - }, - "sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shfmt/blobs/sha256:788b7ecff02bbff7fa1563a4937999972799361b4a0c49b1ed8545983d6ff989", - "sha256": "788b7ecff02bbff7fa1563a4937999972799361b4a0c49b1ed8545983d6ff989" - }, - "ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shfmt/blobs/sha256:788b7ecff02bbff7fa1563a4937999972799361b4a0c49b1ed8545983d6ff989", - "sha256": "788b7ecff02bbff7fa1563a4937999972799361b4a0c49b1ed8545983d6ff989" - }, - "x86_64_linux": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/shfmt/blobs/sha256:0b15af30edec238edf607c38a95bd45249cdd6f48f30ab33bdd0a9c2ae2da956", - "sha256": "0b15af30edec238edf607c38a95bd45249cdd6f48f30ab33bdd0a9c2ae2da956" - } - } - } - }, - "swift-format": { - "version": "510.1.0", - "bottle": { - "rebuild": 0, - "root_url": "https://ghcr.io/v2/homebrew/core", - "files": { - "arm64_sequoia": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swift-format/blobs/sha256:4bee0106201ba2a3036576610e61832b97fb65292c194f52fc15d62e1bdb2243", - "sha256": "4bee0106201ba2a3036576610e61832b97fb65292c194f52fc15d62e1bdb2243" - }, - "arm64_sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swift-format/blobs/sha256:ac50e5269ecc0bffb70a6c5077f97954e2e51c9158a3bfa36b86d89f9d6c5e43", - "sha256": "ac50e5269ecc0bffb70a6c5077f97954e2e51c9158a3bfa36b86d89f9d6c5e43" - }, - "arm64_ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swift-format/blobs/sha256:7fb047e8f80a72e5d8d7ae50c496d0cf59dd3ab654ce6048e4b7fa7b85afe69a", - "sha256": "7fb047e8f80a72e5d8d7ae50c496d0cf59dd3ab654ce6048e4b7fa7b85afe69a" - }, - "sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swift-format/blobs/sha256:a99a19c9fc177a57b2577e3c1b30feb70f13388fc9c4e4ea7968f783058e09a0", - "sha256": "a99a19c9fc177a57b2577e3c1b30feb70f13388fc9c4e4ea7968f783058e09a0" - }, - "ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swift-format/blobs/sha256:a652f68cc4bed9c3186b66c8ee68e79b7387d37943aaff0a0c2d4197367b73fe", - "sha256": "a652f68cc4bed9c3186b66c8ee68e79b7387d37943aaff0a0c2d4197367b73fe" - }, - "x86_64_linux": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swift-format/blobs/sha256:b1949fcb7f1b943fa5b0216bc6f18e12dc369c0538b093786332f851f22b0b03", - "sha256": "b1949fcb7f1b943fa5b0216bc6f18e12dc369c0538b093786332f851f22b0b03" - } - } - } - }, - "swiftformat": { - "version": "0.54.6_1", - "bottle": { - "rebuild": 0, - "root_url": "https://ghcr.io/v2/homebrew/core", - "files": { - "arm64_sequoia": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:03eb08eb7de0e697e574b5d5c94104a88c9548ee880b942f1916536fe7ff897a", - "sha256": "03eb08eb7de0e697e574b5d5c94104a88c9548ee880b942f1916536fe7ff897a" - }, - "arm64_sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:0ff9c3c154fea61303bd060da1aecebb025a3a33460b24910cf55e6ae366574e", - "sha256": "0ff9c3c154fea61303bd060da1aecebb025a3a33460b24910cf55e6ae366574e" - }, - "arm64_ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:52200577da57cebd27e7d4b6a9ed84f6d3475b7f91e28ec4f5947fc2992cd943", - "sha256": "52200577da57cebd27e7d4b6a9ed84f6d3475b7f91e28ec4f5947fc2992cd943" - }, - "sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:9f79e28a0a5c7172be8bfcf23fca47de08f8bc03a3ddcdfbf52704445b9d8b18", - "sha256": "9f79e28a0a5c7172be8bfcf23fca47de08f8bc03a3ddcdfbf52704445b9d8b18" - }, - "ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:416528899d45dc25edc2f14c857239a2c922b4be548345423857f140c6b90f0f", - "sha256": "416528899d45dc25edc2f14c857239a2c922b4be548345423857f140c6b90f0f" - }, - "x86_64_linux": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:86c47e1a74da98ff5646c8d510ea5e6de45e9dc97bc59f151bd2a8848b5bc9f8", - "sha256": "86c47e1a74da98ff5646c8d510ea5e6de45e9dc97bc59f151bd2a8848b5bc9f8" - } - } - } - }, - "trash": { - "version": "0.9.2", - "bottle": { - "rebuild": 1, - "root_url": "https://ghcr.io/v2/homebrew/core", - "files": { - "arm64_sequoia": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:f3b7a766bcc683b339c145ab7d8b484f2bbd65aac6903fd952dec7f4521efe5f", - "sha256": "f3b7a766bcc683b339c145ab7d8b484f2bbd65aac6903fd952dec7f4521efe5f" - }, - "arm64_sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:90cffd3d151720b768c48a8874f7b8dfaaf6f7a9e9000ffe23cfa3f9e4aa6b76", - "sha256": "90cffd3d151720b768c48a8874f7b8dfaaf6f7a9e9000ffe23cfa3f9e4aa6b76" - }, - "arm64_ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:60186a8823abc9dd734475e3f787edd7c2d6a2254fff25b7289de2db15447099", - "sha256": "60186a8823abc9dd734475e3f787edd7c2d6a2254fff25b7289de2db15447099" - }, - "arm64_monterey": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:541af91d1cb128aa743460a529a3dcab5bac63b61ccde0a60d73aee23ab7d5c0", - "sha256": "541af91d1cb128aa743460a529a3dcab5bac63b61ccde0a60d73aee23ab7d5c0" - }, - "arm64_big_sur": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:11c0c85ec692ea6d4a125070f0a6ca576aff991608a6c9632b984cbf983e2481", - "sha256": "11c0c85ec692ea6d4a125070f0a6ca576aff991608a6c9632b984cbf983e2481" - }, - "sonoma": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:c26e06202022f708790f22f4477b65e3337d611c42e9a814ada1526bda03d923", - "sha256": "c26e06202022f708790f22f4477b65e3337d611c42e9a814ada1526bda03d923" - }, - "ventura": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:539093ca74c72ed8be974fd9042b14f55cde0ef2c1fadbedc7343099a394593e", - "sha256": "539093ca74c72ed8be974fd9042b14f55cde0ef2c1fadbedc7343099a394593e" - }, - "monterey": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:09b8ac7ade28ca59bd578b90680ece838a507b90b35e44d06a16f4d8ab9ae6e6", - "sha256": "09b8ac7ade28ca59bd578b90680ece838a507b90b35e44d06a16f4d8ab9ae6e6" - }, - "big_sur": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:403ba52ce97d38535e1d127ca227afd4ea2d0e0c8b414118dbc5376c9ed8f094", - "sha256": "403ba52ce97d38535e1d127ca227afd4ea2d0e0c8b414118dbc5376c9ed8f094" - }, - "catalina": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:b452d67cdeeb52db0aaadd258bc3e214a5ea5ed37da698b45017b01457115ea6", - "sha256": "b452d67cdeeb52db0aaadd258bc3e214a5ea5ed37da698b45017b01457115ea6" - }, - "mojave": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:d8ad5460b24a51a4a12b31ebf1a2887e9e86e029d061f6994c3c1caea7bf0551", - "sha256": "d8ad5460b24a51a4a12b31ebf1a2887e9e86e029d061f6994c3c1caea7bf0551" - }, - "high_sierra": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/trash/blobs/sha256:0ef5ea924ba8d01398686657a839ad270796f3f10eee86d6522980d32038df9a", - "sha256": "0ef5ea924ba8d01398686657a839ad270796f3f10eee86d6522980d32038df9a" - } - } - } - }, - "yamllint": { - "version": "1.35.1", - "bottle": { - "rebuild": 2, - "root_url": "https://ghcr.io/v2/homebrew/core", - "files": { - "arm64_sequoia": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/yamllint/blobs/sha256:cb74d6cc51501733531acd25b26fd474557d19374b98eb7de16271ff2c257860", - "sha256": "cb74d6cc51501733531acd25b26fd474557d19374b98eb7de16271ff2c257860" - }, - "arm64_sonoma": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/yamllint/blobs/sha256:e36b43d6b87028fe2005878cb15c78edec6ddb898e9a86ff7b901fe093cf9c0e", - "sha256": "e36b43d6b87028fe2005878cb15c78edec6ddb898e9a86ff7b901fe093cf9c0e" - }, - "arm64_ventura": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/yamllint/blobs/sha256:3591f98aaaebba5e9360926f5ca756dbd85c6a46de0554042376ac83548c7fb3", - "sha256": "3591f98aaaebba5e9360926f5ca756dbd85c6a46de0554042376ac83548c7fb3" - }, - "sonoma": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/yamllint/blobs/sha256:3889369233f5f342b73cc70625748a52d72117603b92f352af00a9ebd27cb1c4", - "sha256": "3889369233f5f342b73cc70625748a52d72117603b92f352af00a9ebd27cb1c4" - }, - "ventura": { - "cellar": ":any", - "url": "https://ghcr.io/v2/homebrew/core/yamllint/blobs/sha256:209883378df0edf4a0691fd2dbf6f2e8da7776bd9c0de0fc70fa04dd0fc51c8d", - "sha256": "209883378df0edf4a0691fd2dbf6f2e8da7776bd9c0de0fc70fa04dd0fc51c8d" - }, - "x86_64_linux": { - "cellar": ":any_skip_relocation", - "url": "https://ghcr.io/v2/homebrew/core/yamllint/blobs/sha256:993514320174f1147d538719552131a73d34cf66dc9f82c38f6ed28b16cea287", - "sha256": "993514320174f1147d538719552131a73d34cf66dc9f82c38f6ed28b16cea287" - } - } - } - } - } - }, - "system": { - "macos": { - "monterey": { - "HOMEBREW_VERSION": "4.4.2-62-g59d56f8", - "HOMEBREW_PREFIX": "/usr/local", - "Homebrew/homebrew-core": "api", - "CLT": "14.2.0.0.1.1668646533", - "Xcode": "14.2", - "macOS": "12.7.6" - } - } - } -} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index e443d1d28..f23a387f4 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -68,9 +68,9 @@ members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at +available at [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see - + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16760d676..5a0cff024 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ We love pull requests from everyone. By participating in this project, you agree ## Getting Started -- Make sure you have a [GitHub account](https://github.com/join). +- Make sure you have a [GitHub account](https://github.com/signup). - [Open an issue](https://github.com/mas-cli/mas/issues/new) to simply ask a question or request a new feature. - Search for similar issues with the [ERROR MESSAGE](https://github.com/mas-cli/mas/issues?utf8=%E2%9C%93&q=is%3Aopen+ERROR+MESSAGE) @@ -25,17 +25,18 @@ you are experiencing. `git checkout -b awesome-feature main` - Please avoid working [directly on the main branch](https://softwareengineering.stackexchange.com/questions/223400/when-should-i-stop-committing-to-master-on-new-projects). - Make commits of logical units. -- Run script/format before committing your changes. Fix anything that isn't automatically fixed by the linters. +- Run `script/format` before committing. +- Run `script/lint` before committing. Fix all lint violations. - Push your topic branch to your fork and [submit a pull request](https://github.com/mas-cli/mas/compare/main...your-username:topic-branch). Some things that will increase the chance that your pull request is accepted: -- Write tests. (Tests target is still [in progress](https://github.com/mas-cli/mas/issues/123)) +- Write tests. - If you need help with tests, feel free to open a PR in the meantime and just ask for some help. - - Add "[WIP]" to the title of your PR to indicate that it's not ready to be merged. +- Add "[WIP]" to the title of your PR to indicate that it's not ready to be merged. - Follow our [style guide](docs/style.md). -- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). - - Including [appropriate emoji](https://gitmoji.carloscuesta.me/) in the first line of commit messages is fun :wink:. +- Write a [good commit message](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). + - Including [appropriate emoji](https://gitmoji.dev) in the first line of commit messages is fun :wink:. ## Becoming a Contributor @@ -50,7 +51,7 @@ to this project, but must remain an owner. By becoming a contributor, you agree ## Branching and Releases -- This project follows [trunk-based development](https://trunkbaseddevelopment.com/), where `main` is our trunk. +- This project follows [trunk-based development](https://trunkbaseddevelopment.com), where `main` is our trunk. - Release commits will be tagged in the format: `v1.2.3`. - Once releases are tagged, high-level release notes are published on the [releases](https://github.com/mas-cli/mas/releases) page. diff --git a/Dangerfile.swift b/Dangerfile.swift index c5e6345b2..52f5b4d8e 100644 --- a/Dangerfile.swift +++ b/Dangerfile.swift @@ -1,19 +1,24 @@ import Danger + let danger = Danger() -// Thanks other people! if let github = danger.github { + // Thank non-member submitters let submitter = github.pullRequest.user.login - if submitter != "phatblat" && submitter != "chris-araman" { + switch submitter { + case "chris-araman", + "phatblat": + break + default: danger.message(":tada: Thanks for your contribution, \(submitter)!") } - // Mainly to encourage writing up some reasoning about the PR, rather than just leaving a title + // Encourage writing up some reasoning about the PR if github.pullRequest.body?.count ?? 0 < 5 { danger.fail(":memo: Please provide a summary in the Pull Request description.") } - // Make it more obvious that a PR is a work in progress and shouldn't be merged yet + // Warn that PR marked [WIP] should be a Draft if github.pullRequest.title.contains("[WIP]") { danger.warn(":construction: Title includes `[WIP]`. Please convert the pull request to a Draft.") } diff --git a/Homebrew/mas-tap.rb b/Homebrew/mas-tap.rb deleted file mode 100644 index 4195b6d3b..000000000 --- a/Homebrew/mas-tap.rb +++ /dev/null @@ -1,51 +0,0 @@ -# typed: strict -# frozen_string_literal: true - -# mas command formula for custom tap (mas-cli/homebrew-tap). -class Mas < Formula - desc "Mac App Store command-line interface" - homepage "https://github.com/mas-cli/mas" - url "https://github.com/mas-cli/mas.git", - tag: "v1.8.7-beta.1", - revision: "f8be3e9aaa6c78490277976f17041f2577f5dc21" - license "MIT" - head "https://github.com/mas-cli/mas.git", branch: "main" - - bottle do - root_url "https://github.com/mas-cli/mas/releases/download/v1.8.7-beta.1" - sha256 cellar: :any_skip_relocation, arm64_sonoma: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, arm64_ventura: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, arm64_monterey: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, arm64_big_sur: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, sonoma: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, ventura: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, monterey: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, big_sur: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, catalina: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, mojave: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, high_sierra: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, sierra: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - sha256 cellar: :any_skip_relocation, el_capitan: "0d042a450d2623e3ea40db0b645454ee88d1a1763a7aa778eec5beea619b9a60" - end - - depends_on :macos - on_arm do - depends_on xcode: ["12.2", :build] - end - on_intel do - depends_on xcode: ["12.0", :build] - end - - def install - system "script/build" - system "script/install", prefix - - bash_completion.install "contrib/completion/mas-completion.bash" => "mas" - fish_completion.install "contrib/completion/mas.fish" - end - - test do - assert_equal version.to_s, shell_output("#{bin}/mas version").chomp - assert_includes shell_output("#{bin}/mas info 497799835"), "Xcode" - end -end diff --git a/Homebrew/mas.rb b/Homebrew/mas.rb deleted file mode 100644 index 050648f6a..000000000 --- a/Homebrew/mas.rb +++ /dev/null @@ -1,46 +0,0 @@ -# typed: strict -# frozen_string_literal: true - -# mas command formula for homebrew-core tap. -class Mas < Formula - desc "Mac App Store command-line interface" - homepage "https://github.com/mas-cli/mas" - url "https://github.com/mas-cli/mas.git", - tag: "v1.8.7-beta.1", - revision: "f8be3e9aaa6c78490277976f17041f2577f5dc21" - license "MIT" - head "https://github.com/mas-cli/mas.git", branch: "main" - - bottle do - sha256 cellar: :any_skip_relocation, arm64_sonoma: "7b11bfefcb43e9a423ff301f7bbc29b0fb86044bf93442f243c5a8a67d8d4869" - sha256 cellar: :any_skip_relocation, arm64_ventura: "e49511dd1283813c4420aec9fc3b3167d18f9fdbb51d82b1e479b628d5312342" - sha256 cellar: :any_skip_relocation, arm64_monterey: "379d46e2657be295321f1603dc1df28130ea0b5b264ceb192a9ba488d77c7a98" - sha256 cellar: :any_skip_relocation, arm64_big_sur: "918a1484de106940f7bebc936e1ded87d7b65652054b09204887ad0651937ec4" - sha256 cellar: :any_skip_relocation, sonoma: "24e3057991ea1eed52eb4a27c0f17d794106770621e5a8bb975477dae135b82d" - sha256 cellar: :any_skip_relocation, ventura: "6ef7788e28c46cdc0f916812f49dfeb1fabf2240a8c36f33ce34bcfb9df1502f" - sha256 cellar: :any_skip_relocation, monterey: "6b313f2f66d028cb7782c108d6e502ce73ccb9c08fac3bece0b057fcce5c4689" - sha256 cellar: :any_skip_relocation, big_sur: "50b50f51219143fcb69c730b52b74011a76104f66348ea727d0200f7b375ae25" - sha256 cellar: :any_skip_relocation, catalina: "d241d3b9156b033f3d2c31684a44de726297e07fd9bd5e3ccc4c36e4f1c3baf3" - end - - depends_on :macos - on_arm do - depends_on xcode: ["12.2", :build] - end - on_intel do - depends_on xcode: ["12.0", :build] - end - - def install - system "script/build" - system "script/install", prefix - - bash_completion.install "contrib/completion/mas-completion.bash" => "mas" - fish_completion.install "contrib/completion/mas.fish" - end - - test do - assert_equal version.to_s, shell_output("#{bin}/mas version").chomp - assert_includes shell_output("#{bin}/mas info 497799835"), "Xcode" - end -end diff --git a/Makefile b/Makefile deleted file mode 100644 index fabe1b40f..000000000 --- a/Makefile +++ /dev/null @@ -1,169 +0,0 @@ -# -# Makefile -# mas -# - -################################################################################ -# -# Variables -# - -CMD_NAME = mas -SHELL = /bin/sh -PREFIX ?= $(shell brew --prefix) - -SWIFT_VERSION = 5.7.1 - -# set EXECUTABLE_DIRECTORY according to your specific environment -# run swift build and see where the output executable is created - -# OS specific differences -UNAME = ${shell uname} -ARCH = ${shell uname -m} - -ifeq ($(UNAME), Darwin) -PLATFORM = $(ARCH)-apple-macosx -EXECUTABLE_DIRECTORY = ./.build/${PLATFORM}/debug -endif - -################################################################################ -# -# Help -# - -.DEFAULT_GOAL := help - -.PHONY: help -help: MAKEFILE_FMT = " \033[36m%-25s\033[0m%s\n" -help: ## (default) Displays this message - @echo "mas Makefile" - @echo "" - @echo "Targets:" - @grep -E '^[a-zA-Z0-9_-]*:.*?##' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?##"}; {printf $(MAKEFILE_FMT), $$1, $$2}' -: # Hacky way to display a newline ## - -################################################################################ -# -# โ„น๏ธ Info Targets -# - -.PHONY: version -version: ## Prints versions of tools used by this Makefile. - xcodebuild -version - swiftenv version - swift --version - swift package tools-version - -.PHONY: init -init: ## Installs tools. - - swiftenv install $(SWIFT_VERSION) - swiftenv local $(SWIFT_VERSION) - -################################################################################ -# -# ๐Ÿ‘ข Bootstrap -# - -.PHONY: bootstrap -bootstrap: ## Installs tools. - script/bootstrap -f - -.PHONY: bootstrap-update -bootstrap-update: ## Upgrades and installs tools. - script/bootstrap - -################################################################################ -# -# ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป Development Targets -# - -.PHONY: clean -clean: ## Cleans built products. - script/clean - -.PHONY: lint -lint: ## Lints source code. - script/lint - -.PHONY: format -format: ## Formats source code. - script/format - -.PHONY: build -build: ## Builds the project. - script/build - -.PHONY: test -test: build ## Runs tests. - script/test - -# make run ARGS="asdf" -.PHONY: run -run: build - ${EXECUTABLE_DIRECTORY}/${CMD_NAME} $(ARGS) - -.PHONY: update-headers -update-headers: ## Updates private macOS headers. - script/update_headers - -################################################################################ -# -# ๐Ÿ•Š๏ธ Swift Package Targets -# - -.PHONY: describe -describe: ## Describes the Swift package. - swift package describe - -.PHONY: resolve -resolve: ## Resolves SwiftPM dependencies. - swift package resolve - -.PHONY: dependencies -dependencies: resolve ## Lists SwiftPM dependencies. - swift package show-dependencies - -.PHONY: update -update: resolve ## Updates SwiftPM dependencies. - swift package update - -################################################################################ -# -# ๐Ÿš€ Release Targets -# - -.PHONY: build-universal -build-universal: ## Builds a "fat" universal binary. - script/build --universal - -.PHONY: install -install: build ## Installs the binary. - script/install $(PREFIX) - -.PHONY: install-universal -install-universal: build-universal ## Installs a universal binary. - script/install --universal - -.PHONY: uninstall -uninstall: ## Uninstalls the binary. - script/uninstall - -.PHONY: package -package: build ## Packages the project. - script/package - -.PHONY: package-install -package-install: package ## Installs the package. - script/package_install - -.PHONY: bottle -bottle: ## Builds Homebrew bottles. - script/bottle - -.PHONY: brew_formula_update -brew_formula_update: ## Updates homebrew-core formula. - script/brew_formula_update - -.PHONY: brew_release_validate -brew_release_validate: ## Builds Homebrew bottle for the current system. - script/brew_release_validate diff --git a/Package/Distribution.plist b/Package/Distribution.plist deleted file mode 100644 index 571cb27eb..000000000 --- a/Package/Distribution.plist +++ /dev/null @@ -1,20 +0,0 @@ - - - mas_components.pkg - - - - - - - - - - - - - - - - - diff --git a/README.md b/README.md index bde16720e..ee463c8f7 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,11 @@ # mas -A command-line interface for the Mac App Store. Designed for scripting and automation. +A command-line interface for the Mac App Store. Designed for scripting & automation. -[![GitHub Release](https://img.shields.io/github/release/mas-cli/mas.svg)](https://github.com/mas-cli/mas/releases) -[![Software License](https://img.shields.io/badge/license-MIT-lightgrey.svg)]( - https://github.com/mas-cli/mas/blob/main/LICENSE -) -[![Swift 5](https://img.shields.io/badge/Language-Swift_5-orange.svg)](https://swift.org) +[![GitHub Release](https://img.shields.io/github/v/release/mas-cli/mas.svg)](https://github.com/mas-cli/mas/releases) +[![Software License](https://img.shields.io/badge/license-MIT-lightgrey.svg)](LICENSE) +[![Swift 5](https://img.shields.io/badge/Language-Swift_5-orange.svg)](https://www.swift.org) [![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) [![Build, Test, & Lint](https://github.com/mas-cli/mas/actions/workflows/build-test.yml/badge.svg?branch=main)]( https://github.com/mas-cli/mas/actions/workflows/build-test.yml?query=branch%3Amain @@ -18,7 +16,7 @@ A command-line interface for the Mac App Store. Designed for scripting and autom ### ๐Ÿบ Homebrew -[Homebrew](http://brew.sh) is the preferred way to install: +[Homebrew](https://brew.sh) is the preferred way to install: ```shell brew install mas @@ -52,18 +50,19 @@ brew install mas-cli/tap/mas #### ๐Ÿ™ GitHub Releases -Alternatively, binaries and sources are available from the [GitHub Releases](https://github.com/mas-cli/mas/releases). +Alternatively, binaries & sources are available from the [GitHub Releases](https://github.com/mas-cli/mas/releases). #### ๐Ÿ•Š Swift 5 Runtime Support -mas requires Swift 5 runtime support. macOS 10.14.4 (Mojave) and newer include it, but earlier releases do not. +mas requires Swift 5 runtime support. macOS 10.14.4 (Mojave) & newer include it, but earlier releases do not. Without it, running mas might report errors similar to: + > dyld: Symbol not found: _$s11SubSequenceSlTl To get Swift 5 support on macOS versions older than 10.14.4 (Mojave), you can: - Upgrade to macOS 10.14.4 (Mojave) or newer. -- Install the [Swift 5 Runtime Support for Command Line Tools](https://support.apple.com/kb/DL1998). +- Install the [Swift 5 Runtime Support for Command Line Tools](https://support.apple.com/en-us/106446). - Install Xcode 10.2 or newer to `/Applications/Xcode.app`. ## ๐Ÿคณ๐Ÿป Usage @@ -71,17 +70,16 @@ To get Swift 5 support on macOS versions older than 10.14.4 (Mojave), you can: ### ๐Ÿชช App IDs Each application in the Mac App Store has an integer app identifier (app ID). -mas commands accept app IDs as arguments and output App IDs to uniquely identify apps. +mas commands accept app IDs as arguments & output App IDs to uniquely identify apps. -`mas search` and `mas list` can be used to find the app IDs of relevant apps. +`mas search` & `mas list` can be used to find the app IDs of relevant apps. Alternatively, to find an app's app ID: 1. Find the app in the Mac App Store 2. Select `Share` > `Copy Link` -3. Extract the app ID from the URL. e.g., the Mac App Store URL for Xcode, - [https://apps.apple.com/us/app/xcode/id497799835?mt=12](https://apps.apple.com/us/app/xcode/id497799835?mt=12), - has app ID `497799835` +3. Extract the app ID from the URL. e.g., the Mac App Store URL for Xcode + () has app ID `497799835` ### ๐Ÿ› Info from the Mac App Store @@ -107,7 +105,7 @@ $ mas search Xcode ```console $ mas info 497799835 -Xcode 16.0 [0.0] +Xcode 16.0 [Free] By: Apple Inc. Released: 2024-09-16 Minimum OS: 14.5 @@ -189,7 +187,9 @@ $ mas lucky Xcode All the commands in this section require you to be logged into an Apple ID in the Mac App Store. > mas only installs/upgrades applications from the Mac App Store. -Use [`softwareupdate(8)`] to install system updates (e.g., Xcode Command Line Tools, Safari, etc.) +> +> Use [`softwareupdate(8)`](https://www.unix.com/man-page/osx/8/softwareupdate) to install system updates (e.g., Xcode +> Command Line Tools, Safari, etc.) #### `mas upgrade` @@ -270,23 +270,16 @@ Over time, Apple has silently changed these frameworks, breaking some functional https://github.com/mas-cli/mas/issues/417 ) -### ๐Ÿ‘€ Version Consistency - -mas might be using suboptimal app version sources to compare local app versions with Mac App Store app versions. -That current sources are frequently consistent with the Mac App Store, but are infrequently inconsistent. -This might cause symptoms like [#384](https://github.com/mas-cli/mas/issues/384) and -[#387](https://github.com/mas-cli/mas/issues/387). mas will be updated soon to fix any such problems, if possible. - ### โณ Eventual Consistency The Mac App Store operates on eventual consistency, so the versions seen by various parts of mas or the Mac App Store -might be inconsistent for some period of time. This might cause symptoms like -[#384](https://github.com/mas-cli/mas/issues/384) and [#387](https://github.com/mas-cli/mas/issues/387). +might be inconsistent for short periods of time. This might cause symptoms like +[#384](https://github.com/mas-cli/mas/issues/384) & [#387](https://github.com/mas-cli/mas/issues/387). -### ๐Ÿ“ฑ iOS and iPadOS Apps +### ๐Ÿ“ฑ iOS & iPadOS Apps -Macs with Apple Silicon can install and run iOS and iPadOS apps from the Mac App Store. mas is not yet aware of these -apps, and is not yet able to install or upgrade them. [#321](https://github.com/mas-cli/mas/issues/321) +Apple Silicon Macs can install & run iOS & iPadOS apps from the Mac App Store. mas does not yet support such apps. +[#321](https://github.com/mas-cli/mas/issues/321) ### ๐Ÿ“บ Using `tmux` @@ -320,18 +313,14 @@ All feedback is much appreciated! โœจ You can build from Xcode by opening the root mas directory, or from the Terminal: ```shell -script/bootstrap script/build ``` -Build output can be found in the `.build/` directory within the project. +Build output can be found in the `.build` directory within the project. ## โœ… Tests -The tests in this project are a recent work-in-progress. -Since Xcode does not officially support tests for command-line tool targets, -all logic is part of the mas target with tests in masTests. -Tests are written using [Quick]. +Tests are written using [Quick](https://github.com/Quick/Quick) & [Nimble](https://github.com/Quick/Nimble). ```shell script/test @@ -339,9 +328,8 @@ script/test ## ๐Ÿ“„ License -mas was created by [@argon](https://github.com/argon). Code is under the [MIT license](LICENSE). +mas was created by [@argon](https://github.com/argon). + [homebrew-bundle]: https://github.com/Homebrew/homebrew-bundle -[`softwareupdate(8)`]: https://www.unix.com/man-page/osx/8/softwareupdate/ -[Quick]: https://github.com/Quick/Quick diff --git a/Sources/PrivateFrameworks/CommerceKit/CKServiceInterface.h b/Sources/PrivateFrameworks/CommerceKit/CKServiceInterface.h index 14a263943..7792c287e 100644 --- a/Sources/PrivateFrameworks/CommerceKit/CKServiceInterface.h +++ b/Sources/PrivateFrameworks/CommerceKit/CKServiceInterface.h @@ -11,4 +11,3 @@ } @end - diff --git a/Sources/PrivateFrameworks/StoreFoundation/SSDownload.h b/Sources/PrivateFrameworks/StoreFoundation/SSDownload.h index 827d425d5..f5519c389 100644 --- a/Sources/PrivateFrameworks/StoreFoundation/SSDownload.h +++ b/Sources/PrivateFrameworks/StoreFoundation/SSDownload.h @@ -62,4 +62,3 @@ - (void)cancel; @end - diff --git a/Sources/mas/AppStore/Downloader.swift b/Sources/mas/AppStore/Downloader.swift index 5ec5d6178..b1e7216b4 100644 --- a/Sources/mas/AppStore/Downloader.swift +++ b/Sources/mas/AppStore/Downloader.swift @@ -65,8 +65,8 @@ func downloadApps(withAppIDs appIDs: [AppID], purchasing: Bool = false) -> Promi } } .done { - if let error = firstError { - throw error + if let firstError { + throw firstError } } } diff --git a/Sources/mas/Commands/Upgrade.swift b/Sources/mas/Commands/Upgrade.swift index 3f1d3f414..fb30be4c8 100644 --- a/Sources/mas/Commands/Upgrade.swift +++ b/Sources/mas/Commands/Upgrade.swift @@ -14,8 +14,7 @@ extension MAS { /// Command which upgrades apps with new versions available in the Mac App Store. struct Upgrade: ParsableCommand { static let configuration = CommandConfiguration( - abstract: - "Upgrade outdated app(s) installed from the Mac App Store" + abstract: "Upgrade outdated app(s) installed from the Mac App Store" ) @Argument(help: ArgumentHelp("App ID/app name", valueName: "app-id-or-name")) diff --git a/Tests/masTests/.swiftlint.yml b/Tests/masTests/.swiftlint.yml index dc0cbcd0a..bc2a00873 100644 --- a/Tests/masTests/.swiftlint.yml +++ b/Tests/masTests/.swiftlint.yml @@ -4,7 +4,6 @@ # # https://github.com/realm/SwiftLint#configuration # - --- disabled_rules: - force_cast diff --git a/Tests/masTests/JSON/lookup/fantastical.json b/Tests/masTests/JSON/lookup/fantastical.json index e36d8c912..64478878b 100644 --- a/Tests/masTests/JSON/lookup/fantastical.json +++ b/Tests/masTests/JSON/lookup/fantastical.json @@ -61,4 +61,4 @@ "userRatingCount": 1342 } ] -} \ No newline at end of file +} diff --git a/Tests/masTests/JSON/lookup/notability.json b/Tests/masTests/JSON/lookup/notability.json index 9aa1c90ee..fab3501c8 100644 --- a/Tests/masTests/JSON/lookup/notability.json +++ b/Tests/masTests/JSON/lookup/notability.json @@ -69,4 +69,4 @@ "userRatingCount": 1840 } ] -} \ No newline at end of file +} diff --git a/Tests/masTests/JSON/lookup/things.json b/Tests/masTests/JSON/lookup/things.json index 64141dd27..b73839342 100644 --- a/Tests/masTests/JSON/lookup/things.json +++ b/Tests/masTests/JSON/lookup/things.json @@ -65,4 +65,4 @@ "userRatingCount": 1412 } ] -} \ No newline at end of file +} diff --git a/Tests/masTests/JSON/search/nonexistent.json b/Tests/masTests/JSON/search/nonexistent.json index 9a683b1cf..ed4da7187 100644 --- a/Tests/masTests/JSON/search/nonexistent.json +++ b/Tests/masTests/JSON/search/nonexistent.json @@ -1,9 +1,4 @@ - - - { "resultCount":0, "results": [] } - - diff --git a/contrib/completion/mas-completion.bash b/contrib/completion/mas-completion.bash index 31d9a0934..c383d9ca0 100644 --- a/contrib/completion/mas-completion.bash +++ b/contrib/completion/mas-completion.bash @@ -8,8 +8,20 @@ _mas() { COMPREPLY=() _get_comp_words_by_ref cur prev words cword fi - if [[ $cword -eq 1 ]]; then - COMPREPLY=($(compgen -W "$(mas help | tail -n +3 | awk '{print $1}')" -- "$cur")) + if [[ "${cword}" -eq 1 ]]; then + local -r ifs_old="${IFS}" + IFS=$'\n' + local -a mas_help=($(mas help)) + mas_help=("${mas_help[@]:5:${#mas_help[@]}-6}") + mas_help=("${mas_help[@]# }") + local -a commands=(help) + for line in "${mas_help[@]}"; do + if [[ ! "${line}" =~ ^\ ]]; then + commands+=("${line%% *}") + fi + done + COMPREPLY=($(compgen -W "${commands[*]}" -- "${cur}")) + IFS="${ifs_old}" return 0 fi } diff --git a/contrib/completion/mas.fish b/contrib/completion/mas.fish index 05101e571..be4278a93 100644 --- a/contrib/completion/mas.fish +++ b/contrib/completion/mas.fish @@ -2,9 +2,9 @@ function __fish_mas_list_available -d "Lists applications available to install from the Mac App Store" set query (commandline -ct) - if set results (command mas search $query 2>/dev/null) + if set results (command mas search "$query" 2>/dev/null) for res in $results - echo $res + echo "$res" end | string trim --left | string replace -r '\s+' '\t' end end diff --git a/docs/sample.swift b/docs/sample.swift index 17fc5d450..4e1acb7d2 100644 --- a/docs/sample.swift +++ b/docs/sample.swift @@ -2,93 +2,99 @@ // MARK: Types and naming -// Types begin with a capital letter +/// Types begin with a capital letter. struct User { let name: String - // if the first letter of an acronym is lowercase, the entire thing should - // be lowercase + /// if the first letter of an acronym is lowercase, the entire thing should + /// be lowercase. let json: Any - // if the first letter of an acronym is uppercase, the entire thing should - // be uppercase - static func decode(from json: JSON) -> User { - return User(json: json) + /// if the first letter of an acronym is uppercase, the entire thing should + /// be uppercase. + static func decode(from json: JSON) -> Self { + Self(json: json) } } -// Use () for void arguments and Void for void return types -let f: () -> Void = {} +/// Use () for void arguments and Void for void return types. +let closure: () -> Void = { + // Do nothing +} -// When using classes, default to marking them as final -final class MyViewController: UIViewController { - // Prefer strong IBOutlet references - @IBOutlet var button: UIButton! +/// When using classes, default to marking them as final. +final class MyClass { + // Empty class } -// Use typealias when closures are referenced in multiple places +/// Use typealias when closures are referenced in multiple places. typealias CoolClosure = (Int) -> Bool -// Use aliased parameter names when function parameters are ambiguous +/// Use aliased parameter names when function parameters are ambiguous. func yTown(some: Int, withCallback callback: CoolClosure) -> Bool { - return callback(some) + callback(some) } -// It's OK to use $ variable references if the closure is very short and -// readability is maintained +/// It's OK to use $ variable references if the closure is very short and +/// readability is maintained. let cool = yTown(5) { $0 == 6 } -// Use full variable names when closures are more complex +/// Use full variable names when closures are more complex. let cool = yTown(5) { foo in - if foo > 5, foo < 0 { - return true - } else { - return false - } + max(foo, 0) + // โ€ฆ } // Strongify weak references in async closures APIClient.getAwesomeness { [weak self] result in - guard let `self` = self else { return } + guard let self else { + return + } self.stopLoadingSpinner() self.show(result) } -// If the API you are using has implicit unwrapping you should still use if-let -func someUnauditedAPI(thing: String!) { - if let string = thing { - print(string) +/// Use if-let to check for not `nil` (even if using an implicitly unwrapped variable from an API). +func someUnauditedAPI(thing: String?) { + if let thing { + print(thing) } } -// When the type is known you can let the compiler infer +/// When the type is known you can let the compiler infer. let response: Response = .success(NSData()) func doSomeWork() -> Response { - let data = ... + let data = Data("", .utf8) return .success(data) } switch response { -case let .success(data): +case .success(let data): print("The response returned successfully \(data)") - -case let .failure(error): +case .failure(let error): print("An error occurred: \(error)") } // MARK: Organization -// Group methods into specific extensions for each level of access control +/// Group methods into specific extensions for each level of access control. private extension MyClass { - func doSomethingPrivate() {} + func doSomethingPrivate() { + // Do something + } } // MARK: Breaking up long lines // One expression to evaluate and short or no return -guard let singleTest = somethingFailable() else { return } -guard statementThatShouldBeTrue else { return } +guard let singleTest = somethingFailable() else { + return +} + +guard statementThatShouldBeTrue else { + return +} // If a guard clause requires multiple lines, chop down, then start `else` new line // In this case, always chop down else clause. diff --git a/docs/style.md b/docs/style.md index c0487ba64..27051611b 100644 --- a/docs/style.md +++ b/docs/style.md @@ -3,8 +3,8 @@ - Use `script/format` to automatically fix a number of style violations. - Remove unnecessary whitespace from the end of lines. - Use `script/lint` to look for these before committing. - - Note that [two trailing spaces](https://gist.github.com/shaunlebron/746476e6e7a4d698b373) - is intentional in markdown documents to create a line break like `
`, so these should _not_ be removed. + - Note that two trailing spaces is valid markdown to create a line break like `
`, + so those should _not_ be removed. - End each file with a [newline character]( https://unix.stackexchange.com/questions/18743/whats-the-point-in-adding-a-new-line-to-the-end-of-a-file#18789 ). @@ -13,7 +13,7 @@ [Sample](sample.swift) -- Avoid [force unwrapping optionals](https://blog.timac.org/2017/0628-swift-banning-force-unwrapping-optionals/) +- Avoid [force unwrapping optionals](https://blog.timac.org/2017/0628-swift-banning-force-unwrapping-optionals) with `!` in production code - Production code is what gets shipped with the app. Basically, everything under the [`Sources/mas`](https://github.com/mas-cli/mas/tree/main/Sources/mas) folder. diff --git a/script/_setup_script b/script/_setup_script new file mode 100755 index 000000000..40b73f14c --- /dev/null +++ b/script/_setup_script @@ -0,0 +1,42 @@ +#!/bin/zsh -Ndefgku +# +# script/_setup_script +# mas +# +# Boilerplate setup for scripts. +# + +\unalias -as +setopt\ + autopushd\ + combiningchars\ + extendedglob\ + extendedhistory\ + no_globalrcs\ + histexpiredupsfirst\ + histignorespace\ + histverify\ + incappendhistorytime\ + interactivecomments\ + pipefail\ + no_rcs\ + no_unset +export HISTCHARS='!^#' +export IFS=$' \t\n\0' +export NULLCMD=cat +export PAGER=cat +export READNULLCMD=cat +export TMPDIR="${"${TMPDIR:-/tmp/}"/%(#b)([^\/])/"${match[1]}"/}" +export TMPPREFIX="${TMPPREFIX:-"${TMPDIR}"zsh}" +unset CDPATH +unset ENV +unset KEYBOARD_HACK +unset TMPSUFFIX +unset WORDCHARS + +mas_dir="${0:a:h:h}" + +if ! cd -- "${mas_dir}"; then + printf $'Error: Could not cd into mas directory: %s\n' "${mas_dir}" >&2 + exit 1 +fi diff --git a/script/bootstrap b/script/bootstrap index 8af2285a1..63c4eba02 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -1,55 +1,19 @@ -#!/bin/bash -eu +#!/bin/zsh -Ndefgku # # script/bootstrap # mas # -# Installs development dependencies and builds project dependencies. +# Installs dependencies for script/format & script/lint. +# +# Usage: bootstrap [...] # -mas_dir="$(readlink -fn "$(dirname "${BASH_SOURCE:-"${0}"}")/..")" - -if ! cd -- "${mas_dir}"; then - printf $'Error: Could not cd into mas directory: %s\n' "${mas_dir}" >&2 - exit 1 -fi - -function usage { - echo "Usage: bootstrap [-f]" - echo " -f option enables frozen mode" - exit 1 -} - -frozen='' - -# Detect presence of `-f` frozen option -while getopts "f" opt; do - case "${opt}" in - f) - frozen='-f' - ;; - *) - usage 1>&2 - ;; - esac -done - -script/clean +. "${0:a:h}/_setup_script" -printf $'==> ๐Ÿ‘ข Bootstrapping (%s)\n' "$(script/version)" +printf $'==> ๐Ÿ‘ข Bootstrapping mas %s\n' "$(script/version)" -# Install Homebrew tools -if [[ "${frozen}" == "-f" ]]; then - # --no-lock Don't touch Brewfile.lock.json - brew bundle install --no-lock --no-upgrade --verbose -else - # Allow upgrades - rm -f Brewfile.lock.json - brew bundle install --verbose +if ! command -v brew >/dev/null; then + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" fi -if [[ ! -x "$(command -v mise)" ]]; then - brew install mise -fi -mise settings set experimental true -mise install --verbose -mise list --verbose +brew bundle install --verbose "${@}" diff --git a/script/bottle b/script/bottle deleted file mode 100755 index e4c7bb04c..000000000 --- a/script/bottle +++ /dev/null @@ -1,166 +0,0 @@ -#!/bin/bash -ex -# -# script/bottle -# mas -# -# Builds bottles of mas Homebrew formula for custom tap: -# https://github.com/mas-cli/homebrew-tap -# -# This script should be run _after_ the formula has been updated in Homebrew -# - -################################################################################ -# -# Variables -# - -BUILD_DIR="${PWD}/.build" -BOTTLE_DIR="${BUILD_DIR}/bottles" -CORE_TAP_PATH="$(brew --repository homebrew/core)" -MAS_VERSION=$(script/version) -ROOT_URL="https://github.com/mas-cli/mas/releases/download/v${MAS_VERSION}" - -# Supports macOS 10.13 and later -OS_NAMES=( - sequoia - arm64_sequoia - sonoma - arm64_sonoma - ventura - arm64_ventura - monterey - arm64_monterey - big_sur - arm64_big_sur - catalina - mojave - high_sierra - sierra - el_capitan -) - -# Semantic version number split into a list using ugly, bash 3 compatible syntax -IFS=" " read -r -a CURRENT_OS_VERSION <<<"$(sw_vers -productVersion | sed 's/\./ /g')" -CURRENT_OS_VERSION_MAJOR=${CURRENT_OS_VERSION[0]} -CURRENT_OS_VERSION_MINOR=${CURRENT_OS_VERSION[1]} - -echo "CURRENT_OS_VERSION_MAJOR: ${CURRENT_OS_VERSION_MAJOR}" -echo "CURRENT_OS_VERSION_MINOR: ${CURRENT_OS_VERSION_MINOR}" - -case "${CURRENT_OS_VERSION_MAJOR}" in - 15) - CURRENT_PLATFORM=sequoia - ;; - 14) - CURRENT_PLATFORM=sonoma - ;; - 13) - CURRENT_PLATFORM=ventura - ;; - 12) - CURRENT_PLATFORM=monterey - ;; - 11) - CURRENT_PLATFORM=big_sur - ;; - 10) - CURRENT_PLATFORM=catalina - ;; - *) - echo "Unsupported macOS version. This script requires Catalina or better." - exit 1 - ;; -esac - -# Prefix platform with architecture -if [[ "arm64" == "$(uname -m)" ]]; then - CURRENT_PLATFORM="arm64_${CURRENT_PLATFORM}" -fi - -echo "CURRENT_PLATFORM: ${CURRENT_PLATFORM}" - -# Output filename from build-bottle command -OLD_FILENAME="mas--${MAS_VERSION}.${CURRENT_PLATFORM}.bottle.tar.gz" - -################################################################################ -# -# Preflight checks -# - -# # Uninstall if necessary -# brew remove mas 2>/dev/null || true -# brew remove mas-cli/tap/mas 2>/dev/null || true - -# # Uninstall if still found on path -# if command -v mas >/dev/null; then -# script/uninstall || true -# fi - -# Use formula from custom tap -# brew tap mas-cli/tap -# brew update - -# Audit formula -brew audit --strict --verbose --formula --tap mas-cli/tap mas -brew style Homebrew/mas-tap.rb - -################################################################################ -# -# Build the formula for the current macOS version and architecture. -# - -echo "==> ๐Ÿผ Bottling mas ${MAS_VERSION} for: ${OS_NAMES[*]}" -brew install --build-bottle mas-cli/tap/mas - -# Generate bottle do block, dropping last 2 lines -brew bottle --verbose --no-rebuild --root-url="${ROOT_URL}" mas-cli/tap/mas -if ! test -e "${OLD_FILENAME}"; then - echo "Bottle not found: ${OLD_FILENAME}" - echo "If an old version is showing in the log and filename, then make sure the formula has been updated in:" - echo "${CORE_TAP_PATH}" - exit 1 -fi - -SHA256=$(shasum --algorithm 256 "${OLD_FILENAME}" | cut -f 1 -d ' ' -) - -mkdir -p "${BOTTLE_DIR}" - -# Start of bottle block -BOTTLE_BLOCK=$( - cat <<-EOF -bottle do - root_url "${ROOT_URL}" -EOF -) - -################################################################################ -# -# Copy the bottle for all macOS version + architecture combinations. -# - -# Fix filename -for os in "${OS_NAMES[@]}"; do - new_filename="mas-${MAS_VERSION}.${os}.bottle.tar.gz" - cp -v "${OLD_FILENAME}" "${BOTTLE_DIR}/${new_filename}" - - # Append each os - # BOTTLE_BLOCK="$(printf "${BOTTLE_BLOCK}\n sha256 cellar: :any_skip_relocation, %-15s %s" "${os}:" "${SHA256}")" - BOTTLE_BLOCK="${BOTTLE_BLOCK}"$( - cat <<-EOF - - sha256 cellar: :any_skip_relocation, ${os}: "${SHA256}" -EOF - ) -done - -# End of bottle block -BOTTLE_BLOCK=$( - cat <<-EOF - -end -EOF -) - -rm "${OLD_FILENAME}" -ls -l "${BOTTLE_DIR}" -echo "${BOTTLE_BLOCK}" diff --git a/script/brew_build_interactive b/script/brew_build_interactive deleted file mode 100755 index 654bb4911..000000000 --- a/script/brew_build_interactive +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -e -# -# script/brew_build_interactive -# mas -# -# https://docs.brew.sh/Formula-Cookbook#check-the-build-system -# - -HOMEBREW_NO_INSTALL_FROM_API=1 \ - brew reinstall \ - --interactive mas diff --git a/script/brew_core_update b/script/brew_core_update deleted file mode 100755 index af8f46e44..000000000 --- a/script/brew_core_update +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/bash -ex -# -# script/brew_core_update -# mas -# -# Updates mas Homebrew core formula: -# https://github.com/Homebrew/homebrew-core/blob/master/Formula/mas.rb -# -# brew bump-formula-pr --help -# - -CORE_TAP_PATH="$(brew --repository homebrew/core)" -CORE_MAS_FORMULA_FILE="${CORE_TAP_PATH}/Formula/m/mas.rb" - -PROJECT_PATH="$(git rev-parse --show-toplevel)" -LOCAL_MAS_FORMULA_PATH="${PROJECT_PATH}/Homebrew/mas.rb" - -function usage { - echo "Usage: brew_core_update [-d] v0.0 [sha1_hash]" - echo " -d option enables dry run mode" - echo " version will be inferred using version script if not provided" - echo " sha will be inferred from the current commit if not provided" - exit 1 -} - -# Max 3 arguments -if [[ $# -gt 3 ]]; then - usage 1>&2 -fi - -echo='' -dry_run='' - -# Detect presence of `-d` dry run option -while getopts "d" o; do - case "${o}" in - d) - echo='echo (DRY-RUN):' - dry_run='-d' - ;; - *) - usage 1>&2 - ;; - esac -done -shift $((OPTIND - 1)) - -# DRY_RUN environment variable -# shellcheck disable=SC2153 -if [[ $DRY_RUN == 'true' ]]; then - echo='echo (DRY-RUN):' - dry_run='-d' -fi - -# arg 1 - version tag -if [[ -n "${1}" ]]; then - MAS_VERSION="${1}" -else - MAS_VERSION="v$(script/version)" -fi - -echo "MAS_VERSION: ${MAS_VERSION}" - -# arg 2 - revision (commit hash) -if [[ -n "${2}" ]]; then - REVISION="${2}" -else - # Derive revision from version. Fails if MAS_VERSION is not a tag. - REVISION=$(git rev-parse "${MAS_VERSION}") -fi - -echo "REVISION: ${REVISION}" - -################################################################################ -# -# Preflight checks -# - -# Uninstall if necessary -brew remove mas 2>/dev/null || true -brew remove mas-cli/tap/mas 2>/dev/null || true - -# Uninstall if still found on path -if command -v mas >/dev/null; then - script/uninstall || true -fi - -# Ensure core is tapped -if ! [[ -d "${CORE_TAP_PATH}" ]]; then - brew tap homebrew/core -fi - -brew update - -################################################################################ -# -# Build the formula for the current macOS version and architecture. -# - -# Update mas formula in core (temporary) -cp -v "${LOCAL_MAS_FORMULA_PATH}" "${CORE_MAS_FORMULA_FILE}" - -# Install mas from source -# HOMEBREW_NO_INSTALL_FROM_API: -# Force brew to use the local repository instead of the API. -# Disable API before any install, reinstall or upgrade commands. - -HOMEBREW_NO_INSTALL_FROM_API=1 \ - brew install mas \ - --build-from-source \ - --verbose - -# Audit formula -brew audit --strict mas -brew style mas - -# Revert core formula change after testing -pushd "${CORE_TAP_PATH}" -git diff -git checkout . -popd - -################################################################################ -# -# Update Homebrew -# - -# echo "Checking to see if this update can be a simple bump." -# diff "${LOCAL_MAS_FORMULA_PATH}" "${CORE_MAS_FORMULA_FILE}" - -echo "==> ๐Ÿงช Updating homebrew-core formula mas (${MAS_VERSION}, ${REVISION})" - -echo "Validating formula" -brew bump-formula-pr \ - --tag="${MAS_VERSION}" \ - --revision="${REVISION}" \ - --strict \ - --verbose \ - --no-browse \ - --fork-org mas-cli \ - --dry-run \ - mas - -# brew exit status -status=$? -if [[ ${status} -ne 0 ]]; then - echo "Formula did not validate using 'brew bump-formula-pr'" - exit ${status} -fi - -if [[ $dry_run == '-d' ]]; then - exit 0 -fi - -pushd "${CORE_TAP_PATH}" - -echo "Updating homebrew/core formula with a PR" - -$echo brew bump-formula-pr \ - --tag="${MAS_VERSION}" \ - --revision="${REVISION}" \ - --strict \ - --verbose \ - --online \ - --no-browse \ - --fork-org mas-cli \ - mas - -popd diff --git a/script/brew_release_validate b/script/brew_release_validate deleted file mode 100755 index bc4f76709..000000000 --- a/script/brew_release_validate +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# -# script/brew_release_validate -# mas -# -# Validates the mas formula -# https://github.com/Homebrew/homebrew-core/blob/master/CONTRIBUTING.md#to-contribute-a-fix-to-the-foo-formula -# - -brew uninstall --force mas -brew install --build-from-source mas -brew test mas -brew audit --strict mas -brew style mas diff --git a/script/brew_tap_update b/script/brew_tap_update deleted file mode 100755 index 6dd7a88e4..000000000 --- a/script/brew_tap_update +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -ex -# -# script/brew_tap_update -# mas -# -# Updates mas custom tap formula: -# https://github.com/mas-cli/homebrew-tap/blob/main/Formula/mas.rb -# - -function usage { - echo "Usage: brew_tap_update [-d] v0.0 [sha1_hash]" - echo " -d option enables dry run mode" - echo " version will be inferred using version script if not provided" - echo " sha will be inferred from the current commit if not provided" - exit 1 -} - -# Max 3 arguments -if [[ $# -gt 3 ]]; then - usage 1>&2 -fi - -# arg 1 - version tag -if [[ -n "${1}" ]]; then - MAS_VERSION="${1}" -else - MAS_VERSION="v$(script/version)" -fi - -echo "MAS_VERSION: ${MAS_VERSION}" - -# arg 2 - revision (commit hash) -if [[ -n "${2}" ]]; then - REVISION="${2}" -else - # Derive revision from version. Fails if MAS_VERSION is not a tag. - REVISION=$(git rev-parse "${MAS_VERSION}") -fi - -echo "REVISION: ${REVISION}" - -# Build in mas project -script/bottle diff --git a/script/build b/script/build index fd84a9a31..809de60a8 100755 --- a/script/build +++ b/script/build @@ -1,4 +1,4 @@ -#!/bin/bash -eu +#!/bin/zsh -Ndefgku # # script/build # mas @@ -6,31 +6,10 @@ # Builds the Swift Package. # -mas_dir="$(readlink -fn "$(dirname "${BASH_SOURCE:-"${0}"}")/..")" +. "${0:a:h}/_setup_script" -if ! cd -- "${mas_dir}"; then - printf $'Error: Could not cd into mas directory: %s\n' "${mas_dir}" >&2 - exit 1 -fi +printf $'==> ๐Ÿ—๏ธ Building mas %s\n' "$(script/version)" -# Build for the host architecture by default. -ARCH=() -if [[ "${#}" -ge 1 && "${1}" == '--universal' ]]; then - ARCH=( - --arch arm64 - --arch x86_64 - ) -fi +script/generate_version_info_for_swift -# Disable the manifest cache on Xcode 12.5 and later. -CACHE=() -if [[ "$(swift build --help)" =~ manifest-cache ]]; then - CACHE=(--manifest-cache none) -fi - -echo "==> ๐Ÿ—๏ธ Building mas ($(script/version --write))" -swift build \ - --configuration release \ - "${ARCH[@]+"${ARCH[@]}"}" \ - --disable-sandbox \ - "${CACHE[@]+"${CACHE[@]}"}" +swift build --configuration release "${@}" diff --git a/script/build_artifacts b/script/build_artifacts deleted file mode 100755 index 6414d1609..000000000 --- a/script/build_artifacts +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -e -# -# script/build_artifacts -# mas -# -# Runs all related scripts for generating all artifacts. -# - -MAS_VERSION=$(script/version) - -echo "Building mas $MAS_VERSION artifacts" - -script/clean -script/build --universal -script/package diff --git a/script/clean b/script/clean index ded54c5be..b5af491c3 100755 --- a/script/clean +++ b/script/clean @@ -1,4 +1,4 @@ -#!/bin/bash -e +#!/bin/zsh -Ndefgku # # script/clean # mas @@ -6,5 +6,8 @@ # Deletes the build directory. # +. "${0:a:h}/_setup_script" + swift package clean swift package reset +rm -f Sources/mas/Package.swift diff --git a/script/format b/script/format index b942cb26e..db5fb8d36 100755 --- a/script/format +++ b/script/format @@ -1,51 +1,37 @@ -#!/bin/bash -eu +#!/bin/zsh -Ndefgku # # script/format # mas # -# Linting checks for development and CI. -# # Automatically formats and fixes style violations using various tools. # # Please keep in sync with script/lint. # -mas_dir="$(readlink -fn "$(dirname "${BASH_SOURCE:-"${0}"}")/..")" - -if ! cd -- "${mas_dir}"; then - printf $'Error: Could not cd into mas directory: %s\n' "${mas_dir}" >&2 - exit 1 -fi +. "${0:a:h}/_setup_script" -printf $'==> ๐Ÿšจ Formatting mas\n' +printf $'==> ๐Ÿšจ Formatting mas %s\n' "$(script/version)" -for LINTER in markdownlint prettier shfmt swift-format swiftformat swiftlint yamllint; do - if [[ ! -x "$(command -v ${LINTER})" ]]; then - printf $'error: %s is not installed. Run \'script/bootstrap\' or \'brew install %s\'.\n' "${LINTER}" "${LINTER}" +for formatter in markdownlint prettier swift-format swiftformat swiftlint yamllint; do + if ! command -v "${formatter}" >/dev/null; then + printf $'error: %s is not installed. Run \'script/bootstrap\' or \'brew install %s\'.\n' "${formatter}" "${formatter}" >&2 exit 1 fi done -for SOURCE in Package.swift Sources Tests; do - printf -- $'--> ๐Ÿ•Š %s swift-format\n' "${SOURCE}" - swift-format format --in-place --recursive "${SOURCE}" - printf -- $'--> ๐Ÿ•Š %s swiftformat\n' "${SOURCE}" - swiftformat "${SOURCE}" - printf -- $'--> ๐Ÿ•Š %s swiftlint\n' "${SOURCE}" - swiftlint --fix --strict "${SOURCE}" +for source in Package.swift Sources Tests; do + printf -- $'--> ๐Ÿฆ… %s swift-format\n' "${source}" + swift-format format --in-place --recursive "${source}" + printf -- $'--> ๐Ÿฆ… %s swiftformat\n' "${source}" + script -q /dev/null swiftformat --strict "${source}" | + (grep -vxE '(?:\^D\x08{2})?Running SwiftFormat\.{3}\r|Reading (?:config|swift-version) file at .*|\x1b\[32mSwiftFormat completed in \d+\.\d+s\.\x1b\[0m\r|0/\d+ files formatted\.\r' || true) + printf -- $'--> ๐Ÿฆ… %s swiftlint\n' "${source}" + swiftlint --fix --quiet "${source}" done -printf -- $'--> ๐Ÿ“œ Bash shfmt\n' -shfmt \ - --write \ - --list \ - --indent 2 \ - --case-indent \ - contrib/ script/ - printf -- $'--> ใ€ฝ๏ธ Markdown\n' -markdownlint --config .markdownlint.json --fix .github . +markdownlint --config .markdownlint.json --fix . docs -printf -- $'--> ๐Ÿ–Š YAML\n' -# shellcheck disable=SC2046 -prettier --write $(yamllint --list-files .) +printf -- $'--> ๐Ÿ“ YAML\n' +script -q /dev/null prettier --write "${(f)"$(yamllint --list-files .)"}" | + (grep -vxE '.+ \d+ms \(unchanged\)\r' || true) diff --git a/script/generate_version_info_for_swift b/script/generate_version_info_for_swift new file mode 100755 index 000000000..c29e2741b --- /dev/null +++ b/script/generate_version_info_for_swift @@ -0,0 +1,17 @@ +#!/bin/zsh -Ndefgku +# +# script/generate_version_info_for_swift +# mas +# +# Generates a file to provide the mas version to Swift code. +# + +. "${0:a:h}/_setup_script" + +# Write version to Swift singleton +cat <Sources/mas/Package.swift +/// Generated by \`script/generate_version_info_for_swift\`. +enum Package { + static let version = "$(script/version)" +} +EOF diff --git a/script/install b/script/install deleted file mode 100755 index c771518e5..000000000 --- a/script/install +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -e -# -# script/install -# mas -# -# Installs mas into PREFIX. -# -# NOTE: This script is called by the mas Homebrew formula so it has only system -# dependencies aside from Swift. -# https://github.com/Homebrew/homebrew-core/blob/master/Formula/mas.rb -# - -ARCH=$(uname -m) -RELEASE=.build/${ARCH}-apple-macosx/release -MAS_VERSION=$(script/version) -PREFIX=/usr/local - -while test -n "$1"; do - if [[ "$1" == '--universal' ]]; then - ARCH=universal - RELEASE=.build/release - else - # Override default prefix path with optional arg - PREFIX="$1" - fi - - shift -done - -echo "==> ๐Ÿ“ฒ Installing mas ($MAS_VERSION) for $ARCH to $PREFIX" -ditto -v \ - "$RELEASE/mas" \ - "$PREFIX/bin/mas" diff --git a/script/lint b/script/lint index d655a52a2..9632678e3 100755 --- a/script/lint +++ b/script/lint @@ -1,4 +1,4 @@ -#!/bin/bash -u +#!/bin/zsh -Ndfgku # # script/lint # mas @@ -10,20 +10,15 @@ # Please keep in sync with script/format. # -set -o pipefail +. "${0:a:h}/_setup_script" -mas_dir="$(readlink -fn "$(dirname "${BASH_SOURCE:-"${0}"}")/..")" +printf $'==> ๐Ÿšจ Linting mas %s\n' "$(script/version)" -if ! cd -- "${mas_dir}"; then - printf $'Error: Could not cd into mas directory: %s\n' "${mas_dir}" >&2 - exit 1 -fi +script/generate_version_info_for_swift -printf $'==> ๐Ÿšจ Linting mas (%s)\n' "$(script/version --write)" - -for linter in git markdownlint periphery shellcheck shfmt swift-format swiftformat swiftlint yamllint; do - if [[ ! -x "$(command -v ${linter})" ]]; then - printf $'error: %s is not installed. Run \'script/bootstrap\' or \'brew install %s\'.\n' "${linter}" "${linter}" +for linter in git markdownlint periphery shellcheck swift-format swiftformat swiftlint yamllint; do + if ! command -v "${linter}" >/dev/null; then + printf $'error: %s is not installed. Run \'script/bootstrap\' or \'brew install %s\'.\n' "${linter}" "${linter}" >&2 exit 1 fi done @@ -32,45 +27,35 @@ exit_code=0 for source in Package.swift Sources Tests; do printf -- $'--> ๐Ÿฆ… %s swift-format\n' "${source}" swift-format lint --strict --recursive "${source}" - ((exit_code |= "${?}")) + ((exit_code |= ${?})) printf -- $'--> ๐Ÿฆ… %s swiftformat\n' "${source}" script -q /dev/null swiftformat --lint --strict "${source}" | (grep -vxE '(?:\^D\x08{2})?Running SwiftFormat\.{3}\r|\(lint mode - no files will be changed\.\)\r|Reading (?:config|swift-version) file at .*|\x1b\[32mSwiftFormat completed in \d+\.\d+s\.\x1b\[0m\r|0/\d+ files require formatting\.\r' || true) - ((exit_code |= "${?}")) + ((exit_code |= ${?})) printf -- $'--> ๐Ÿฆ… %s swiftlint\n' "${source}" - swiftlint --strict --quiet "${source}" 2> \ - >((grep -vxF $'warning: Configuration option \'allow_multiline_func\' in \'opening_brace\' rule is deprecated. Use the option \'ignore_multiline_function_signatures\' instead.' || true) >&2) - ((exit_code |= "${?}")) + swiftlint --strict --quiet "${source}" + ((exit_code |= ${?})) done -printf -- $'--> ๐Ÿš Bash shellcheck\n' -shellcheck --shell=bash script/* -((exit_code |= "${?}")) - -printf -- $'--> ๐Ÿ“œ Bash shfmt\n' -shfmt \ - --diff \ - --list \ - --indent 2 \ - --case-indent \ - contrib/ script/ -((exit_code |= "${?}")) +printf -- $'--> ๐Ÿš ShellCheck\n' +shellcheck -s bash -o all -e SC1088,SC2296,SC2301,SC2312 -a -P SCRIPTDIR script/**/*(.) +((exit_code |= ${?})) printf -- $'--> ใ€ฝ๏ธ Markdown\n' -markdownlint --config .markdownlint.json .github . -((exit_code |= "${?}")) - -printf -- $'--> ๐ŸŒณ Git\n' -PAGER='cat' git diff --check -((exit_code |= "${?}")) +markdownlint --config .markdownlint.json . docs +((exit_code |= ${?})) -printf -- $'--> ๐Ÿ–Š YAML\n' +printf -- $'--> ๐Ÿ“ YAML\n' yamllint . -((exit_code |= "${?}")) +((exit_code |= ${?})) + +printf -- $'--> ๐ŸŒณ Git\n' +git diff --check +((exit_code |= ${?})) printf -- $'--> ๐ŸŒ€ Periphery\n' script -q /dev/null periphery scan --strict --quiet --disable-update-check | (grep -vxE '(?:\x1b\[0;1;32m|\^D\x08{2})\* (?:\x1b\[0;0m\x1b\[0;1m)?No unused code detected\.(?:\x1b\[0;0m)?\r' || true) -((exit_code |= "${?}")) +((exit_code |= ${?})) exit "${exit_code}" diff --git a/script/package b/script/package index 30df8f8c9..1c1bba9a0 100755 --- a/script/package +++ b/script/package @@ -1,43 +1,57 @@ -#!/bin/bash -e +#!/bin/zsh -Ndefgku # # script/package # mas # -# Builds macOS installer component and distribution packages. +# Builds .pkg installer. # -BUILD_DIR="$PWD/.build" -COMPONENT_PACKAGE="$BUILD_DIR/mas_components.pkg" -DISTRIBUTION_PACKAGE="$BUILD_DIR/mas.pkg" +. "${0:a:h}/_setup_script" -IDENTIFIER="com.mphys.mas-cli" +script/build --arch arm64 --arch x86_64 -# Distribution package definition -# https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html -DISTRIBUTION_PLIST="Package/Distribution.plist" +build_dir=.build +destination_root="${build_dir}/destination" +version="$(script/version)" -# Destination for install root -DSTROOT=.build/distributions -script/install "$DSTROOT/usr/local" --universal +printf $'==> ๐Ÿ“ฆ Assembling installer package for mas %s\n' "${version}" -MAS_VERSION=$(script/version) +ditto -v "${build_dir}/apple/Products/Release/mas" "${destination_root}/mas" -echo "==> ๐Ÿ“ฆ Assemble an installer package" - -# Assemble macOS installer component package (aka "product archive"). pkgbuild \ - --identifier "$IDENTIFIER" \ - --install-location "/" \ - --version "$MAS_VERSION" \ - --root "$DSTROOT" \ - "$COMPONENT_PACKAGE" + --identifier com.mphys.mas-cli \ + --install-location /usr/local/bin \ + --version "${version}" \ + --root "${destination_root}" \ + "${build_dir}/mas_components.pkg" -# Build distribution package (aka "product archive"). Not sure why, but this is how Carthage does it. -# https://github.com/Carthage/Carthage/blob/master/Makefile#L69 +# shellcheck disable=SC1036 productbuild \ - --distribution "$DISTRIBUTION_PLIST" \ - --package-path "$BUILD_DIR" \ - "$DISTRIBUTION_PACKAGE" - -echo "==> ๐Ÿ”ข File Hash" -shasum -a 256 "$DISTRIBUTION_PACKAGE" + --distribution =(cat <<'END' + + + + + + #mas_components.pkg + + + + + + + + + + + + + + + + + +END +) \ + --package-path "${build_dir}" \ + "${build_dir}/mas-${version}.pkg" diff --git a/script/package_install b/script/package_install deleted file mode 100755 index 3419135c9..000000000 --- a/script/package_install +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -e -# -# script/package_install -# mas -# -# Installs the mas distribution package. Requires sudo access. -# - -IDENTIFIER=com.mphys.mas-cli - -echo "==> ๐Ÿ“ฒ Installing mas" - -sudo installer \ - -pkg .build/mas.pkg \ - -target / - -pkgutil --pkg-info "$IDENTIFIER" - -pkgutil --files "$IDENTIFIER" diff --git a/script/test b/script/test index 7c5f41cd9..5f3a5e1aa 100755 --- a/script/test +++ b/script/test @@ -1,4 +1,4 @@ -#!/bin/bash -eu +#!/bin/zsh -Ndefgku # # script/test # mas @@ -6,13 +6,11 @@ # Runs mas tests. # -mas_dir="$(readlink -fn "$(dirname "${BASH_SOURCE:-"${0}"}")/..")" +. "${0:a:h}/_setup_script" -if ! cd -- "${mas_dir}"; then - printf $'Error: Could not cd into mas directory: %s\n' "${mas_dir}" >&2 - exit 1 -fi +printf $'==> โœ… Testing mas %s\n' "$(script/version)" -printf $'==> โœ… Testing mas (%s)\n' "$(script/version --write)" +script/generate_version_info_for_swift -swift test +script -q /dev/null swift test | + (grep -vxE $'Test Suite \'.+\' (?:started|passed) at \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}\\.?\\r|Test Case \'-\\[.+\\]\' (?:started|passed \\(\\d+\\.\\d+ seconds\\))\\.\\r|\\t Executed \\d+ tests?, with 0 failures \\(0 unexpected\\) in \\d+\\.\\d+ \\(\\d+\\.\\d+\\) seconds\\r' || true) diff --git a/script/uninstall b/script/uninstall deleted file mode 100755 index e672d2832..000000000 --- a/script/uninstall +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -e -# -# script/uninstall -# mas -# -# Removes mas from PREFIX. -# - -# Override default prefix path with optional 1st arg -if test -n "$1"; then - PREFIX="$1" -else - PREFIX=$(brew --prefix) -fi - -echo "==> ๐Ÿ”ฅ Uninstalling mas from $PREFIX" - -trash -F "$PREFIX/bin/mas" || true diff --git a/script/update_headers b/script/update_headers index 0fabab6ac..b669feea7 100755 --- a/script/update_headers +++ b/script/update_headers @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/zsh -Ndefgku # # script/update_headers # mas @@ -6,27 +6,19 @@ # Runs class-dump to generate headers for Apple private frameworks. # -main() { - check_class_dump - extract_private_framework_headers "CommerceKit" - extract_private_framework_headers "StoreFoundation" -} +. "${0:a:h}/_setup_script" -check_class_dump() { - # command: usage: command [-pVv] command [arg ...] - if ! command -v class-dump; then - echo "class-dump is not installed." >&2 - echo "Download from http://stevenygard.com/projects/class-dump/" >&2 - exit 1 - fi -} +if ! command -v class-dump >/dev/null; then + printf $'class-dump is not installed.\n\nDownload, build & install mas fork of class-dump from https://github.com/mas-cli/class-dump\n' >&2 + exit 1 +fi extract_private_framework_headers() { - local framework_name="$1" - shift + local framework_name="${1}" local directory="Sources/PrivateFrameworks/${framework_name}" - mkdir -p "$directory" - class-dump -Ho "$directory" "/System/Library/PrivateFrameworks/${framework_name}.framework" + mkdir -p "${directory}" + class-dump -Ho "${directory}" "/System/Library/PrivateFrameworks/${framework_name}.framework" } -main +extract_private_framework_headers CommerceKit +extract_private_framework_headers StoreFoundation diff --git a/script/version b/script/version index 73b1464cb..f5369b270 100755 --- a/script/version +++ b/script/version @@ -1,30 +1,11 @@ -#!/bin/bash -eu +#!/bin/zsh -Ndefgku # # script/version # mas # -# Displays the current marketing version of mas. +# Displays the mas version. # -mas_dir="$(readlink -fn "$(dirname "${BASH_SOURCE:-"${0}"}")/..")" +. "${0:a:h}/_setup_script" -if ! cd -- "${mas_dir}"; then - printf $'Error: Could not cd into mas directory: %s\n' "${mas_dir}" >&2 - exit 1 -fi - -if [[ -z "${MAS_VERSION:-}" ]] && git describe >/dev/null 2>&1; then - # Use last tag if MAS_VERSION environment variable is unset or empty - MAS_VERSION=$(git describe --abbrev=0 --tags 2>/dev/null || true) -fi -echo "${MAS_VERSION#v}" - -if [[ "${#}" -ge 1 && "${1}" == '--write' ]]; then - # Write new version into swift package - cat <Sources/mas/Package.swift -/// Generated by \`script/version\`. -enum Package { - static let version = "${MAS_VERSION#v}" -} -EOF -fi +printf $'%s\n' "${"$(git describe --tags 2>/dev/null)"#v}" diff --git a/script/version_bump b/script/version_bump deleted file mode 100755 index 10b22aadc..000000000 --- a/script/version_bump +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash -eu -# -# script/version_bump -# mas -# -# Increments the marketing version of mas. -# - -mas_dir="$(readlink -fn "$(dirname "${BASH_SOURCE:-"${0}"}")/..")" - -if ! cd -- "${mas_dir}"; then - printf $'Error: Could not cd into mas directory: %s\n' "${mas_dir}" >&2 - exit 1 -fi - -LOCAL_MAS_FORMULA_PATH="Homebrew/mas.rb" -LOCAL_TAP_FORMULA_PATH="Homebrew/mas-tap.rb" -SWIFT_PACKAGE="Sources/mas/Package.swift" - -function usage { - echo "Usage: version_bump v0.0 [sha1_hash]" - echo "- existing tag name" - echo "- sha will be inferred from the given tag if not provided" - exit 1 -} - -if [[ $# -lt 1 ]]; then - usage -fi - -# arg 1 - version tag -MAS_VERSION="${1}" - -# arg 2 - revision (commit hash) -if [[ "${#}" -ge 2 ]]; then - REVISION="${2}" -else - REVISION=$(git rev-parse "${MAS_VERSION}") -fi - -echo "MAS_VERSION: ${MAS_VERSION}" -echo "REVISION: ${REVISION}" - -# Write new version into swift package -cat <"${SWIFT_PACKAGE}" -/// Generated by \`script/version_bump\`. -enum Package { - static let version = "${MAS_VERSION#v}" -} -EOF - -echo -cat "${SWIFT_PACKAGE}" - -# Write new version into brew formulae -for file in ${LOCAL_MAS_FORMULA_PATH} ${LOCAL_TAP_FORMULA_PATH}; do - echo "${file}" - sd '( +tag: +)"[^"]+"' "\$1\"${MAS_VERSION}\"" "${file}" - sd '( +revision: +)"[^"]+"' "\$1\"${REVISION}\"" "${file}" - sd '( +root_url "https://github.com/mas-cli/mas/releases/download/).+' "\${1}${MAS_VERSION}\"" "${file}" -done