Add the ability to 'add' `mas` dependencies to Brewfile
boldandbrad opened this issue · comments
Goal
Add the ability to add Brewfile lines of the following format: mas "name", id: 12345678
Assumptions
- The "name" value itself does not matter to
mas
for install, only the "id" does (mas install [ID]
) - Recent versions of macOS prohibit
mas
from installing applications that have not been previously purchased/installed on a Mac by the active Apple ID - mas known issues
Potential Command Structures
-
brew add --mas [PARAM(S)]
- Syntax is consistent with
brew add --cask/formula
- Requires refactor of existing code to implement
- Syntax is consistent with
-
brew mas [PARAM(S)]
- Not consistent with existing structure
- Could require inconsistent implementation of eventual
brew drop
/brew mas drop
- Does not require refactor of existing code to implement
Potential Params
-
Only [ID]
- Easy for user to obtain via
mas list
if it was previously installed (Assumption 2) brew add
runsmas info [ID]
to get the app's "name" automatically
- Easy for user to obtain via
-
Only [NAME]
- Easy for user to obtain via
mas list
if it was previously installed (Assumption 2) brew add
runsmas search [NAME]
to get the app's "id" automatically - might require parsing and user input if a direct match is not found
- Easy for user to obtain via
-
Both [NAME:ID]
- Easy for user to obtain both via
mas list
if it was previously installed (Assumption 2) brew add
does not need to invokemas info
ormas search
- Could make it difficult to support adding multiple mas dependencies at once (if we want to support that)
- Easy for user to obtain both via
Inspiration/Reference
brew bundle dump
implementation formas
dependencies: mac_app_store_dumper_spec.rb- Initial discussion/context in #1
Thank you so much for this detailed write-up! This is very helpful.
In addition, dumping mas
apps is also implemented here: mac_app_store_dumper.rb
I'm not quite sure what the spec file is (it might be test cases?) but I tend to find that the implementations normally are in the lib/
directory.
I think all three ways of specifying mas
applications can work with the brew add
command in general alongside formulae and casks by using a bit of special syntax. Since the colon (:
) doesn't appear in any formula names, it's a perfect character to indicate a mas
app.
The form of a mas
app would be ID:NAME
, or /^\d+:[^:]+$/
as a regular expression. In addition, we could also accept different segments of the full syntax, like :NAME
to search for the id by name, or ID:
to let the name be automatically filled in. And because the only formula/cask that is just numbers is the cask 7777
, the trailing colon at the end of the ID could be optional, with priority being for the formulae and casks first.
For example, this line would add the mas app with the ID 1482454543
, the mas apps named xcode
and bear
, and the casks 7777
and firefox
to the Brewfile:
brew add 1482454543 497799835:xcode :bear 7777 firefox
To add the mas app with an ID of 7777
instead of the cask, both brew add --mas 7777
and brew add 7777:
would work.
Now, this is just one way of solving it. The advantage of using the colon separator this way is that it allows for there to be no confusion about what is meant to be a mas
app, and to me, removing sections of the full ID:NAME
format to have them be filled in feels natural. It also allows for typing brew add ID
in all cases except for app 7777, which doesn't actually appear to be a valid app.
If you have any different ideas or improvements to this one, please let me know. Also, I swapped the order of the ID
and NAME
just because :firefox
looked better than firefox:
to me, and because it kind of makes sense for the most important bit of information (the id) to come first. Tell me if you preferred it the other way around.
I like your suggested implementation for a few reasons:
- Supports adding multiple items to the Brewfile at once (and across all types)
- Consistent with the current structure
- Easy for the user as the tool handles multiple cases automatically if the user doesn't have all pieces of information available
- The order of ID:NAME actually makes more sense considering that's consistent with how
mas list
andmas search
output
The only other things I'll note are...
NAME
should support being surrounded in quotes. Some app names in the App Store have spaces in them. Although the value doesn't matter formas
orbrewfile
, if people prefer the exact name, or copy it frommas
output, they will need to wrap it in quotes so it doesn't get read as multiple formulae ->brew add :"Canary Mail"
- Although I don't personally use Whalebrew, we might want to check to make sure that our regex implementation wouldn't make it impossible or difficult to add whalebrew support later if others come along with that need. I can do some research on this if you like.
After digging a little bit through the whalebrew repo, I don't think we need to worry about our regex. It seems like whalebrew formulae don't include :
and almost all of them start with whalebrew/
which would be fairly easy to catch aside from potential conflict with the homebrew whalebrew formulae itself. Either way, it shouldn't be a concern for this issue.
Regarding supporting names in quotes, I believe the shell itself can already handle that. By putting single quotes, double quotes, or escaping spaces, the name will be interpreted as one name once it is received by the argument parser.
For example, with current functionality, typing any of these:
brew add :"Canary Mail"
brew add :'Canary Mail'
brew add :Canary\ Mail
brew add :Canary' 'Mail
brew add ':Canary Mail'
Outputs the same exact error message:
Error: No available formula with the name ":canary mail".
Built-in commands like brew install
also behave in the same way.