owners 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b6b42791dcd2801448725619a34e70091c5d84b
4
- data.tar.gz: dca77d4996a6a2e9e0fedf15a4b86308f37b5187
3
+ metadata.gz: 20bc5ff50e8b6c0614a56bf72251c9dc8a1d059c
4
+ data.tar.gz: a765f585fde8b708ee5ff77c3214af251eff0407
5
5
  SHA512:
6
- metadata.gz: 1c40ac244b5ff0bf3aa6c7a465a09291a784bfd97a9f8c5c3cdd8719581e6d9e6583defe885a1d69819a16d75daf7eaeda5fef755a597a4f52b1cab490585c94
7
- data.tar.gz: 124a7bfa90f7aa4b59cc241d9b9da38053aca59e41735768972aca871fe21a936097dabef27af8b7d12134e3d0a96a09ba8c8e5bb856133ba8f9ddac06c09b8b
6
+ metadata.gz: 6ccafca0dd0655c27e80103e06f7cc61dce514bb1f8c556b048851de1eddb43752db874eb331c85ec64d499fb620368b2d503376040d5eb1375bc80b24013e5e
7
+ data.tar.gz: bfbd3c7370a857c1c090b2332e42ae1ff7007c7c4322ba992c168afb34fa6e2bd43ca56a442750fb5335a8e208ee77e275c7c2d217b11e11ad12915ceea49de2
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- owners (0.0.8)
4
+ owners (0.0.9)
5
5
  thor
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -34,6 +34,8 @@ jane@your-org.com
34
34
  #some_slack_channel
35
35
  ```
36
36
 
37
+ #### Filters
38
+
37
39
  The `OWNERS` file also supports filtering paths with regular expressions. Any whitespace between these filters and their corresponding subscribers is ignored.
38
40
 
39
41
  ```
@@ -43,6 +45,8 @@ bob@demo.com lib/bobs_special_file.rb
43
45
  #whitespace path/with spaces/is all part/of the filter.txt
44
46
  ```
45
47
 
48
+ #### Multiple subscribers
49
+
46
50
  Subscribers can be listed multiple times in an `OWNERS` file.
47
51
 
48
52
  ```
@@ -56,6 +60,8 @@ Multiple comma separated subscribers can be listed for the same filter.
56
60
  @data,@team-leads db
57
61
  ```
58
62
 
63
+ #### Comments
64
+
59
65
  Comments are supported by prefixing lines with `//`.
60
66
 
61
67
  ```
@@ -64,14 +70,61 @@ Comments are supported by prefixing lines with `//`.
64
70
  // even this one with whitespace
65
71
 
66
72
  @data,@team-leads db
73
+
74
+ #internal .env
67
75
  ```
68
76
 
77
+ #### Finding owners
78
+
69
79
  Find the owners for specific files by passing them to the `Owners.for` method.
80
+ This returns an array of `Owner` objects which are simple wrappers around
81
+ `String` with a few extra methods.
70
82
 
71
83
  ```ruby
72
- Owners.for("app/models/user.rb", "db/schema.rb") #=> ["@data", "@team-leads"]
84
+ owners = Owners.for("db/schema.rb", ".env") #=> ["@data", "#internal"]
85
+ ```
86
+
87
+ The owner's `type` can be one of `%i(alert email group label mention path tag)`.
88
+
89
+ ```ruby
90
+ owners.first.type #=> :mention
91
+ owners.last.type #=> :tag
92
+ ```
93
+
94
+ The `paths` method returns an array of owned file paths that triggered the match.
95
+
96
+ ```ruby
97
+ owners.first.paths #=> ["db/schema.rb"]
98
+ owners.last.paths #=> [".env"]
99
+ ```
100
+
101
+ The `subscriptions` method allows us to inspect the rules that triggered a match.
102
+
103
+ ```ruby
104
+ owners.each do |owner|
105
+ puts owner
106
+
107
+ owner.subscriptions.each do |path, subscriptions|
108
+ puts " #{path}"
109
+
110
+ subscriptions.each do |subscription|
111
+ puts " #{subscription.file}:#{subscription.line} => #{subscription.filter}"
112
+ end
113
+ end
114
+ end
73
115
  ```
74
116
 
117
+ ```
118
+ @data
119
+ db/schema.rb
120
+ OWNERS:5 => (?-mix:db)
121
+ #internal
122
+ .env
123
+ OWNERS:7 => (?-mix:.env)
124
+ ```
125
+
126
+ #### Git diff integration
127
+
75
128
  To find the owners for files changed with `git diff` use the `Owners.for_diff` method.
76
129
 
77
130
  ```ruby
@@ -79,20 +132,50 @@ Owners.for_diff("your-feature-branch-or-ref", "optional-base-ref-defaults-to-mas
79
132
  ```
80
133
 
81
134
 
82
- ## CLI
135
+ ## Command line interface
83
136
 
84
- This gem also comes with a convenient `owners` command line interface. Each owner is printed out and separated by newlines.
137
+ This gem also comes with a convenient `owners` CLI. Each owner is printed out and separated by newlines.
85
138
 
86
139
  ```bash
87
140
  owners for .env app/controllers/posts_controller.rb app/models/user.rb
88
141
  ```
89
142
 
90
143
  ```
91
- @infrastructure
92
- @api
144
+ #infrastructure
145
+ @api/internal
146
+ @data
147
+ ```
148
+
149
+ #### Debugging and managing subscriptions
150
+
151
+ The `--debug` option outputs additional information for subscriptions.
152
+
153
+ ```bash
154
+ owners for --debug .env app/controllers/posts_controller.rb app/models/user.rb
155
+ ```
156
+
157
+ ```
158
+ #infrastructure
159
+ tag
160
+ .env
161
+ OWNERS:1 => (?-mix:\.env)
162
+
163
+ @api/internal
164
+ group
165
+ app/controllers/posts_controller.rb
166
+ OWNERS:2 => (?-mix:app/(controllers|models))
167
+
168
+ app/models/user.rb
169
+ OWNERS:2 => (?-mix:app/(controllers|models))
170
+
93
171
  @data
172
+ mention
173
+ ./app/models/user.rb
174
+ ./OWNERS:3 => (?-mix:app/models)
94
175
  ```
95
176
 
177
+ #### Git diff integration
178
+
96
179
  The `git diff` integration works in the command line as well.
97
180
 
98
181
  ```bash
@@ -110,6 +193,16 @@ See `owners help` for more information.
110
193
  * `Owners.file=`
111
194
  * `Owners.for`
112
195
  * `Owners.for_diff`
196
+ * `Owners::Owner#type`
197
+ * `Owners::Owner#subscriptions`
198
+ * `Owners::Subscription#file`
199
+ * `Owners::Subscription#filter`
200
+ * `Owners::Subscription#line`
201
+ * `Owners::Subscription#metadata?`
202
+ * `Owners::Subscription#root`
203
+ * `Owners::Subscription#subscribed?`
204
+ * `Owners::Subscription#subscribers`
205
+ * `Owners::Subscription#subscription`
113
206
 
114
207
 
115
208
  ## Testing
@@ -130,4 +223,4 @@ bundle exec rspec
130
223
 
131
224
  ## License
132
225
 
133
- [MIT](https://github.com/shuber/owners/blob/master/LICENSE) - Copyright © 2015 Sean Huber
226
+ [MIT](https://github.com/shuber/owners/blob/master/LICENSE) - Copyright © 2015 Sean Huber
data/example/OWNERS CHANGED
@@ -1,6 +1,6 @@
1
1
  // comment
2
2
  @org/blog
3
- @multiple,@owners db
3
+ ,,,@multiple,@owners,, db
4
4
  //comment
5
5
 
6
6
  ////// comment
data/lib/owners/cli.rb CHANGED
@@ -1,20 +1,47 @@
1
1
  module Owners
2
2
  class CLI < Thor
3
+ class_option :debug,
4
+ aliases: %w(-d),
5
+ desc: "Output additional subscription debugging info",
6
+ type: :boolean
7
+
8
+ class_option :file,
9
+ aliases: %w(-f),
10
+ desc: "The name of the OWNERS file",
11
+ type: :string
12
+
3
13
  desc "for [FILES...]", "List owners for a set of files"
4
- method_option :file, desc: "The name of the OWNERS file"
5
14
  def for(*files)
6
15
  Owners.file = options[:file] if options[:file]
7
16
  Owners.for(*files).each do |owner|
8
- puts owner
17
+ output(owner)
9
18
  end
10
19
  end
11
20
 
12
21
  desc "for_diff REF [BASE_REF]", "List owners for a set of git changes"
13
- method_option :file, desc: "The name of the OWNERS file"
14
22
  def for_diff(ref, base_ref = "master")
15
23
  Owners.file = options[:file] if options[:file]
16
24
  Owners.for_diff(ref, base_ref).each do |owner|
17
- puts owner
25
+ output(owner)
26
+ end
27
+ end
28
+
29
+ no_commands do
30
+ def output(owner)
31
+ say owner
32
+
33
+ if options[:debug]
34
+ say owner.type, :yellow
35
+
36
+ owner.subscriptions.each do |path, subscriptions|
37
+ subscriptions.each do |sub|
38
+ say " #{path}", :red
39
+ say " #{sub.file}:#{sub.line} => #{sub.filter}", :blue
40
+ end
41
+
42
+ say
43
+ end
44
+ end
18
45
  end
19
46
  end
20
47
  end
data/lib/owners/config.rb CHANGED
@@ -1,50 +1,50 @@
1
1
  module Owners
2
- # Parses an OWNERS file and returns an array of owners
3
- # that have subscribed to a specified file path.
2
+ # Represents a single OWNERS file.
3
+ #
4
+ # It parses OWNERS files and returns an array of
5
+ # {Subscription} objects is returned for a specified
6
+ # file path.
4
7
  #
5
8
  # @api private
6
9
  class Config
7
- COMMENT = /^\s*\/\//
10
+ attr_reader :file, :root
11
+
12
+ def self.for(configs)
13
+ configs.map do |file, contents|
14
+ new(file, contents)
15
+ end
16
+ end
8
17
 
9
18
  def initialize(file, contents = nil)
19
+ @file = file.to_s
10
20
  @contents = contents || file.read
11
- @root = File.dirname(file.to_s)
21
+ @root = File.dirname(@file)
12
22
  end
13
23
 
14
- def owners(path)
15
- if path =~ prefix
16
- relative = path.sub(prefix, "")
17
-
18
- search do |subscription, results|
19
- owners = subscribers(relative, subscription)
20
- results.push(*owners)
24
+ def subscriptions(path)
25
+ search do |subscription, results|
26
+ if subscription.subscribed?(path)
27
+ results << subscription
21
28
  end
22
29
  end
23
30
  end
24
31
 
25
32
  private
26
33
 
27
- def prefix
28
- /\.?\/?#{@root}\//
29
- end
30
-
31
34
  def search(&block)
32
- subscriptions.each_with_object([], &block)
35
+ attempts
36
+ .reject(&:metadata?)
37
+ .each_with_object([], &block)
33
38
  end
34
39
 
35
- def subscriptions
36
- @contents.split("\n").reject do |subscription|
37
- subscription.empty? || subscription =~ COMMENT
40
+ def attempts
41
+ lines.map.with_index do |subscription, index|
42
+ Subscription.new(subscription, index + 1, self)
38
43
  end
39
44
  end
40
45
 
41
- def subscribers(path, subscription)
42
- subscribers, pattern = subscription.split(/\s+/, 2)
43
- regex = Regexp.new(pattern || ".*")
44
-
45
- subscribers.split(",").tap do |owners|
46
- owners.clear unless regex =~ path
47
- end
46
+ def lines
47
+ @contents.split("\n")
48
48
  end
49
49
  end
50
50
  end
@@ -0,0 +1,36 @@
1
+ module Owners
2
+ # Represents a unique "owner" across any number of OWNERS files.
3
+ #
4
+ # It is a simple wrapper around a {String} with some useful
5
+ # methods for inspecting an owner's type and subscriptions.
6
+ #
7
+ # @api public
8
+ class Owner < SimpleDelegator
9
+ def paths
10
+ subscriptions.keys
11
+ end
12
+
13
+ def subscriptions
14
+ @subscriptions ||= Hash.new { |hash, key| hash[key] = [] }
15
+ end
16
+
17
+ def type
18
+ case to_s
19
+ when /^!/
20
+ :alert
21
+ when /^[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+$/i
22
+ :email
23
+ when /^@.+\/[^@]+$/
24
+ :group
25
+ when /^@/
26
+ :mention
27
+ when /^#/
28
+ :tag
29
+ when /\//
30
+ :path
31
+ else
32
+ :label
33
+ end
34
+ end
35
+ end
36
+ end
data/lib/owners/search.rb CHANGED
@@ -1,40 +1,67 @@
1
1
  module Owners
2
2
  # Accepts an array of file paths and returns an array of
3
- # owners that have subscribed to the specified files.
3
+ # {Owner} objects that have subscribed to the files.
4
4
  #
5
5
  # @api private
6
6
  class Search
7
+ RELATIVE = /^\.?\//
8
+
7
9
  def initialize(files, configs = nil)
8
10
  @files = files.map(&:dup)
9
11
  @configs = configs
10
12
  end
11
13
 
12
- def owners
13
- search do |(path, config), results|
14
- owners = config.owners(path.to_s)
15
- results.merge(owners) if owners
14
+ def results
15
+ owners.each do |owner|
16
+ subscriptions.each do |path, subscription|
17
+ if subscription.subscribers.include?(owner)
18
+ owner.subscriptions[path] << subscription
19
+ end
20
+ end
16
21
  end
17
22
  end
18
23
 
19
24
  private
20
25
 
26
+ def owners
27
+ subscribers.map { |subscriber| Owner.new(subscriber) }
28
+ end
29
+
30
+ def subscribers
31
+ subscriptions_by_file
32
+ .values
33
+ .flatten
34
+ .flat_map(&:subscribers)
35
+ .uniq
36
+ end
37
+
38
+ def subscriptions
39
+ subscriptions_by_file.flat_map do |path, subscriptions|
40
+ [path].product(subscriptions)
41
+ end
42
+ end
43
+
44
+ def subscriptions_by_file
45
+ search do |(path, config), results|
46
+ relative = path.sub("./", "")
47
+ results[relative] += config.subscriptions(path)
48
+ end
49
+ end
50
+
21
51
  def search(&block)
22
- attempts.each_with_object(SortedSet.new, &block).to_a
52
+ results = Hash.new { |hash, key| hash[key] = [] }
53
+ attempts.each_with_object(results, &block)
23
54
  end
24
55
 
25
56
  def attempts
26
- paths.product(configs)
57
+ paths.map(&:to_s).product(configs)
27
58
  end
28
59
 
29
60
  def configs
30
- if @configs
31
- @configs.map { |file, contents| Config.new(file, contents) }
32
- else
33
- subscriptions.map { |file| Config.new(file) }
34
- end
61
+ Config.for(@configs || owner_files)
35
62
  end
36
63
 
37
- def subscriptions
64
+ def owner_files
38
65
  trees.flat_map(&:owner_files).uniq
39
66
  end
40
67
 
@@ -44,7 +71,7 @@ module Owners
44
71
 
45
72
  def paths
46
73
  @files.map do |file|
47
- file.prepend("./") unless file =~ /^\.?\//
74
+ file.prepend("./") unless file =~ RELATIVE
48
75
  Pathname.new(file)
49
76
  end
50
77
  end
@@ -0,0 +1,57 @@
1
+ module Owners
2
+ # Represents a single line of an OWNERS file.
3
+ #
4
+ # It contains some useful methods for inspecting the
5
+ # subscriptions themselves like the file, line, and
6
+ # filter, and subscribers.
7
+ #
8
+ # @api public
9
+ class Subscription
10
+ COMMENT = /^\s*\/\//
11
+ WILDCARD = /.*/
12
+
13
+ attr_reader :file, :line, :root, :subscription
14
+
15
+ def initialize(subscription, line, config)
16
+ @subscribers, @filter = subscription.split(/\s+/, 2)
17
+ @subscription = subscription
18
+ @line = line
19
+ @file = config.file.sub("./", "")
20
+ @root = config.root
21
+ end
22
+
23
+ def filter
24
+ Regexp.new(@filter || WILDCARD)
25
+ end
26
+
27
+ def metadata?
28
+ comment? || empty?
29
+ end
30
+
31
+ def subscribed?(path)
32
+ path =~ prefix && relative(path) =~ filter
33
+ end
34
+
35
+ def subscribers
36
+ @subscribers.split(",").reject(&:empty?)
37
+ end
38
+
39
+ private
40
+
41
+ def comment?
42
+ subscription =~ COMMENT
43
+ end
44
+
45
+ def empty?
46
+ subscription.strip.empty?
47
+ end
48
+
49
+ def prefix
50
+ /\.?\/?#{root}\//
51
+ end
52
+
53
+ def relative(path)
54
+ path.sub(prefix, "")
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,3 @@
1
1
  module Owners
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
data/lib/owners.rb CHANGED
@@ -1,9 +1,12 @@
1
+ require "delegate"
1
2
  require "pathname"
2
3
  require "set"
3
4
  require "thor"
4
5
  require_relative "owners/cli"
5
6
  require_relative "owners/config"
7
+ require_relative "owners/owner"
6
8
  require_relative "owners/search"
9
+ require_relative "owners/subscription"
7
10
  require_relative "owners/tree"
8
11
  require_relative "owners/version"
9
12
 
@@ -25,7 +28,7 @@ module Owners
25
28
  #
26
29
  # @api public
27
30
  def for(*files)
28
- Search.new(files).owners
31
+ Search.new(files).results
29
32
  end
30
33
 
31
34
  # Accepts a git ref and an optional base ref and returns
@@ -47,7 +50,7 @@ module Owners
47
50
  hash.update(file => contents)
48
51
  end
49
52
 
50
- Search.new(files, configs).owners
53
+ Search.new(files, configs).results
51
54
  end
52
55
  end
53
56
  end
@@ -0,0 +1,75 @@
1
+ RSpec.describe Owners::Owner do
2
+ describe "#paths" do
3
+ subject { described_class.new("test") }
4
+
5
+ it "parses paths correctly" do
6
+ expect(subject.paths).to be_empty
7
+
8
+ subject.subscriptions["testing"] << nil
9
+ expect(subject.paths).to eq(["testing"])
10
+
11
+ subject.subscriptions["again"] << nil
12
+ expect(subject.paths).to eq(["testing", "again"])
13
+ end
14
+ end
15
+
16
+ describe "#type" do
17
+ subject { described_class.new(owner).type }
18
+
19
+ context "with an alert" do
20
+ let(:owner) { "!alert" }
21
+
22
+ it "parses type correctly" do
23
+ expect(subject).to eq(:alert)
24
+ end
25
+ end
26
+
27
+ context "with an email" do
28
+ let(:owner) { "test+extra@example.com" }
29
+
30
+ it "parses type correctly" do
31
+ expect(subject).to eq(:email)
32
+ end
33
+ end
34
+
35
+ context "with a group" do
36
+ let(:owner) { "@example/group-name" }
37
+
38
+ it "parses type correctly" do
39
+ expect(subject).to eq(:group)
40
+ end
41
+ end
42
+
43
+ context "with a mention" do
44
+ let(:owner) { "@test" }
45
+
46
+ it "parses type correctly" do
47
+ expect(subject).to eq(:mention)
48
+ end
49
+ end
50
+
51
+ context "with a tag" do
52
+ let(:owner) { "#test" }
53
+
54
+ it "parses type correctly" do
55
+ expect(subject).to eq(:tag)
56
+ end
57
+ end
58
+
59
+ context "with a path" do
60
+ let(:owner) { "/one/two" }
61
+
62
+ it "parses type correctly" do
63
+ expect(subject).to eq(:path)
64
+ end
65
+ end
66
+
67
+ context "with anything else" do
68
+ let(:owner) { "anything" }
69
+
70
+ it "parses type correctly" do
71
+ expect(subject).to eq(:label)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -22,7 +22,7 @@ RSpec.describe Owners::CLI do
22
22
  end
23
23
 
24
24
  context "with a specified file" do
25
- before { args << "--file" << "SOMETHING_ELSE" }
25
+ before { args << "-f" << "SOMETHING_ELSE" }
26
26
 
27
27
  it "overrides the default OWNERS filename" do
28
28
  begin
@@ -32,6 +32,27 @@ RSpec.describe Owners::CLI do
32
32
  end
33
33
  end
34
34
  end
35
+
36
+ context "without debugging" do
37
+ before { args << "-d" }
38
+
39
+ it "parses owners correctly" do
40
+ expected = <<-OUTPUT
41
+ @org/auth
42
+ group
43
+ example/app/controllers/users_controller.rb
44
+ example/app/OWNERS:1 => (?-mix:user)
45
+
46
+ @org/blog
47
+ group
48
+ example/app/controllers/users_controller.rb
49
+ example/OWNERS:2 => (?-mix:.*)
50
+
51
+ OUTPUT
52
+
53
+ expect(subject).to eq(expected)
54
+ end
55
+ end
35
56
  end
36
57
 
37
58
  describe "for_diff" do
@@ -39,7 +60,7 @@ RSpec.describe Owners::CLI do
39
60
 
40
61
  context "without a specified file" do
41
62
  it "parses owners correctly" do
42
- expect(subject).to eq("@org/blog\n@whitespace\ndata@example.com\n")
63
+ expect(subject).to eq("@org/blog\ndata@example.com\n@whitespace\n")
43
64
  end
44
65
  end
45
66
 
data/spec/owners_spec.rb CHANGED
@@ -17,7 +17,7 @@ RSpec.describe Owners do
17
17
  ]}
18
18
 
19
19
  it "parses owners correctly" do
20
- expect(subject).to eq(["@org/auth", "@org/blog", "data@example.com"])
20
+ expect(subject).to eq(["@org/blog", "@org/auth", "data@example.com"])
21
21
  end
22
22
  end
23
23
 
@@ -41,7 +41,7 @@ RSpec.describe Owners do
41
41
  let(:paths) { ["example/app/models/blog.rb"] }
42
42
 
43
43
  it "parses owners correctly" do
44
- expect(subject).to eq(["@blogger", "@org/blog", "data@example.com"])
44
+ expect(subject).to eq(["data@example.com", "@blogger", "@org/blog"])
45
45
  end
46
46
  end
47
47
 
@@ -49,7 +49,7 @@ RSpec.describe Owners do
49
49
  let(:paths) { ["example/app/models/post.rb"] }
50
50
 
51
51
  it "parses owners correctly" do
52
- expect(subject).to eq(["@org/blog", "@whitespace", "data@example.com"])
52
+ expect(subject).to eq(["data@example.com", "@whitespace", "@org/blog"])
53
53
  end
54
54
  end
55
55
 
@@ -57,7 +57,7 @@ RSpec.describe Owners do
57
57
  let(:paths) { ["example/app/models/comment.rb"] }
58
58
 
59
59
  it "parses owners correctly" do
60
- expect(subject).to eq(["@duplicate", "@org/blog", "@owner", "data@example.com"])
60
+ expect(subject).to eq(["data@example.com", "@owner", "@duplicate", "@org/blog"])
61
61
  end
62
62
  end
63
63
 
@@ -65,7 +65,15 @@ RSpec.describe Owners do
65
65
  let(:paths) { ["example/db/schema.rb"] }
66
66
 
67
67
  it "parses owners correctly" do
68
- expect(subject).to eq(["@multiple", "@org/blog", "@owners"])
68
+ expect(subject).to eq(["@org/blog", "@multiple", "@owners"])
69
+ end
70
+ end
71
+
72
+ context "with empty comma separated owners" do
73
+ let(:paths) { ["example/db/schema.rb"] }
74
+
75
+ it "parses owners correctly" do
76
+ expect(subject).to eq(["@org/blog", "@multiple", "@owners"])
69
77
  end
70
78
  end
71
79
 
@@ -95,7 +103,7 @@ RSpec.describe Owners do
95
103
  let(:base_ref) { "ba7cd78" }
96
104
 
97
105
  it "parses owners correctly" do
98
- expect(subject).to eq(["@org/blog", "@whitespace", "data@example.com"])
106
+ expect(subject).to eq(["@org/blog", "data@example.com", "@whitespace"])
99
107
  end
100
108
  end
101
109
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: owners
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Huber
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-20 00:00:00.000000000 Z
11
+ date: 2016-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -68,10 +68,13 @@ files:
68
68
  - lib/owners.rb
69
69
  - lib/owners/cli.rb
70
70
  - lib/owners/config.rb
71
+ - lib/owners/owner.rb
71
72
  - lib/owners/search.rb
73
+ - lib/owners/subscription.rb
72
74
  - lib/owners/tree.rb
73
75
  - lib/owners/version.rb
74
76
  - owners.gemspec
77
+ - spec/owner_spec.rb
75
78
  - spec/owners_cli_spec.rb
76
79
  - spec/owners_spec.rb
77
80
  - spec/spec_helper.rb
@@ -105,6 +108,7 @@ signing_key:
105
108
  specification_version: 4
106
109
  summary: Take ownership of your code
107
110
  test_files:
111
+ - spec/owner_spec.rb
108
112
  - spec/owners_cli_spec.rb
109
113
  - spec/owners_spec.rb
110
114
  - spec/spec_helper.rb