acts-as-taggable-on 1.0.19 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.19
1
+ 1.1.0
@@ -82,7 +82,6 @@ module ActiveRecord
82
82
  end
83
83
  RUBY
84
84
  end
85
-
86
85
  if respond_to?(:tag_types)
87
86
  write_inheritable_attribute( :tag_types, (tag_types + args).uniq )
88
87
  else
@@ -286,29 +285,40 @@ module ActiveRecord
286
285
  def is_taggable?
287
286
  self.class.is_taggable?
288
287
  end
289
-
288
+
290
289
  def add_custom_context(value)
291
290
  custom_contexts << value.to_s unless custom_contexts.include?(value.to_s) or self.class.tag_types.map(&:to_s).include?(value.to_s)
292
291
  end
293
292
 
294
- def tag_list_on(context, owner=nil)
295
- var_name = context.to_s.singularize + "_list"
293
+ def tag_list_on(context, owner = nil)
296
294
  add_custom_context(context)
297
- return instance_variable_get("@#{var_name}") unless instance_variable_get("@#{var_name}").nil?
298
-
295
+ cache = tag_list_cache_on(context)
296
+ return owner ? cache[owner] : cache[owner] if cache[owner]
297
+
299
298
  if !owner && self.class.caching_tag_list_on?(context) and !(cached_value = cached_tag_list_on(context)).nil?
300
- instance_variable_set("@#{var_name}", TagList.from(self["cached_#{var_name}"]))
299
+ cache[owner] = TagList.from(cached_tag_list_on(context))
301
300
  else
302
- instance_variable_set("@#{var_name}", TagList.new(*tags_on(context, owner).map(&:name)))
301
+ cache[owner] = TagList.new(*tags_on(context, owner).map(&:name))
303
302
  end
304
303
  end
304
+
305
+ def all_tags_list_on(context)
306
+ variable_name = "@all_#{context.to_s.singularize}_list"
307
+ return instance_variable_get(variable_name) if instance_variable_get(variable_name)
308
+ instance_variable_set(variable_name, TagList.new(all_tags_on(context).map(&:name)).freeze)
309
+ end
310
+
311
+ def all_tags_on(context)
312
+ opts = {:conditions => ["#{Tagging.table_name}.context = ?", context.to_s]}
313
+ base_tags.find(:all, opts.merge(:order => "#{Tagging.table_name}.created_at"))
314
+ end
305
315
 
306
- def tags_on(context, owner=nil)
316
+ def tags_on(context, owner = nil)
307
317
  if owner
308
318
  opts = {:conditions => ["#{Tagging.table_name}.context = ? AND #{Tagging.table_name}.tagger_id = ? AND #{Tagging.table_name}.tagger_type = ?",
309
319
  context.to_s, owner.id, owner.class.to_s]}
310
320
  else
311
- opts = {:conditions => ["#{Tagging.table_name}.context = ?", context.to_s]}
321
+ opts = {:conditions => ["#{Tagging.table_name}.context = ? AND #{Tagging.table_name}.tagger_id IS NULL", context.to_s]}
312
322
  end
313
323
  base_tags.find(:all, opts)
314
324
  end
@@ -316,9 +326,16 @@ module ActiveRecord
316
326
  def cached_tag_list_on(context)
317
327
  self["cached_#{context.to_s.singularize}_list"]
318
328
  end
329
+
330
+ def tag_list_cache_on(context)
331
+ variable_name = "@#{context.to_s.singularize}_list"
332
+ cache = instance_variable_get(variable_name)
333
+ instance_variable_set(variable_name, cache = {}) unless cache
334
+ cache
335
+ end
319
336
 
320
- def set_tag_list_on(context,new_list, tagger=nil)
321
- instance_variable_set("@#{context.to_s.singularize}_list", TagList.from_owner(tagger, new_list))
337
+ def set_tag_list_on(context, new_list, tagger = nil)
338
+ tag_list_cache_on(context)[tagger] = TagList.from(new_list)
322
339
  add_custom_context(context)
323
340
  end
324
341
 
@@ -367,24 +384,24 @@ module ActiveRecord
367
384
  def save_cached_tag_list
368
385
  self.class.tag_types.map(&:to_s).each do |tag_type|
369
386
  if self.class.send("caching_#{tag_type.singularize}_list?")
370
- self["cached_#{tag_type.singularize}_list"] = send("#{tag_type.singularize}_list").to_s
387
+ self["cached_#{tag_type.singularize}_list"] = tag_list_cache_on(tag_type.singularize).tags.join(', ')
371
388
  end
372
389
  end
373
390
  end
374
391
 
375
392
  def save_tags
376
393
  (custom_contexts + self.class.tag_types.map(&:to_s)).each do |tag_type|
377
- next unless instance_variable_get("@#{tag_type.singularize}_list")
378
- owner = instance_variable_get("@#{tag_type.singularize}_list").owner
379
- new_tag_names = instance_variable_get("@#{tag_type.singularize}_list") - tags_on(tag_type).map(&:name)
380
- old_tags = tags_on(tag_type, owner).reject { |tag| instance_variable_get("@#{tag_type.singularize}_list").include?(tag.name) }
381
-
382
- transaction do
383
- base_tags.delete(*old_tags) if old_tags.any?
384
- new_tag_names.each do |new_tag_name|
385
- new_tag = Tag.find_or_create_with_like_by_name(new_tag_name)
386
- Tagging.create(:tag_id => new_tag.id, :context => tag_type,
387
- :taggable => self, :tagger => owner)
394
+ tag_list_cache = tag_list_cache_on(tag_type)
395
+ for owner, tag_list in tag_list_cache
396
+ new_tag_names = tag_list - tags_on(tag_type, owner).map(&:name)
397
+ old_tags = tags_on(tag_type, owner).reject { |tag| tag_list.include?(tag.name) }
398
+ transaction do
399
+ base_tags.delete(*old_tags) if old_tags.any?
400
+ new_tag_names.each do |new_tag_name|
401
+ new_tag = Tag.find_or_create_with_like_by_name(new_tag_name)
402
+ Tagging.create(:tag_id => new_tag.id, :context => tag_type,
403
+ :taggable => self, :tagger => owner)
404
+ end
388
405
  end
389
406
  end
390
407
  end
@@ -86,11 +86,5 @@ class TagList < Array
86
86
  tag_list.add(string.split(delimiter))
87
87
  end
88
88
  end
89
-
90
- def from_owner(owner, *tags)
91
- returning from(*tags) do |taglist|
92
- taglist.owner = owner
93
- end
94
- end
95
89
  end
96
90
  end
@@ -10,5 +10,5 @@ class Tagging < ActiveRecord::Base #:nodoc:
10
10
  validates_presence_of :context
11
11
  validates_presence_of :tag_id
12
12
 
13
- validates_uniqueness_of :tag_id, :scope => [:taggable_type, :taggable_id, :context]
13
+ validates_uniqueness_of :tag_id, :scope => [:taggable_type, :taggable_id, :context, :tagger_id, :tagger_type]
14
14
  end
@@ -48,8 +48,22 @@ describe "acts_as_tagger" do
48
48
 
49
49
  it 'should by default create the tag context on-the-fly' do
50
50
  @taggable.tag_list_on(:here_ond_now).should be_empty
51
- @tagger.tag(@taggable, :with=>'that', :on=>:here_ond_now)
52
- @taggable.tag_list_on(:here_ond_now).should include('that')
51
+ @tagger.tag(@taggable, :with=>'that', :on => :here_ond_now)
52
+ @taggable.tag_list_on(:here_ond_now).should_not include('that')
53
+ @taggable.all_tags_list_on(:here_ond_now).should include('that')
54
+ end
55
+
56
+ it "should show all the tag list when both public and owned tags exist" do
57
+ @taggable.tag_list = 'ruby, python'
58
+ @tagger.tag(@taggable, :with => 'java, lisp', :on => :tags)
59
+ @taggable.all_tags_on(:tags).map(&:name).sort.should == %w(ruby python java lisp).sort
60
+ end
61
+
62
+ it "should not add owned tags to the common list" do
63
+ @taggable.tag_list = 'ruby, python'
64
+ @tagger.tag(@taggable, :with => 'java, lisp', :on => :foo)
65
+ @tagger.tag(@taggable, :with => '', :on => :foo)
66
+ @taggable.tag_list.should == %w(ruby python)
53
67
  end
54
68
 
55
69
  it "should throw an exception when the default is over-ridden" do
@@ -64,7 +64,7 @@ describe TagList do
64
64
 
65
65
  it "should be able to call to_s on a frozen tag list" do
66
66
  @tag_list.freeze
67
- lambda { @tag_list.add("cool","rad,bodacious") }.should raise_error(TypeError)
68
- lambda { @tag_list.to_s }.should_not raise_error(TypeError)
67
+ lambda { @tag_list.add("cool","rad,bodacious") }.should raise_error
68
+ lambda { @tag_list.to_s }.should_not raise_error
69
69
  end
70
70
  end
@@ -7,35 +7,40 @@ describe "Taggable" do
7
7
  end
8
8
 
9
9
  it "should have tag types" do
10
- TaggableModel.tag_types.should == [:tags, :languages, :skills, :needs, :offerings]
11
- @taggable.tag_types.should == TaggableModel.tag_types
10
+ for type in [:tags, :languages, :skills, :needs, :offerings]
11
+ TaggableModel.tag_types.should include type
12
+ end
13
+ @taggable.tag_types.should == TaggableModel.tag_types
12
14
  end
13
15
 
14
16
  it "should have tag_counts_on" do
15
17
  TaggableModel.tag_counts_on(:tags).should be_empty
16
-
18
+
17
19
  @taggable.tag_list = ["awesome", "epic"]
18
20
  @taggable.save
19
21
 
20
22
  TaggableModel.tag_counts_on(:tags).count.should == 2
21
23
  @taggable.tag_counts_on(:tags).count.should == 2
22
24
  end
23
-
25
+
24
26
  it "should be able to create tags" do
25
27
  @taggable.skill_list = "ruby, rails, css"
26
- @taggable.instance_variable_get("@skill_list").instance_of?(TagList).should be_true
28
+ @taggable.instance_variable_get("@skill_list").instance_of?(Hash).should be_true
29
+ @taggable.instance_variable_get("@skill_list")[nil].instance_of?(TagList).should be_true
27
30
  @taggable.save
28
-
31
+
29
32
  Tag.find(:all).size.should == 3
30
33
  end
31
-
34
+
32
35
  it "should be able to create tags through the tag list directly" do
33
36
  @taggable.tag_list_on(:test).add("hello")
34
- @taggable.save
37
+ @taggable.tag_list_cache_on(:test).should_not be_empty
38
+ @taggable.save
39
+ @taggable.save_tags
35
40
  @taggable.reload
36
41
  @taggable.tag_list_on(:test).should == ["hello"]
37
42
  end
38
-
43
+
39
44
  it "should differentiate between contexts" do
40
45
  @taggable.skill_list = "ruby, rails, css"
41
46
  @taggable.tag_list = "ruby, bob, charlie"
@@ -44,7 +49,7 @@ describe "Taggable" do
44
49
  @taggable.skill_list.include?("ruby").should be_true
45
50
  @taggable.skill_list.include?("bob").should be_false
46
51
  end
47
-
52
+
48
53
  it "should be able to remove tags through list alone" do
49
54
  @taggable.skill_list = "ruby, rails, css"
50
55
  @taggable.save
@@ -55,13 +60,13 @@ describe "Taggable" do
55
60
  @taggable.reload
56
61
  @taggable.should have(2).skills
57
62
  end
58
-
63
+
59
64
  it "should be able to find by tag" do
60
65
  @taggable.skill_list = "ruby, rails, css"
61
66
  @taggable.save
62
67
  TaggableModel.find_tagged_with("ruby").first.should == @taggable
63
68
  end
64
-
69
+
65
70
  it "should be able to find by tag with context" do
66
71
  @taggable.skill_list = "ruby, rails, css"
67
72
  @taggable.tag_list = "bob, charlie"
@@ -70,27 +75,27 @@ describe "Taggable" do
70
75
  TaggableModel.find_tagged_with("bob", :on => :skills).first.should_not == @taggable
71
76
  TaggableModel.find_tagged_with("bob", :on => :tags).first.should == @taggable
72
77
  end
73
-
78
+
74
79
  it "should be able to use the tagged_with named scope" do
75
80
  @taggable.skill_list = "ruby, rails, css"
76
81
  @taggable.tag_list = "bob, charlie"
77
82
  @taggable.save
78
-
83
+
79
84
  TaggableModel.tagged_with("ruby").first.should == @taggable
80
85
  TaggableModel.tagged_with("ruby, css").first.should == @taggable
81
86
  TaggableModel.tagged_with("ruby, nonexistingtag").should be_empty
82
87
  TaggableModel.tagged_with("bob", :on => :skills).first.should_not == @taggable
83
88
  TaggableModel.tagged_with("bob", :on => :tags).first.should == @taggable
84
89
  end
85
-
90
+
86
91
  it "should not care about case" do
87
92
  bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby")
88
93
  frank = TaggableModel.create(:name => "Frank", :tag_list => "Ruby")
89
-
94
+
90
95
  Tag.find(:all).size.should == 1
91
96
  TaggableModel.find_tagged_with("ruby").should == TaggableModel.find_tagged_with("Ruby")
92
97
  end
93
-
98
+
94
99
  it "should be able to get tag counts on model as a whole" do
95
100
  bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
96
101
  frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
@@ -98,39 +103,39 @@ describe "Taggable" do
98
103
  TaggableModel.tag_counts.should_not be_empty
99
104
  TaggableModel.skill_counts.should_not be_empty
100
105
  end
101
-
106
+
102
107
  it "should be able to get all tag counts on model as whole" do
103
108
  bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
104
109
  frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
105
110
  charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby")
106
-
111
+
107
112
  TaggableModel.all_tag_counts.should_not be_empty
108
113
  TaggableModel.all_tag_counts.first.count.should == 3 # ruby
109
114
  end
110
-
115
+
111
116
  it "should not return read-only records" do
112
117
  TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
113
-
118
+
114
119
  TaggableModel.tagged_with("ruby").first.should_not be_readonly
115
120
  end
116
-
121
+
117
122
  it "should be able to get scoped tag counts" do
118
123
  bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
119
124
  frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
120
125
  charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby")
121
-
126
+
122
127
  TaggableModel.tagged_with("ruby").tag_counts.first.count.should == 2 # ruby
123
128
  TaggableModel.tagged_with("ruby").skill_counts.first.count.should == 1 # ruby
124
129
  end
125
-
130
+
126
131
  it "should be able to get all scoped tag counts" do
127
132
  bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
128
133
  frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
129
134
  charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby")
130
-
135
+
131
136
  TaggableModel.tagged_with("ruby").all_tag_counts.first.count.should == 3 # ruby
132
137
  end
133
-
138
+
134
139
  it "should be able to set a custom tag context list" do
135
140
  bob = TaggableModel.create(:name => "Bob")
136
141
  bob.set_tag_list_on(:rotors, "spinning, jumping")
@@ -139,12 +144,12 @@ describe "Taggable" do
139
144
  bob.reload
140
145
  bob.tags_on(:rotors).should_not be_empty
141
146
  end
142
-
147
+
143
148
  it "should be able to find tagged" do
144
149
  bob = TaggableModel.create(:name => "Bob", :tag_list => "fitter, happier, more productive", :skill_list => "ruby, rails, css")
145
150
  frank = TaggableModel.create(:name => "Frank", :tag_list => "weaker, depressed, inefficient", :skill_list => "ruby, rails, css")
146
151
  steve = TaggableModel.create(:name => 'Steve', :tag_list => 'fitter, happier, more productive', :skill_list => 'c++, java, ruby')
147
-
152
+
148
153
  TaggableModel.find_tagged_with("ruby", :order => 'taggable_models.name').should == [bob, frank, steve]
149
154
  TaggableModel.find_tagged_with("ruby, rails", :order => 'taggable_models.name').should == [bob, frank]
150
155
  TaggableModel.find_tagged_with(["ruby", "rails"], :order => 'taggable_models.name').should == [bob, frank]
@@ -154,12 +159,12 @@ describe "Taggable" do
154
159
  bob = TaggableModel.create(:name => "Bob", :tag_list => "fitter, happier, more productive", :skill_list => "ruby, rails, css")
155
160
  frank = TaggableModel.create(:name => "Frank", :tag_list => "weaker, depressed, inefficient", :skill_list => "ruby, rails, css")
156
161
  steve = TaggableModel.create(:name => 'Steve', :tag_list => 'fitter, happier, more productive', :skill_list => 'c++, java, ruby')
157
-
162
+
158
163
  TaggableModel.find_tagged_with(["ruby", "java"], :order => 'taggable_models.name', :any => true).should == [bob, frank, steve]
159
164
  TaggableModel.find_tagged_with(["c++", "fitter"], :order => 'taggable_models.name', :any => true).should == [bob, steve]
160
165
  TaggableModel.find_tagged_with(["depressed", "css"], :order => 'taggable_models.name', :any => true).should == [bob, frank]
161
166
  end
162
-
167
+
163
168
  it "should be able to find tagged on a custom tag context" do
164
169
  bob = TaggableModel.create(:name => "Bob")
165
170
  bob.set_tag_list_on(:rotors, "spinning, jumping")
@@ -172,29 +177,38 @@ describe "Taggable" do
172
177
  bob = TaggableModel.create(:name => "Bob", :tag_list => "fitter, happier, more productive", :skill_list => "ruby, rails, css")
173
178
  frank = TaggableModel.create(:name => "Frank", :tag_list => "weaker, depressed, inefficient", :skill_list => "ruby, rails, css")
174
179
  steve = TaggableModel.create(:name => 'Steve', :tag_list => 'fitter, happier, more productive', :skill_list => 'c++, java, python')
175
-
180
+
176
181
  # Let's only find those productive Rails developers
177
182
  TaggableModel.tagged_with('rails', :on => :skills, :order => 'taggable_models.name').should == [bob, frank]
178
183
  TaggableModel.tagged_with('happier', :on => :tags, :order => 'taggable_models.name').should == [bob, steve]
179
184
  TaggableModel.tagged_with('rails', :on => :skills).tagged_with('happier', :on => :tags).should == [bob]
180
185
  TaggableModel.tagged_with('rails').tagged_with('happier', :on => :tags).should == [bob]
181
186
  end
182
-
187
+
183
188
  it "should be able to find tagged with only the matching tags" do
184
189
  bob = TaggableModel.create(:name => "Bob", :tag_list => "lazy, happier")
185
190
  frank = TaggableModel.create(:name => "Frank", :tag_list => "fitter, happier, inefficient")
186
191
  steve = TaggableModel.create(:name => 'Steve', :tag_list => "fitter, happier")
187
-
192
+
188
193
  TaggableModel.find_tagged_with("fitter, happier", :match_all => true).should == [steve]
189
194
  end
190
-
195
+
191
196
  it "should be able to find tagged with some excluded tags" do
192
197
  bob = TaggableModel.create(:name => "Bob", :tag_list => "happier, lazy")
193
198
  frank = TaggableModel.create(:name => "Frank", :tag_list => "happier")
194
199
  steve = TaggableModel.create(:name => 'Steve', :tag_list => "happier")
195
-
200
+
196
201
  TaggableModel.find_tagged_with("lazy", :exclude => true).should == [frank, steve]
197
202
  end
203
+
204
+ it "should not create duplicate taggings" do
205
+ bob = TaggableModel.create(:name => "Bob")
206
+ lambda {
207
+ bob.tag_list << "happier"
208
+ bob.tag_list << "happier"
209
+ bob.save
210
+ }.should change(Tagging, :count).by(1)
211
+ end
198
212
 
199
213
  describe "Single Table Inheritance" do
200
214
  before do
@@ -203,32 +217,32 @@ describe "Taggable" do
203
217
  @inherited_same = InheritingTaggableModel.new(:name => "inherited same")
204
218
  @inherited_different = AlteredInheritingTaggableModel.new(:name => "inherited different")
205
219
  end
206
-
220
+
207
221
  it "should be able to save tags for inherited models" do
208
222
  @inherited_same.tag_list = "bob, kelso"
209
223
  @inherited_same.save
210
224
  InheritingTaggableModel.find_tagged_with("bob").first.should == @inherited_same
211
225
  end
212
-
226
+
213
227
  it "should find STI tagged models on the superclass" do
214
228
  @inherited_same.tag_list = "bob, kelso"
215
229
  @inherited_same.save
216
230
  TaggableModel.find_tagged_with("bob").first.should == @inherited_same
217
231
  end
218
-
232
+
219
233
  it "should be able to add on contexts only to some subclasses" do
220
234
  @inherited_different.part_list = "fork, spoon"
221
235
  @inherited_different.save
222
236
  InheritingTaggableModel.find_tagged_with("fork", :on => :parts).should be_empty
223
237
  AlteredInheritingTaggableModel.find_tagged_with("fork", :on => :parts).first.should == @inherited_different
224
238
  end
225
-
239
+
226
240
  it "should have different tag_counts_on for inherited models" do
227
241
  @inherited_same.tag_list = "bob, kelso"
228
242
  @inherited_same.save!
229
243
  @inherited_different.tag_list = "fork, spoon"
230
244
  @inherited_different.save!
231
-
245
+
232
246
  InheritingTaggableModel.tag_counts_on(:tags).map(&:name).should == %w(bob kelso)
233
247
  AlteredInheritingTaggableModel.tag_counts_on(:tags).map(&:name).should == %w(fork spoon)
234
248
  TaggableModel.tag_counts_on(:tags).map(&:name).should == %w(bob kelso fork spoon)
@@ -6,17 +6,32 @@ describe "Tagger" do
6
6
  @user = TaggableUser.new
7
7
  @taggable = TaggableModel.new(:name => "Bob Jones")
8
8
  end
9
-
9
+
10
10
  it "should have taggings" do
11
11
  @user.tag(@taggable, :with=>'ruby,scheme', :on=>:tags)
12
12
  @user.owned_taggings.size == 2
13
13
  end
14
-
14
+
15
15
  it "should have tags" do
16
16
  @user.tag(@taggable, :with=>'ruby,scheme', :on=>:tags)
17
17
  @user.owned_tags.size == 2
18
18
  end
19
19
 
20
+ it "should not overlap or lose tags from different users" do
21
+ @user2 = TaggableUser.new
22
+ lambda{
23
+ @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
24
+ @user2.tag(@taggable, :with => 'java, python, lisp, ruby', :on => :tags)
25
+ }.should change(Tagging, :count).by(6)
26
+
27
+ @user.owned_tags.map(&:name).should == %w(ruby scheme)
28
+ @user2.owned_tags.map(&:name).sort.should == %w(java python lisp ruby).sort
29
+ @taggable.tags_from(@user).should == %w(ruby scheme)
30
+ @taggable.tags_from(@user2).should == %w(java python lisp ruby)
31
+ @taggable.all_tags_list_on(:tags).sort.should == %w(ruby scheme java python lisp).sort
32
+ @taggable.all_tags_on(:tags).size.should == 6
33
+ end
34
+
20
35
  it "is tagger" do
21
36
  @user.is_tagger?.should(be_true)
22
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts-as-taggable-on
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.19
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-21 00:00:00 -05:00
12
+ date: 2010-02-03 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15