owners 0.0.8 → 0.0.9

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
  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