From bb85581df054d64f108ee6916fc5196bea93055c Mon Sep 17 00:00:00 2001 From: Andrew Janke Date: Thu, 3 Aug 2017 00:41:51 -0400 Subject: [PATCH] brew deps: add --include-requirements --- Library/Homebrew/cmd/deps.rb | 134 ++++++++++++++++++++++++++--------- completions/zsh/_brew | 10 ++- docs/Manpage.md | 13 +++- manpages/brew-cask.1 | 2 +- manpages/brew.1 | 16 +++-- 5 files changed, 130 insertions(+), 45 deletions(-) diff --git a/Library/Homebrew/cmd/deps.rb b/Library/Homebrew/cmd/deps.rb index bbf0c1b0b4409..de7aa4a51203d 100644 --- a/Library/Homebrew/cmd/deps.rb +++ b/Library/Homebrew/cmd/deps.rb @@ -1,4 +1,4 @@ -#: * `deps` [`--1`] [`-n`] [`--union`] [`--full-name`] [`--installed`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] : +#: * `deps` [`--1`] [`-n`] [`--union`] [`--full-name`] [`--installed`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] [`--include-requirements`] : #: Show dependencies for . When given multiple formula arguments, #: show the intersection of dependencies for . #: @@ -19,15 +19,22 @@ #: . To include the `:build` type dependencies, pass `--include-build`. #: Similarly, pass `--include-optional` to include `:optional` dependencies. #: To skip `:recommended` type dependencies, pass `--skip-recommended`. +#: To include requirements in addition to dependencies, pass `--include-requirements`. #: -#: * `deps` `--tree` [] (|`--installed`): +#: * `deps` `--tree` [`--1`] [] [`--annotate`] (|`--installed`): #: Show dependencies as a tree. When given multiple formula arguments, output #: individual trees for every formula. #: +#: If `--1` is passed, only one level of children is displayed. +#: #: If `--installed` is passed, output a tree for every installed formula. #: #: The placeholder is any combination of options `--include-build`, -#: `--include-optional`, and `--skip-recommended` as documented above. +#: `--include-optional`, `--skip-recommended`, and `--include-requirements` as +#: documented above. +#: +#: If `--annotate` is passed, the build, optional, and recommended dependencies +#: are marked as such in the output. #: #: * `deps` [] (`--installed`|`--all`): #: Show dependencies for installed or all available formulae. Every line of @@ -37,6 +44,10 @@ #: The placeholder is any combination of options `--include-build`, #: `--include-optional`, and `--skip-recommended` as documented above. +# The undocumented `--for-each` option will switch into the mode used by `deps --all`, +# but only list dependencies for specified formula, one specified formula per line. +# This is used for debugging the `--installed`/`--all` display mode. + # encoding: UTF-8 require "formula" @@ -52,20 +63,26 @@ def deps all?: ARGV.include?("--all"), topo_order?: ARGV.include?("-n"), union?: ARGV.include?("--union"), + for_each?: ARGV.include?("--for-each"), ) - if mode.installed? && mode.tree? - puts_deps_tree Formula.installed + if mode.tree? + if mode.installed? + puts_deps_tree Formula.installed, !ARGV.one? + else + raise FormulaUnspecifiedError if ARGV.named.empty? + puts_deps_tree ARGV.formulae, !ARGV.one? + end elsif mode.all? puts_deps Formula - elsif mode.tree? - raise FormulaUnspecifiedError if ARGV.named.empty? - puts_deps_tree ARGV.formulae elsif ARGV.named.empty? raise FormulaUnspecifiedError unless mode.installed? puts_deps Formula.installed + elsif mode.for_each? + puts_deps ARGV.formulae else all_deps = deps_for_formulae(ARGV.formulae, !ARGV.one?, &(mode.union? ? :| : :&)) + all_deps = condense_requirements(all_deps) all_deps = all_deps.select(&:installed?) if mode.installed? all_deps = all_deps.map(&method(:dep_display_name)).uniq all_deps.sort! unless mode.topo_order? @@ -73,24 +90,59 @@ def deps end end - def dep_display_name(d) - ARGV.include?("--full-name") ? d.to_formula.full_name : d.name + def condense_requirements(deps) + if ARGV.include?("--include-requirements") + deps + else + deps.map do |dep| + if dep.is_a? Dependency + dep + elsif dep.default_formula? + dep.to_dependency + end + end.compact + end + end + + def dep_display_name(dep) + str = if dep.is_a? Requirement + if ARGV.include?("--include-requirements") + if dep.default_formula? + ":#{dep.display_s} (#{dep_display_name(dep.to_dependency)})" + else + ":#{dep.display_s}" + end + elsif dep.default_formula? + dep_display_name(dep.to_dependency) + else + # This shouldn't happen, but we'll put something here to help debugging + "::#{dep.name}" + end + else + ARGV.include?("--full-name") ? dep.to_formula.full_name : dep.name + end + if ARGV.include?("--annotate") + str = "#{str} [build]" if dep.build? + str = "#{str} [optional" if dep.optional? + str = "#{str} [recommended]" if dep.recommended? + end + str end def deps_for_formula(f, recursive = false) includes = [] ignores = [] - if ARGV.include? "--include-build" + if ARGV.include?("--include-build") includes << "build?" else ignores << "build?" end - if ARGV.include? "--include-optional" + if ARGV.include?("--include-optional") includes << "optional?" else ignores << "optional?" end - ignores << "recommended?" if ARGV.include? "--skip-recommended" + ignores << "recommended?" if ARGV.include?("--skip-recommended") if recursive deps = f.recursive_dependencies do |dependent, dep| @@ -120,7 +172,7 @@ def deps_for_formula(f, recursive = false) end end - deps + reqs.select(&:default_formula?).map(&:to_dependency) + deps + reqs.to_a end def deps_for_formulae(formulae, recursive = false, &block) @@ -129,41 +181,55 @@ def deps_for_formulae(formulae, recursive = false, &block) def puts_deps(formulae) formulae.each do |f| - deps = deps_for_formula(f).sort_by(&:name).map(&method(:dep_display_name)) + deps = deps_for_formula(f) + deps = condense_requirements(deps) + deps = deps.sort_by(&:name).map(&method(:dep_display_name)) puts "#{f.full_name}: #{deps.join(" ")}" end end - def puts_deps_tree(formulae) + def puts_deps_tree(formulae, recursive = false) formulae.each do |f| - puts "#{f.full_name} (required dependencies)" - recursive_deps_tree(f, "") + puts f.full_name + @dep_stack = [] + recursive_deps_tree(f, "", recursive) puts end end - def recursive_deps_tree(f, prefix) - reqs = f.requirements.select(&:default_formula?) - deps = f.deps.default - max = reqs.length - 1 - reqs.each_with_index do |req, i| - chr = if i == max && deps.empty? + def recursive_deps_tree(f, prefix, recursive) + reqs = f.requirements + deps = f.deps + dependables = reqs + deps + dependables = dependables.reject(&:optional?) unless ARGV.include?("--include-optional") + dependables = dependables.reject(&:build?) unless ARGV.include?("--include-build") + dependables = dependables.reject(&:recommended?) if ARGV.include?("--skip-recommended") + max = dependables.length - 1 + @dep_stack.push f.name + dependables.each_with_index do |dep, i| + next if !ARGV.include?("--include-requirements") && dep.is_a?(Requirement) && !dep.default_formula? + tree_lines = if i == max "└──" else "├──" end - puts prefix + "#{chr} :#{dep_display_name(req.to_dependency)}" - end - max = deps.length - 1 - deps.each_with_index do |dep, i| - chr = if i == max - "└──" + display_s = "#{tree_lines} #{dep_display_name(dep)}" + is_circular = @dep_stack.include?(dep.name) + display_s = "#{display_s} (CIRCULAR DEPENDENCY)" if is_circular + puts "#{prefix}#{display_s}" + next if !recursive || is_circular + prefix_addition = if i == max + " " else - "├──" + "│ " + end + if dep.is_a?(Requirement) && dep.default_formula? + recursive_deps_tree(Formulary.factory(dep.to_dependency.name), prefix + prefix_addition, true) + end + if dep.is_a? Dependency + recursive_deps_tree(Formulary.factory(dep.name), prefix + prefix_addition, true) end - prefix_ext = (i == max) ? " " : "│ " - puts prefix + "#{chr} #{dep_display_name(dep)}" - recursive_deps_tree(Formulary.factory(dep.name), prefix + prefix_ext) end + @dep_stack.pop end end diff --git a/completions/zsh/_brew b/completions/zsh/_brew index 61dc26b42d063..bc88f402b56cd 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -284,8 +284,8 @@ _brew_create() { ':url:_urls' } -# brew deps [--1] [-n] [--union] [--full-name] [--installed] [--include-build] [--include-optional] [--skip-recommended] formulae -# brew deps --tree [filters] (formulae|--installed) +# brew deps [--1] [-n] [--union] [--full-name] [--installed] [--include-build] [--include-optional] [--skip-recommended] [--include-requirements] formulae +# brew deps --tree [--1] [filters] (formulae|--installed) # brew deps [filters] (--installed|--all) # The filters placeholder is any combination of options --include-build, --include-optional, and --skip-recommended as documented above. _brew_deps() { @@ -294,6 +294,7 @@ _brew_deps() { '--include-build[include \:build dependencies]' \ '--include-optional[include \:optional dependencies]' \ '--skip-recommended[skip \:recommended type dependencies]' \ + '--include-requirements[include requirements]' \ '--1[only show dependencies one level down, instead of recursing]' \ '-n[show dependencies in topological order]' \ '--union[show the union of dependencies for formulae, instead of the intersection]' \ @@ -303,6 +304,11 @@ _brew_deps() { - tree-deps \ '--tree[show dependencies as a tree]' \ '(*)--installed[show dependencies for all installed formulae]' \ + '--include-build[include \:build dependencies]' \ + '--include-optional[include \:optional dependencies]' \ + '--skip-recommended[skip \:recommended type dependencies]' \ + '--include-requirements[include requirements]' \ + '--1[only show dependencies one level down, instead of recursing]' \ '(--installed)*:formulae:__brew_formulae' \ - installed-all \ '--include-build[include \:build dependencies]' \ diff --git a/docs/Manpage.md b/docs/Manpage.md index 49f6bb5aee6d3..1ec9493954f70 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -77,7 +77,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note a bug report, you will likely be asked for this information if you do not provide it. - * `deps` [`--1`] [`-n`] [`--union`] [`--full-name`] [`--installed`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] `formulae`: + * `deps` [`--1`] [`-n`] [`--union`] [`--full-name`] [`--installed`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] [`--include-requirements`] `formulae`: Show dependencies for `formulae`. When given multiple formula arguments, show the intersection of dependencies for `formulae`. @@ -98,15 +98,22 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note `formulae`. To include the `:build` type dependencies, pass `--include-build`. Similarly, pass `--include-optional` to include `:optional` dependencies. To skip `:recommended` type dependencies, pass `--skip-recommended`. + To include requirements in addition to dependencies, pass `--include-requirements`. - * `deps` `--tree` [`filters`] (`formulae`|`--installed`): + * `deps` `--tree` [`--1`] [`filters`] [`--annotate`] (`formulae`|`--installed`): Show dependencies as a tree. When given multiple formula arguments, output individual trees for every formula. + If `--1` is passed, only one level of children is displayed. + If `--installed` is passed, output a tree for every installed formula. The `filters` placeholder is any combination of options `--include-build`, - `--include-optional`, and `--skip-recommended` as documented above. + `--include-optional`, `--skip-recommended`, and `--include-requirements` as + documented above. + + If `--annotate` is passed, the build, optional, and recommended dependencies + are marked as such in the output. * `deps` [`filters`] (`--installed`|`--all`): Show dependencies for installed or all available formulae. Every line of diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1 index f11d48c094216..763d78ebe6c17 100644 --- a/manpages/brew-cask.1 +++ b/manpages/brew-cask.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BREW\-CASK" "1" "July 2017" "Homebrew" "brew-cask" +.TH "BREW\-CASK" "1" "August 2017" "Homebrew" "brew-cask" . .SH "NAME" \fBbrew\-cask\fR \- a friendly binary installer for macOS diff --git a/manpages/brew.1 b/manpages/brew.1 index 2d8ba3f09f871..46a1d9bd92be5 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BREW" "1" "July 2017" "Homebrew" "brew" +.TH "BREW" "1" "August 2017" "Homebrew" "brew" . .SH "NAME" \fBbrew\fR \- The missing package manager for macOS @@ -88,7 +88,7 @@ If \fB\-\-quiet\fR is passed, list only the names of commands without the header Show Homebrew and system configuration useful for debugging\. If you file a bug report, you will likely be asked for this information if you do not provide it\. . .TP -\fBdeps\fR [\fB\-\-1\fR] [\fB\-n\fR] [\fB\-\-union\fR] [\fB\-\-full\-name\fR] [\fB\-\-installed\fR] [\fB\-\-include\-build\fR] [\fB\-\-include\-optional\fR] [\fB\-\-skip\-recommended\fR] \fIformulae\fR +\fBdeps\fR [\fB\-\-1\fR] [\fB\-n\fR] [\fB\-\-union\fR] [\fB\-\-full\-name\fR] [\fB\-\-installed\fR] [\fB\-\-include\-build\fR] [\fB\-\-include\-optional\fR] [\fB\-\-skip\-recommended\fR] [\fB\-\-include\-requirements\fR] \fIformulae\fR Show dependencies for \fIformulae\fR\. When given multiple formula arguments, show the intersection of dependencies for \fIformulae\fR\. . .IP @@ -107,17 +107,23 @@ If \fB\-\-full\-name\fR is passed, list dependencies by their full name\. If \fB\-\-installed\fR is passed, only list those dependencies that are currently installed\. . .IP -By default, \fBdeps\fR shows required and recommended dependencies for \fIformulae\fR\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR\. Similarly, pass \fB\-\-include\-optional\fR to include \fB:optional\fR dependencies\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\. +By default, \fBdeps\fR shows required and recommended dependencies for \fIformulae\fR\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR\. Similarly, pass \fB\-\-include\-optional\fR to include \fB:optional\fR dependencies\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\. To include requirements in addition to dependencies, pass \fB\-\-include\-requirements\fR\. . .TP -\fBdeps\fR \fB\-\-tree\fR [\fIfilters\fR] (\fIformulae\fR|\fB\-\-installed\fR) +\fBdeps\fR \fB\-\-tree\fR [\fB\-\-1\fR] [\fIfilters\fR] [\fB\-\-annotate\fR] (\fIformulae\fR|\fB\-\-installed\fR) Show dependencies as a tree\. When given multiple formula arguments, output individual trees for every formula\. . .IP +If \fB\-\-1\fR is passed, only one level of children is displayed\. +. +.IP If \fB\-\-installed\fR is passed, output a tree for every installed formula\. . .IP -The \fIfilters\fR placeholder is any combination of options \fB\-\-include\-build\fR, \fB\-\-include\-optional\fR, and \fB\-\-skip\-recommended\fR as documented above\. +The \fIfilters\fR placeholder is any combination of options \fB\-\-include\-build\fR, \fB\-\-include\-optional\fR, \fB\-\-skip\-recommended\fR, and \fB\-\-include\-requirements\fR as documented above\. +. +.IP +If \fB\-\-annotate\fR is passed, the build, optional, and recommended dependencies are marked as such in the output\. . .TP \fBdeps\fR [\fIfilters\fR] (\fB\-\-installed\fR|\fB\-\-all\fR)