Skip to content
This repository has been archived by the owner on Jul 4, 2023. It is now read-only.

Implement brew desc, with a cache #42281

Closed
wants to merge 13 commits into from
Closed

Implement brew desc, with a cache #42281

wants to merge 13 commits into from

Conversation

hivehand
Copy link
Contributor

This is an attempt to recreate @telemachus’s brew desc tool, using the desc component now built into formulae. Like the original brew desc, it lets you look up formulae either by their exact names, or by searching through some combination of name and description.

Notes:

  • It follows the suggestion made by @mistydemeo, in the discussion over the pull request that added desc to formulae, and uses a cache for performance.
  • Said cache tries to be “pay-as-you-go”: the cache isn't created, or updated, until you either explicitly do so with brew desc --cache, or perform a search. This allows people who don’t expect to use brew desc to avoid paying ~5 extra seconds with every brew update.
  • A slight performance tweak to utils.rb’s maximum-length-determination logic, with input from @bfontaine, came along for the ride.

Caveats:

  • I have almost no personal experience with Kegs or Casks, and so can’t guarantee that desc and the cache work properly with them.
  • I’m not well-versed with brew’s model for handling ARGV, so it’s possible that I’m making a lot of unnecessary noise in the desc.rb command handling.

Open Questions:

  • brew search --desc is exactly equivalent to brew desc -d. I’m not sure it makes sense to preserve both, particularly since the former was never documented, but for the time being I’ve rewritten it to take advantage of the cache.
  • The cache-generation code is completely silent. I don’t know if we want to notify the user to the effect that “It’s OK! Something’s actually happening!” when the first attempt to run brew desc takes several seconds.

Feedback is more than welcome.

@dunn dunn added the features label Jul 31, 2015
@dunn
Copy link
Contributor

dunn commented Jul 31, 2015

The tests are failing on Mountain Lion—are you using any Ruby that's not valid in 1.8?

@hivehand
Copy link
Contributor Author

That’s entirely possible. I apologize. I’ll install 1.8.7 and see about finding and fixing the issue. (Off the top of my head, I'm guessing that it might be due to my use of proc rather than Proc.new, but we’ll see.)

@hivehand
Copy link
Contributor Author

Aieeee, no. Close, but the actual culprit was my using { <sym_name>: <value> } instead of { :<sym_name> => <value> }. I’ll fix that, and update after proper testing.

def desc
options = ARGV.options_only

if options.include?("--decache")
Copy link
Contributor

Choose a reason for hiding this comment

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

You can drop the parentheses here.

Copy link
Member

Choose a reason for hiding this comment

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

--decache feels bit jargon.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was meant to be either a portmanteau of “delete” and “cache”, or analogous to “decompress”. I’m open to clearer suggestions, though. --delete_cache?

Copy link
Contributor

Choose a reason for hiding this comment

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

I’d prefer not to mix underscores and hyphens, so maybe --delete-cache.

@MikeMcQuaid
Copy link
Member

@hivehand Can you show the output of time brew readall and time brew desc --cache? Thanks!

descriptions (`-d`) for `<pattern>`. `<pattern>` is by default interpreted
as a literal string; if flanked by slashes, it is instead interpreted as a
regular expression. Formula descriptions are cached, and the cache is
created on the first search, making it slower than succeeding ones.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don’t think “succeeding” is the good word here 😉

Copy link
Contributor

Choose a reason for hiding this comment

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

How about "subsequent" or "later"?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree that “succeeding” is not the good word. I like “subsequent”: I’ll use that.

@telemachus
Copy link
Contributor

@hivehand Thanks for doing this!

require 'descriptions'
require 'cmd/search'

USAGE =<<EOM
Copy link
Member

Choose a reason for hiding this comment

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

Since none of internal commands has a usage message. I think we should drop this. Manpage should be sufficiency.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough. I will make it behave like brew deps just raise a FormulaUnspecifiedError instead.

@MikeMcQuaid
Copy link
Member

I recommend this be profiled with something like ruby-prof --printer=call_stack --file=call_stack.html -- brew desc --cache to try and tweak performance.

@hivehand
Copy link
Contributor Author

The first benchmarks, as requested by @MikeMcQuaid:

$ time brew readall

real    0m2.721s
user    0m2.577s
sys 0m0.139s
$ time brew desc --recache

real    0m2.925s
user    0m2.775s
sys 0m0.143s

More to come as soon as I familiarize myself with ruby-prof.

I’ll be addressing and/or replying to specific comments shortly. Thank you all for the careful proofreading and detailed feedback!


matchers = {
:name => proc { |name, desc| name =~ regex },
:desc => proc { |name, desc| desc =~ regex },
Copy link
Contributor

Choose a reason for hiding this comment

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

You can use _ for the parameters you’re no using, e.g. { |_, desc| desc =~ regex }.

@hivehand
Copy link
Contributor Author

I just pushed an update. I believe that this addresses all issues raised and suggestions made, with the exception of @bfontaine’s proposal that I use case instead of a hash of procs when performing a search. (I’m not yet sure that I properly understand how to use case concisely here.)

On the profiling front,

ruby-prof --printer=call_stack --file=call_stack.html -- brew desc --cache

fails with

/usr/local/lib/ruby/gems/2.2.0/gems/ruby-prof-0.15.8/lib/ruby-prof/compatibility.rb:104:in `load': cannot load such file -- brew (LoadError)
    from /usr/local/lib/ruby/gems/2.2.0/gems/ruby-prof-0.15.8/lib/ruby-prof/compatibility.rb:104:in `start_script'
    from /usr/local/lib/ruby/gems/2.2.0/gems/ruby-prof-0.15.8/bin/ruby-prof:292:in `run'
    from /usr/local/lib/ruby/gems/2.2.0/gems/ruby-prof-0.15.8/bin/ruby-prof:340:in `<top (required)>'
    from /usr/local/bin/ruby-prof:23:in `load'
    from /usr/local/bin/ruby-prof:23:in `<main>’

which stands to reason, since brew is a shell script rather than Ruby. I will see if I can teach myself enough ruby-prof to obtain useful results; in the meantime, hints would be welcome.

@xu-cheng
Copy link
Member

xu-cheng commented Aug 1, 2015

@hivehand I wrote a small script to help you profile homebrew.

If you install it with brew tap homebrew/dev-tools. You should be able to run brew prof desc --cache to generate the result.

@MikeMcQuaid
Copy link
Member

Maintainers: please hold off merging this: I haven't had the chance to review it yet but would like it before we merge it.

@cache = {}
CSV.open(CACHE_FILE, 'w') do |csv|
Formula.map do |f|
name, desc = f.name, f.desc
Copy link
Member

Choose a reason for hiding this comment

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

f.full_name

@MikeMcQuaid
Copy link
Member

@hivehand That approach sounds good!

1. Resurrect the late `brew desc` as a means of geting descriptions
   for an arbitrary set of formulae via the command line.
2. Create the Descriptions class to do most of the heavy lifting.
3. Update the man page.
Use traditional Hash-construction notation, and deal with the fact
that Hash#select in Ruby 1.8.7 and earlier returns an Array of
Arrays, instead of a Hash.

While we're here:

- Make `ruby desc` without arguments print usage, rather than all
  formulae.
- Rename --cache to --recache, and update the manual accordingly.
- Sort formulae by name when printing.
- Flag formulae with missing descriptions when printing the list.
- Add zsh autocompletion support.
- Dispose of the verbose usage message.
- Adopt too many tweaks and refinements courtesy of @bfontaine
  to enumerate.
- Replace `--decache` with `--delete-cache` and, for consistency,
  `--recache` with `--create-cache`.
- Update the man page accordingly.
- Use the update report to update only the affected formulae.
- Also, refactor the cache-saving code.
- Also refactor using Filepaths
- Refactor update_cache, splitting cache addition and deletion into
  separate methods. Use those methods to update the cache when tapping
  or untapping.
- Also revise update_cache, and move cache_fresh? while we're at it.
- Realign methods' descriptions with reality.
Also remove the Descriptions::delete_cache method, since nothing now
uses it.
@hivehand
Copy link
Contributor Author

hivehand commented Sep 1, 2015

Apologies in advance if I’m being a pest, but are there any outstanding issues regarding this pull request? The changes have been working well for me, locally, for the past two weeks and change, with minimal impact on performance. I’d still be happy to share prof results, once I know where and in what format to submit them.

@hivehand
Copy link
Contributor Author

hivehand commented Sep 2, 2015

And, of course, a day after my last comment, I discover the newly-added support for formula renaming in update.rb. I’ve added the corresponding support to the description-cache updating logic.

@MikeMcQuaid
Copy link
Member

The diff looks good to me. If @xu-cheng is happy with it as-is then I'll do some more local testing and merge.

@xu-cheng
Copy link
Member

xu-cheng commented Sep 6, 2015

LGTM

searches = {
'-s' => :either,
'-n' => :name,
'-d' => :desc
Copy link
Member

Choose a reason for hiding this comment

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

Would be nice to also have --search, --name etc. here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added. (In the process, I replaced the somewhat convoluted Hash logic with a case statement, which should please @bfontaine. 😉)

@MikeMcQuaid
Copy link
Member

A couple of final nits but otherwise looks and works great for me 👍

Add the '--search', '--name', and '--description' options, and update
bash completion accordingly.
@MikeMcQuaid
Copy link
Member

Thanks for the great work here @hivehand! Merged!

@hivehand
Copy link
Contributor Author

hivehand commented Sep 8, 2015

Thank you, collectively, for the many excellent suggestions and your patience!

@telemachus
Copy link
Contributor

@hivehand Thanks for getting this into brew.

@hivehand
Copy link
Contributor Author

hivehand commented Sep 8, 2015

@telemachus, you’re welcome. Thanks for hopelessly addicting me to formula descriptions in the first place!

@MikeMcQuaid
Copy link
Member

Such a great example of a feature that we couldn't have implemented well in core as a one-off that the community picked up and got it back into core as a full-fledged, improving feature. 👏 to both of you @telemachus, @hivehand.

@hivehand hivehand deleted the redesc branch September 10, 2015 18:17
@Homebrew Homebrew locked and limited conversation to collaborators Jul 10, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants