codeowners 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 162d8c21d1f878a18c07817645f62191d2e4996d58533f819e6ebf102e7409fb
4
- data.tar.gz: 4e06893a39070f1c34178f62e31e9afea773096bb121d98cdefea1620825bd2a
3
+ metadata.gz: 66eab678e31ae2c7c45bf32e8b8a92163bb3cef3147475a95775ece36081dce2
4
+ data.tar.gz: e188c85670d6cc4d1a0bb1d2f2fb6aee9085f1ad3b3ef978027d55ec4afc311d
5
5
  SHA512:
6
- metadata.gz: 579bbfb6ce368e0407d6d17f644e352b9f9823fd9ed71850189917d272e1ffe6177dd10650f0604172f7a4318d51cd550530c738397f8d90becff8348fbb701a
7
- data.tar.gz: 250bb637dfa66ef6cd4455c489e980e5475b1e67f5684cd70791dba1fe58b8d0e126d11031b3cd3b1f5eb1b6e0b5b5eb870f87e3bc6d7234d9713c1d299bbcd0
6
+ metadata.gz: 0c4e4381b4cdd046065ec83a785d742b058768d9b27cb78b765ecfe230e76e4a1cc608a3f395496196be051601ae7e9f22a3050f64e97e70a0f3761db481a204
7
+ data.tar.gz: 4037d4d9ba417ffe5ae65c3e50051f245c111f80e3880366b1bde609d936f15cef994a38a1438c64842447dbb2bb2f5685a6fd0c46268a065187699357541b9a
@@ -1,6 +1,10 @@
1
1
  # Codeowners
2
2
  Simple CLI to interact with GitHub CODEOWNERS
3
3
 
4
+ ## v0.0.2 - 2020-06-27
5
+ ### Added
6
+ - [Luca Guidi] Added pattern support to `codeowners contributors`
7
+
4
8
  ## v0.0.1 - 2020-06-12
5
9
  ### Added
6
10
  - [Luca Guidi] Added `codeowners contributors`
data/README.md CHANGED
@@ -34,6 +34,17 @@ Person One / +106, -0
34
34
  Person Two <person.two@company.com> / +12, -2
35
35
  ```
36
36
 
37
+ The command accepts also a pattern to match files in bulk.
38
+
39
+ ```shell
40
+ $ codeowners contributors 'path/to/**/*.rb'
41
+ path/to/**/*.rb
42
+
43
+ Person One <person.one@company.com> / +243, -438
44
+ Person Three <person.three@company.com> / +104, -56
45
+ Person Two <person.two@company.com> / +12, -2
46
+ ```
47
+
37
48
  ### Help
38
49
 
39
50
  For a complete set of options, please run:
@@ -55,17 +55,43 @@ module Codeowners
55
55
  DEFAULT_CODEOWNERS_PATH = ::File.join(".github", "CODEOWNERS").freeze
56
56
  private_constant :DEFAULT_CODEOWNERS_PATH
57
57
 
58
- desc "List code contributors for a file"
58
+ FORMAT_MAPPING = { "string" => "to_s", "csv" => "to_csv" }.freeze
59
+ private_constant :FORMAT_MAPPING
59
60
 
60
- argument :file, required: true, desc: "File to check"
61
+ FORMAT_VALUES = FORMAT_MAPPING.keys.freeze
62
+ private_constant :FORMAT_VALUES
63
+
64
+ DEFAULT_FORMAT = FORMAT_VALUES.first
65
+ private_constant :DEFAULT_FORMAT
66
+
67
+ DEFAULT_DEBUG = false
68
+ private_constant :DEFAULT_DEBUG
69
+
70
+ desc "List code contributors for a file (or a pattern)"
71
+
72
+ argument :file, required: true, desc: "File (or pattern) to check"
61
73
 
62
74
  option :base_directory, type: :string, default: DEFAULT_BASE_DIRECTORY, desc: "Base directory"
75
+ option :format, type: :string, default: DEFAULT_FORMAT, values: FORMAT_VALUES, desc: "Output format"
76
+ option :debug, type: :boolean, default: DEFAULT_DEBUG, desc: "Print debug information to stdout"
77
+
78
+ example [
79
+ "path/to/file.rb # file",
80
+ "'path/to/**/*.rb' # pattern"
81
+ ]
63
82
 
64
- def call(file:, base_directory:, **)
65
- result = Codeowners::ListContributors.new(base_directory).call(file)
83
+ def call(file:, base_directory:, format:, debug:, **)
84
+ result = Codeowners::ListContributors.new(base_directory).call(file, debug)
66
85
  exit(1) unless result.successful?
67
86
 
68
- out.puts result.to_s
87
+ out.puts output(result, format)
88
+ end
89
+
90
+ private
91
+
92
+ def output(result, format)
93
+ method_name = FORMAT_MAPPING.fetch(format)
94
+ result.public_send(method_name.to_sym)
69
95
  end
70
96
  end
71
97
 
@@ -9,9 +9,10 @@ module Codeowners
9
9
  @base_directory = Pathname.new(::File.expand_path(base_directory))
10
10
  end
11
11
 
12
- def contributors(file)
12
+ def contributors(file, debug = false)
13
13
  require "codeowners/git/contributors"
14
- output = git(["log", "--max-count=500", "--shortstat", %(--pretty=format:"author:%aN email:%ae"), "--no-color", "--", escape(file)])
14
+ output = git(["log", "--numstat", %(--pretty=format:"author:%aN email:%ae"), "--no-color", "--", escape(file)])
15
+ print_debug(output, debug)
15
16
 
16
17
  Contributors.call(file, output)
17
18
  end
@@ -42,5 +43,12 @@ module Codeowners
42
43
  return stdout.read
43
44
  end
44
45
  end
46
+
47
+ def print_debug(output, debug)
48
+ return unless debug
49
+
50
+ puts output
51
+ puts "\n" * 10
52
+ end
45
53
  end
46
54
  end
@@ -18,6 +18,10 @@ module Codeowners
18
18
  def to_s
19
19
  "#{name} <#{email}> / +#{insertions}, -#{deletions}"
20
20
  end
21
+
22
+ def to_csv
23
+ "#{name}, #{email}, #{insertions}, #{deletions}"
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -36,27 +36,37 @@ module Codeowners
36
36
  while lines.any?
37
37
  commit = lines.take_while { |line| line != "" }
38
38
  yield parse(commit.dup) unless commit.empty?
39
- lines -= commit
40
- lines.shift
39
+ lines.shift(commit.size + 1)
41
40
  end
42
41
  end
43
42
 
44
43
  def self.parse(commit)
45
- stats = commit.pop
46
- stats = stats.split(", ")
44
+ authors, stats = commit.partition { |line| line.match?(/author:/) }
47
45
 
48
- _, insertions, deletions = *stats
49
- insertions = insertions.to_i
50
- deletions = deletions.to_i
46
+ [extract_authors(authors), *calculate_stats(stats)]
47
+ end
51
48
 
52
- authors = commit.map do |author|
49
+ def self.extract_authors(authors)
50
+ authors.map do |author|
53
51
  {
54
- "name" => author.scan(/author:(.*)email:/).flatten.first.chop,
55
- "email" => author.scan(/email:(.*)/).flatten.first
52
+ "name" => scan(author, /author:(.*)email:/).chop,
53
+ "email" => scan(author, /email:(.*)/)
56
54
  }
55
+ end.uniq
56
+ end
57
+
58
+ def self.calculate_stats(stats)
59
+ stats.each_with_object([0, 0]) do |stat, result|
60
+ stat = stat.split(/[[:space:]]+/)
61
+
62
+ insertions, deletions, = *stat
63
+ result[0] += Integer(insertions)
64
+ result[1] += Integer(deletions)
57
65
  end
66
+ end
58
67
 
59
- [authors.uniq, insertions, deletions]
68
+ def self.scan(string, pattern)
69
+ string.scan(pattern).flatten.first
60
70
  end
61
71
 
62
72
  def initialize(data)
@@ -17,14 +17,18 @@ module Codeowners
17
17
  def to_s
18
18
  [@file, "", *@contributors.map(&:to_s)].join("\n")
19
19
  end
20
+
21
+ def to_csv
22
+ @contributors.map(&:to_csv).join("\n")
23
+ end
20
24
  end
21
25
 
22
26
  def initialize(base_directory, git: Git.new(base_directory))
23
27
  @git = git
24
28
  end
25
29
 
26
- def call(file)
27
- contributors = @git.contributors(file)
30
+ def call(file, debug = false)
31
+ contributors = @git.contributors(file, debug)
28
32
  return Result.new if contributors.empty?
29
33
 
30
34
  contributors = contributors.each.lazy.sort_by { |c| -c.insertions }
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Codeowners
4
4
  class Result
5
+ attr_reader :owners
6
+
5
7
  def initialize(pattern = nil, owners = [])
6
8
  @pattern = pattern
7
9
  @owners = owners
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Codeowners
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codeowners
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-12 00:00:00.000000000 Z
11
+ date: 2020-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-cli