git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v5 01/15] Add new git-related helper to contrib

From
Ramkumar Ramachandra <artagnon@gmail.com>
Date
May 19, 2013, 14:40 UTC
Message-ID
<CALkWK0ke-Ns0JCt6LAzWqympWZ=2x3rRHOjnzB9QN7gc2=ckgw@mail.gmail.com>
In-Reply-To
<1368877615-9563-2-git-send-email-felipe.contreras@gmail.com>
Okay, let's look at this part.
Felipe Contreras wrote:
Show 26 quoted lines
> diff --git a/contrib/related/git-related b/contrib/related/git-related
> new file mode 100755
> index 0000000..4f31482
> --- /dev/null
> +++ b/contrib/related/git-related
> @@ -0,0 +1,124 @@
> +#!/usr/bin/env ruby
> +
> +# This script finds people that might be interested in a patch
> +# usage: git related <file>
> +
> +$since = '5-years-ago'
> +$min_percent = 10
> +
> +def fmt_person(name, email)
> +  name ? '%s <%s>' % [name, email] : email
> +end
> +
> +class Commit
> +
> +  attr_reader :persons
> +
> +  def initialize(id)
> +    @id = id
> +    @persons = []
> +  end
Okay, although I'm wondering what id is.
Show 10 quoted lines
> +  def parse(data)
> +    msg = nil
> +    data.each_line do |line|
> +      if not msg
> +        case line
> +        when /^author ([^<>]+) <(\S+)> (.+)$/
> +          @persons << fmt_person($1, $2)
> +        when /^$/
> +          msg = true
> +        end

When there's a blank line, flip the switch and start looking in the commit message. Why though? You're worried that the commit message will contain a line matching /^author ([^<>]+) <(\S+)> (.+)$/? If so, why don't you split('\n', 2), look for the author in the $1 and Whatevered-by in $2?

> +      else
> +        if line =~ /^(Signed-off|Reviewed|Acked)-by: ([^<>]+) <(\S+?)>$/
elif?  Can this be more generic to include Whatevered-by?
> +          @persons << fmt_person($2, $3)

Will $2 ever be nil (from fmt_person)? ie. Why are you checking for the special case " <\S+?>$"?

> +        end
> +      end
> +    end
> +    @persons.uniq!
So you don't care if the person has appeared twice or thrice in the message.
Show 9 quoted lines
> +  end
> +
> +end
> +
> +class Commits
> +
> +  def initialize
> +    @items = {}
> +  end
Okay.
> +  def size
> +    @items.size
> +  end
#size is reminiscent of Array#size and Hash#size.
> +  def each(&block)
> +    @items.each(&block)
> +  end

I can see how you iterate over commits from the code below. However, using #each like this is confusing, because the reader expects #each to be invoked on an Enumerable. So, I have two suggestions:

1. Use block_given? to make sure that #each works even without a block
(just like Enumerator#each).
2. Mixin Enumerable by putting in an 'include Enumerable' after the
class line.  Aside from clarity, you get stuff like #find for free.
> +  def import
>From reading the code below, your calling semantics are: first set

each @items[id] to a new Commit object. import is meant to invoke Commit#parse and set @persons there. Okay.

> +    return if @items.empty?
> +    File.popen(%w[git cat-file --batch], 'r+') do |p|
> +      p.write(@items.keys.join("\n"))
> +      p.close_write
Okay.
> +      p.each do |l|
> +        if l =~ /^(\h{40}) commit (\d+)/
s/l/line/?
Show 11 quoted lines
> +          id, len = $1, $2
> +          data = p.read($2.to_i)
> +          @items[id].parse(data)
> +        end
> +      end
> +    end
> +  end
> +
> +  def get_blame(source, start, len, from)
> +    return if len == 0
> +    len ||= 1

Please don't use ||=. It is notorious for causing confusion in Ruby-land. Hint: it's not exactly equivalent to either len = len || 1 or len || len = 1.

> +    File.popen(['git', 'blame', '--incremental', '-C',
Still no -CCC?
Show 6 quoted lines
> +               '-L', '%u,+%u' % [start, len],
> +               '--since', $since, from + '^',
> +               '--', source]) do |p|
> +      p.each do |line|
> +        if line =~ /^(\h{40})/
> +          id = $1
Use $0 and remove the parens: you're matching the whole line.
> +          @items[id] = Commit.new(id)
Okay.
Show 12 quoted lines
> +        end
> +      end
> +    end
> +  end
> +
> +  def from_patch(file)
> +    from = source = nil
> +    File.open(file) do |f|
> +      f.each do |line|
> +        case line
> +        when /^From (\h+) (.+)$/
> +          from = $1
Okay.
> +        when /^---\s+(\S+)/
> +          source = $1 != '/dev/null' ? $1[2..-1] : nil
Okay.
> +        when /^@@ -(\d+)(?:,(\d+))?/
> +          get_blame(source, $1, $2, from)
Okay.
Show 8 quoted lines
> +        end
> +      end
> +    end
> +  end
> +
> +end
> +
> +exit 1 if ARGV.size != 1
Okay.
> +commits = Commits.new
> +commits.from_patch(ARGV[0])
> +commits.import
The calling semantics could be better, but it's not a big complaint.
> +count_per_person = Hash.new(0)
Initializing all keys to 0.  Okay.
> +commits.each do |id, commit|
Cute.
> +  commit.persons.each do |person|
> +    count_per_person[person] += 1
Okay.
Show 7 quoted lines
> +  end
> +end
> +
> +count_per_person.each do |person, count|
> +  percent = count.to_f * 100 / commits.size
> +  next if percent < $min_percent
> +  puts person
Not going to print percentage as well?

Overall, significant improvement over v3 which used all kinds of unnecessarily complex data structures and convoluted logic. Looks like something I'd want to use: not blindly as a cc-cmd, but just to get a quick idea. I also wish for depth most times: a working shortlog -L --follow would be really nice.

Previous: Felipe ContrerasNext: Felipe Contreras
Message 6 of 28 in “New git-related helper”
  1. 00/15 New git-related helperFelipe Contreras, May 18, 2013
  2. 01/15 Add new git-related helper to contribFelipe Contreras, May 18, 2013
  3. Felipe ContrerasMay 18, 2013
  4. Junio C HamanoMay 19, 2013
  5. Felipe ContrerasMay 19, 2013
  6. Ramkumar RamachandraMay 19, 2013
  7. Felipe ContrerasMay 19, 2013
  8. Ramkumar RamachandraMay 19, 2013
  9. Felipe ContrerasMay 19, 2013
  10. David AguilarMay 19, 2013
  11. Ramkumar RamachandraMay 19, 2013
  12. Ramkumar RamachandraMay 19, 2013
  13. Felipe ContrerasMay 19, 2013
  14. Felipe ContrerasMay 19, 2013
  15. 02/15 contrib: related: add option parsingFelipe Contreras, May 18, 2013
  16. 03/15 contrib: related: sort by amount of involvementFelipe Contreras, May 18, 2013
  17. 04/15 contrib: related: print the amount of involvementFelipe Contreras, May 18, 2013
  18. 05/15 contrib: related: add helper Person classesFelipe Contreras, May 18, 2013
  19. 06/15 contrib: related: show role countFelipe Contreras, May 18, 2013
  20. 07/15 contrib: related: add support for more rolesFelipe Contreras, May 18, 2013
  21. 08/15 contrib: related: group persons with same emailFelipe Contreras, May 18, 2013
  22. 09/15 contrib: related: add mailmap supportFelipe Contreras, May 18, 2013
  23. 10/15 contrib: related: allow usage on other directoriesFelipe Contreras, May 18, 2013
  24. 11/15 contrib: related: add support for multiple patchesFelipe Contreras, May 18, 2013
  25. 12/15 contrib: related: add option to show commitsFelipe Contreras, May 18, 2013
  26. 13/15 contrib: related: add option to parse from committishFelipe Contreras, May 18, 2013
  27. 14/15 contrib: related: parse committish like format-patchFelipe Contreras, May 18, 2013
  28. 15/15 contrib: related: fix parsing of rev-list argsFelipe Contreras, May 18, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.