Skip to content

Support optional JSON output for config, list, lookup/info, outdated & search; improve tabular output#1230

Merged
rgoldberg merged 19 commits intomas-cli:mainfrom
rgoldberg:7.0.0/190-json
Apr 26, 2026
Merged

Support optional JSON output for config, list, lookup/info, outdated & search; improve tabular output#1230
rgoldberg merged 19 commits intomas-cli:mainfrom
rgoldberg:7.0.0/190-json

Conversation

@rgoldberg
Copy link
Copy Markdown
Member

Support optional JSON output for config, list, lookup/info, outdated & search; improve tabular output.

Resolve #190
Resolve #412
Resolve #1091

@rgoldberg rgoldberg added this to the 7.0.0 milestone Apr 22, 2026
@rgoldberg rgoldberg self-assigned this Apr 22, 2026
@rgoldberg rgoldberg force-pushed the 7.0.0/190-json branch 6 times, most recently from b8c8eb5 to 210425a Compare April 22, 2026 04:15
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces native JSON output support for the list, outdated, search, lookup, and config commands. This is achieved through the integration of a new swift-json library and a Zsh wrapper script that uses jq and column for terminal formatting. The implementation includes a significant refactor of the CatalogApp and InstalledApp models to handle metadata key mapping and JSON serialization. Feedback highlights several performance and architectural concerns, including inefficient JSON re-parsing in the outdated command, high memory overhead from storing raw JSON strings in models, and potential performance degradation due to disk I/O during canonical path resolution. Additionally, the review points out the tight coupling created by using a magic file descriptor (FD 3) for communication between the binary and the wrapper script, and the bypass of terminal detection logic via hardcoded ANSI escape sequences.

Comment thread Scripts/mas Outdated
Comment thread Sources/mas/Commands/OptionGroups/OutputFormatOptionGroup.swift
Comment thread Sources/mas/Commands/Outdated.swift Outdated
Comment thread Sources/mas/Models/CatalogApp.swift Outdated
Comment thread Sources/mas/Models/InstalledApp.swift Outdated
Comment thread Sources/mas/Models/InstalledApp.swift Outdated
@mas-cli mas-cli deleted a comment from gemini-code-assist Bot Apr 22, 2026
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
…tiveTo:)`.

Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
…rate expressions.

Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Minor cleanup.

Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
…outdated` & `search`.

Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
@rgoldberg rgoldberg requested a review from a team as a code owner April 25, 2026 23:25
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Apr 25, 2026

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarQube Cloud

@rgoldberg
Copy link
Copy Markdown
Member Author

/gemini review

Besides reviewing all the new code changes, also reply to each open review comment with whether the issue has been resolved.

@gemini-code-assist
Copy link
Copy Markdown

Code Review

Summary

This pull request introduces optional JSON output for several mas commands (config, list, lookup/info, outdated, and search) and improves the existing tabular output. It also includes refactoring to support these changes, such as introducing JSONAST and JSONDecoding dependencies, and updates to the Printer utility.

General Feedback

  • Maintainability: The introduction of JSON.Object and JSONDecodable protocols significantly improves the maintainability of JSON output handling across different commands. The use of Lazy for JSON serialization is a good performance optimization.
  • Correctness: The logic for mapping Apple's JSON keys to more readable names in CatalogApp and InstalledApp is robust and well-implemented using regex-based mapping.
  • Efficiency: The use of OSAllocatedUnfairLock in the Lazy utility ensures thread safety for lazy-loaded JSON strings.

Specific Issues

Sources/mas/Commands/OptionGroups/OutputFormatOptionGroup.swift

  • Severity: medium
  • Issue: The info method uses unsafe and direct file descriptor access (fstat(3, ...)). While this is likely intended to detect if the output is being piped, relying on hardcoded file descriptors can be fragile.
  • Suggestion: Consider using a more robust way to detect if the output is a terminal, such as checking isatty(STDOUT_FILENO) if applicable, or ensuring the file descriptor 3 is explicitly managed.

Sources/mas/Models/CatalogApp.swift

  • Severity: low
  • Issue: The regex-based key mapping is complex. While it works, it might be difficult to debug if Apple changes their JSON structure significantly.
  • Suggestion: Ensure that the regex patterns are well-documented with examples of the transformations they perform to aid future maintainers.

Review Comments Status

As requested, I have reviewed the code changes. Please note that I do not have access to the previous review comments thread to mark them as resolved. If you have specific comments you would like me to address, please provide them here.

@rgoldberg
Copy link
Copy Markdown
Member Author

Sources/mas/Commands/OptionGroups/OutputFormatOptionGroup.swift

  • Severity: medium
  • Issue: The info method uses unsafe and direct file descriptor access (fstat(3, ...)). While this is likely intended to detect if the output is being piped, relying on hardcoded file descriptors can be fragile.
  • Suggestion: Consider using a more robust way to detect if the output is a terminal, such as checking isatty(STDOUT_FILENO) if applicable, or ensuring the file descriptor 3 is explicitly managed.

@gemini-code-assist fstat(3, ...) specifically checks if FD3 is piped, because, if it is, the output is written to FD3. Normal usage of this project's Swift binary will be via a zsh wrapper script that pipes FD3 as necessary. The switch to outputting to stdout if FD3 isn't piped facilitates testing the binary directly without the wrapper & without requiring FD3 to be setup. If FD3 is setup outside of the wrapper, you can still test using FD3 outside the wrapper.

Does that alleviate your concerns? If not, explain what is problematic. Is there some better way to determine if FD3 is piped? Or do you have a problem with even checking if FD3 is piped?

@gemini-code-assist
Copy link
Copy Markdown

Thank you for the clarification. I understand that the fstat(3, ...) check is a deliberate design choice to detect if the output is being piped to the zsh wrapper, which facilitates testing without requiring the wrapper setup.

Given this context, the approach is functional and serves the project's specific testing requirements. I have no further concerns regarding this implementation. Thank you for explaining the rationale behind it.

@rgoldberg rgoldberg merged commit 09f2ce5 into mas-cli:main Apr 26, 2026
10 of 16 checks passed
@rgoldberg rgoldberg deleted the 7.0.0/190-json branch April 26, 2026 01:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create libexec setup script Output column misalignment for certain characters JSON output option

1 participant