garcun 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 +7 -0
- data/.gitattributes +17 -0
- data/.gitignore +197 -0
- data/.rspec +2 -0
- data/Gemfile +22 -0
- data/LICENSE +201 -0
- data/README.md +521 -0
- data/Rakefile +47 -0
- data/garcun.gemspec +83 -0
- data/lib/garcon.rb +290 -0
- data/lib/garcon/chef/chef_helpers.rb +343 -0
- data/lib/garcon/chef/coerce/coercer.rb +134 -0
- data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
- data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
- data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
- data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
- data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
- data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
- data/lib/garcon/chef/handler/devreporter.rb +127 -0
- data/lib/garcon/chef/log.rb +64 -0
- data/lib/garcon/chef/node.rb +100 -0
- data/lib/garcon/chef/provider/civilize.rb +209 -0
- data/lib/garcon/chef/provider/development.rb +159 -0
- data/lib/garcon/chef/provider/download.rb +420 -0
- data/lib/garcon/chef/provider/house_keeping.rb +265 -0
- data/lib/garcon/chef/provider/node_cache.rb +31 -0
- data/lib/garcon/chef/provider/partial.rb +183 -0
- data/lib/garcon/chef/provider/recovery.rb +80 -0
- data/lib/garcon/chef/provider/zip_file.rb +271 -0
- data/lib/garcon/chef/resource/attribute.rb +52 -0
- data/lib/garcon/chef/resource/base_dsl.rb +174 -0
- data/lib/garcon/chef/resource/blender.rb +140 -0
- data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
- data/lib/garcon/chef/resource/resource_name.rb +109 -0
- data/lib/garcon/chef/secret_bag.rb +204 -0
- data/lib/garcon/chef/validations.rb +76 -0
- data/lib/garcon/chef_inclusions.rb +151 -0
- data/lib/garcon/configuration.rb +138 -0
- data/lib/garcon/core_ext.rb +39 -0
- data/lib/garcon/core_ext/array.rb +27 -0
- data/lib/garcon/core_ext/binding.rb +64 -0
- data/lib/garcon/core_ext/boolean.rb +66 -0
- data/lib/garcon/core_ext/duration.rb +271 -0
- data/lib/garcon/core_ext/enumerable.rb +34 -0
- data/lib/garcon/core_ext/file.rb +127 -0
- data/lib/garcon/core_ext/filetest.rb +62 -0
- data/lib/garcon/core_ext/hash.rb +279 -0
- data/lib/garcon/core_ext/kernel.rb +159 -0
- data/lib/garcon/core_ext/lazy.rb +222 -0
- data/lib/garcon/core_ext/method_access.rb +243 -0
- data/lib/garcon/core_ext/module.rb +92 -0
- data/lib/garcon/core_ext/nil.rb +53 -0
- data/lib/garcon/core_ext/numeric.rb +44 -0
- data/lib/garcon/core_ext/object.rb +342 -0
- data/lib/garcon/core_ext/pathname.rb +152 -0
- data/lib/garcon/core_ext/process.rb +41 -0
- data/lib/garcon/core_ext/random.rb +497 -0
- data/lib/garcon/core_ext/string.rb +312 -0
- data/lib/garcon/core_ext/struct.rb +49 -0
- data/lib/garcon/core_ext/symbol.rb +170 -0
- data/lib/garcon/core_ext/time.rb +234 -0
- data/lib/garcon/exceptions.rb +101 -0
- data/lib/garcon/inflections.rb +237 -0
- data/lib/garcon/inflections/defaults.rb +79 -0
- data/lib/garcon/inflections/inflections.rb +182 -0
- data/lib/garcon/inflections/rules_collection.rb +37 -0
- data/lib/garcon/secret.rb +271 -0
- data/lib/garcon/stash/format.rb +114 -0
- data/lib/garcon/stash/journal.rb +226 -0
- data/lib/garcon/stash/queue.rb +83 -0
- data/lib/garcon/stash/serializer.rb +86 -0
- data/lib/garcon/stash/store.rb +435 -0
- data/lib/garcon/task.rb +31 -0
- data/lib/garcon/task/atomic.rb +151 -0
- data/lib/garcon/task/atomic_boolean.rb +127 -0
- data/lib/garcon/task/condition.rb +99 -0
- data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
- data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
- data/lib/garcon/task/count_down_latch.rb +92 -0
- data/lib/garcon/task/delay.rb +196 -0
- data/lib/garcon/task/dereferenceable.rb +144 -0
- data/lib/garcon/task/event.rb +119 -0
- data/lib/garcon/task/executor.rb +275 -0
- data/lib/garcon/task/executor_options.rb +59 -0
- data/lib/garcon/task/future.rb +107 -0
- data/lib/garcon/task/immediate_executor.rb +84 -0
- data/lib/garcon/task/ivar.rb +171 -0
- data/lib/garcon/task/lazy_reference.rb +74 -0
- data/lib/garcon/task/monotonic_time.rb +69 -0
- data/lib/garcon/task/obligation.rb +256 -0
- data/lib/garcon/task/observable.rb +101 -0
- data/lib/garcon/task/priority_queue.rb +234 -0
- data/lib/garcon/task/processor_count.rb +128 -0
- data/lib/garcon/task/read_write_lock.rb +304 -0
- data/lib/garcon/task/safe_task_executor.rb +58 -0
- data/lib/garcon/task/single_thread_executor.rb +97 -0
- data/lib/garcon/task/thread_pool/cached.rb +71 -0
- data/lib/garcon/task/thread_pool/executor.rb +294 -0
- data/lib/garcon/task/thread_pool/fixed.rb +61 -0
- data/lib/garcon/task/thread_pool/worker.rb +90 -0
- data/lib/garcon/task/timer.rb +44 -0
- data/lib/garcon/task/timer_set.rb +194 -0
- data/lib/garcon/task/timer_task.rb +377 -0
- data/lib/garcon/task/waitable_list.rb +58 -0
- data/lib/garcon/utility/ansi.rb +199 -0
- data/lib/garcon/utility/at_random.rb +77 -0
- data/lib/garcon/utility/crypto.rb +292 -0
- data/lib/garcon/utility/equalizer.rb +146 -0
- data/lib/garcon/utility/faker/extensions/array.rb +22 -0
- data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
- data/lib/garcon/utility/faker/faker.rb +164 -0
- data/lib/garcon/utility/faker/faker/company.rb +17 -0
- data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
- data/lib/garcon/utility/faker/faker/version.rb +3 -0
- data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
- data/lib/garcon/utility/faker/locales/en.yml +21 -0
- data/lib/garcon/utility/file_helper.rb +170 -0
- data/lib/garcon/utility/hookers.rb +178 -0
- data/lib/garcon/utility/interpolation.rb +90 -0
- data/lib/garcon/utility/memstash.rb +364 -0
- data/lib/garcon/utility/misc.rb +54 -0
- data/lib/garcon/utility/msg_from_god.rb +62 -0
- data/lib/garcon/utility/retry.rb +238 -0
- data/lib/garcon/utility/timeout.rb +58 -0
- data/lib/garcon/utility/uber/builder.rb +91 -0
- data/lib/garcon/utility/uber/callable.rb +7 -0
- data/lib/garcon/utility/uber/delegates.rb +13 -0
- data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
- data/lib/garcon/utility/uber/options.rb +101 -0
- data/lib/garcon/utility/uber/uber_version.rb +3 -0
- data/lib/garcon/utility/uber/version.rb +33 -0
- data/lib/garcon/utility/url_helper.rb +100 -0
- data/lib/garcon/utils.rb +29 -0
- data/lib/garcon/version.rb +62 -0
- data/lib/garcun.rb +24 -0
- metadata +680 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
# Add #blank? method to TrueClass class.
|
|
21
|
+
class TrueClass
|
|
22
|
+
# True is never blank.
|
|
23
|
+
#
|
|
24
|
+
# @example
|
|
25
|
+
# true.blank? # => false
|
|
26
|
+
#
|
|
27
|
+
# @return [FalseClass]
|
|
28
|
+
#
|
|
29
|
+
# @api public
|
|
30
|
+
def blank?
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Since TrueClass is immutable it cannot be duplicated.
|
|
35
|
+
# For this reason #try_dup returns +self+.
|
|
36
|
+
#
|
|
37
|
+
# true.dup! #=> true
|
|
38
|
+
#
|
|
39
|
+
def dup! ; self ; end
|
|
40
|
+
def dup? ; false ; end
|
|
41
|
+
def clone? ; false ; end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Add #blank? method to FalseClass class.
|
|
45
|
+
class FalseClass
|
|
46
|
+
# False is always blank.
|
|
47
|
+
#
|
|
48
|
+
# @example
|
|
49
|
+
# false.blank? # => true
|
|
50
|
+
#
|
|
51
|
+
# @return [TrueClass]
|
|
52
|
+
#
|
|
53
|
+
# @api public
|
|
54
|
+
def blank?
|
|
55
|
+
true
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Since FalseClass is immutable it cannot be duplicated.
|
|
59
|
+
# For this reason #try_dup returns +self+.
|
|
60
|
+
#
|
|
61
|
+
# false.dup! #=> false
|
|
62
|
+
#
|
|
63
|
+
def dup! ; self ; end
|
|
64
|
+
def dup? ; false ; end
|
|
65
|
+
def clone? ; false ; end
|
|
66
|
+
end
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
class Duration
|
|
21
|
+
include Comparable
|
|
22
|
+
|
|
23
|
+
SECOND = 1
|
|
24
|
+
MINUTE = 60 * SECOND
|
|
25
|
+
HOUR = 60 * MINUTE
|
|
26
|
+
DAY = 24 * HOUR
|
|
27
|
+
WEEK = 7 * DAY
|
|
28
|
+
YEAR = 365 * DAY
|
|
29
|
+
|
|
30
|
+
SEGMENTS = %w{years weeks days hours minutes seconds}.collect{ |s| s.to_sym }
|
|
31
|
+
|
|
32
|
+
def self.[](seconds, *segments)
|
|
33
|
+
new(seconds, *segments)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def initialize(seconds=0, *segments)
|
|
37
|
+
@seconds = seconds.to_i
|
|
38
|
+
reset_segments(*segments)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def segments; @segments; end
|
|
42
|
+
|
|
43
|
+
def reset_segments(*segments)
|
|
44
|
+
case segments.size
|
|
45
|
+
when 0
|
|
46
|
+
@segments = [:days, :hours, :minutes, :seconds]
|
|
47
|
+
when 1
|
|
48
|
+
case segments = segments[0]
|
|
49
|
+
when Array
|
|
50
|
+
@segments = segments.collect { |p| (p.to_s.downcase.chomp('s') + 's').to_sym }
|
|
51
|
+
raise ArgumentError unless @segments.all? { |s| SEGMENTS.include?(s) }
|
|
52
|
+
else
|
|
53
|
+
f = SEGMENTS.index(segments)
|
|
54
|
+
@segments = SEGMENTS[f..0]
|
|
55
|
+
end
|
|
56
|
+
when 2
|
|
57
|
+
f = SEGMENTS.index(segments[0])
|
|
58
|
+
t = SEGMENTS.index(segments[1])
|
|
59
|
+
@segments = SEGMENTS[f..t]
|
|
60
|
+
else
|
|
61
|
+
raise ArgumentError
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def inspect
|
|
66
|
+
h = to_h
|
|
67
|
+
segments.reverse.collect do |l|
|
|
68
|
+
"#{h[l.to_sym]} #{l}"
|
|
69
|
+
end.join(' ')
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def to_i ; @seconds.to_i ; end
|
|
73
|
+
def to_f ; @seconds.to_f ; end
|
|
74
|
+
|
|
75
|
+
public
|
|
76
|
+
|
|
77
|
+
def to_a
|
|
78
|
+
a, s = [], @seconds
|
|
79
|
+
a[5], s = *s.divmod(YEAR) if @segments.include?(:years)
|
|
80
|
+
a[4], s = *s.divmod(WEEK) if @segments.include?(:weeks)
|
|
81
|
+
a[3], s = *s.divmod(DAY) if @segments.include?(:days)
|
|
82
|
+
a[2], s = *s.divmod(HOUR) if @segments.include?(:hours)
|
|
83
|
+
a[1], s = *s.divmod(MINUTE) if @segments.include?(:minutes)
|
|
84
|
+
a[0], s = *s.divmod(SECOND) if @segments.include?(:seconds)
|
|
85
|
+
a.compact.reverse
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def to_h
|
|
89
|
+
h, s = {}, @seconds
|
|
90
|
+
h[:years], s = *s.divmod(YEAR) if @segments.include?(:years)
|
|
91
|
+
h[:weeks], s = *s.divmod(WEEK) if @segments.include?(:weeks)
|
|
92
|
+
h[:days], s = *s.divmod(DAY) if @segments.include?(:days)
|
|
93
|
+
h[:hours], s = *s.divmod(HOUR) if @segments.include?(:hours)
|
|
94
|
+
h[:minutes], s = *s.divmod(MINUTE) if @segments.include?(:minutes)
|
|
95
|
+
h[:seconds], s = *s.divmod(SECOND) if @segments.include?(:seconds)
|
|
96
|
+
h
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def to_s
|
|
100
|
+
h = to_h
|
|
101
|
+
segments.reverse.collect do |l|
|
|
102
|
+
"#{h[l.to_sym]} #{l}"
|
|
103
|
+
end.join(' ')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def ==(other)
|
|
107
|
+
if Duration === other
|
|
108
|
+
other.seconds == seconds
|
|
109
|
+
else
|
|
110
|
+
other == seconds
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def <=>(other)
|
|
115
|
+
@seconds <=> other.to_i
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def years ; to_h[:years] ; end
|
|
119
|
+
def weeks ; to_h[:weeks] ; end
|
|
120
|
+
def days ; to_h[:days] ; end
|
|
121
|
+
def hours ; to_h[:hours] ; end
|
|
122
|
+
def minutes ; to_h[:minutes] ; end
|
|
123
|
+
def seconds ; to_h[:seconds] ; end
|
|
124
|
+
|
|
125
|
+
def total ; seconds ; end
|
|
126
|
+
|
|
127
|
+
def +(other)
|
|
128
|
+
self.class.new(@seconds + other.to_i, segments)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def -(other)
|
|
132
|
+
self.class.new(@seconds - other.to_i, segments)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def *(other)
|
|
136
|
+
self.class.new(@seconds * other.to_i, segments)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def /(other)
|
|
140
|
+
self.class.new(@seconds / other.to_i, segments)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def segmented(*segments)
|
|
144
|
+
self.class.new(@seconds, segments)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Format duration.
|
|
148
|
+
#
|
|
149
|
+
# *Identifiers*
|
|
150
|
+
#
|
|
151
|
+
# %w -- Number of weeks
|
|
152
|
+
# %d -- Number of days
|
|
153
|
+
# %h -- Number of hours
|
|
154
|
+
# %m -- Number of minutes
|
|
155
|
+
# %s -- Number of seconds
|
|
156
|
+
# %t -- Total number of seconds
|
|
157
|
+
# %x -- Duration#to_s
|
|
158
|
+
# %% -- Literal `%' character
|
|
159
|
+
#
|
|
160
|
+
# *Example*
|
|
161
|
+
#
|
|
162
|
+
# d = Duration.new(:weeks => 10, :days => 7)
|
|
163
|
+
# => #<Duration: 11 weeks>
|
|
164
|
+
# d.strftime("It's been %w weeks!")
|
|
165
|
+
# => "It's been 11 weeks!"
|
|
166
|
+
#
|
|
167
|
+
def strftime(fmt)
|
|
168
|
+
h = to_h
|
|
169
|
+
hx = {
|
|
170
|
+
'y' => h[:years] ,
|
|
171
|
+
'w' => h[:weeks] ,
|
|
172
|
+
'd' => h[:days] ,
|
|
173
|
+
'h' => h[:hours] ,
|
|
174
|
+
'm' => h[:minutes],
|
|
175
|
+
's' => h[:seconds],
|
|
176
|
+
't' => total,
|
|
177
|
+
'x' => to_s
|
|
178
|
+
}
|
|
179
|
+
fmt.gsub(/%?%(w|d|h|m|s|t|x)/) do |match|
|
|
180
|
+
hx[match[1..1]]
|
|
181
|
+
end.gsub('%%', '%')
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def -@
|
|
185
|
+
self.class.new(-@seconds)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def +@
|
|
189
|
+
self.class.new(+@seconds)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def before(time)
|
|
193
|
+
@seconds.before(time)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def after(time)
|
|
197
|
+
@seconds.after(time)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
# = Numeric Extensions for Durations
|
|
202
|
+
#
|
|
203
|
+
module Numeric
|
|
204
|
+
|
|
205
|
+
# Enables the use of time calculations and declarations,
|
|
206
|
+
# like 45.minutes + 2.hours + 4.years. The base unit for
|
|
207
|
+
# all of these Numeric time methods is seconds.
|
|
208
|
+
def seconds ; Duration[self] ; end
|
|
209
|
+
alias_method :second, :seconds
|
|
210
|
+
|
|
211
|
+
# Converts minutes into seconds.
|
|
212
|
+
def minutes ; Duration[self * 60] ; end
|
|
213
|
+
alias_method :minute, :minutes
|
|
214
|
+
|
|
215
|
+
# Converts hours into seconds.
|
|
216
|
+
def hours ; Duration[self * 3600] ; end
|
|
217
|
+
alias_method :hour, :hours
|
|
218
|
+
#def as_hours ; self / 60.minutes ; end
|
|
219
|
+
|
|
220
|
+
# Converts days into seconds.
|
|
221
|
+
def days ; Duration[self * 86400] ; end
|
|
222
|
+
alias_method :day, :days
|
|
223
|
+
|
|
224
|
+
# Converts weeks into seconds.
|
|
225
|
+
def weeks ; Duration[self * 604800] ; end
|
|
226
|
+
alias_method :week, :weeks
|
|
227
|
+
|
|
228
|
+
# Converts fortnights into seconds.
|
|
229
|
+
# (A fortnight is 2 weeks)
|
|
230
|
+
def fortnights ; Duration[self * 1209600] ; end
|
|
231
|
+
alias_method :fortnight, :fortnights
|
|
232
|
+
|
|
233
|
+
# Converts months into seconds.
|
|
234
|
+
# WARNING: This is not exact as it assumes 30 days to a month.
|
|
235
|
+
def months ; Duration[self * 30 * 86400] ; end
|
|
236
|
+
alias_method :month, :months
|
|
237
|
+
|
|
238
|
+
# Converts years into seconds.
|
|
239
|
+
# WARNING: This is not exact as it assumes 365 days to a year.
|
|
240
|
+
# ie. It doesn not account for leap years.
|
|
241
|
+
def years ; Duration[self * 365 * 86400, :years] ; end
|
|
242
|
+
alias_method :year, :years
|
|
243
|
+
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Time#duration has been added to convert the UNIX timestamp into a Duration.
|
|
247
|
+
# See Time#duration for an example.
|
|
248
|
+
#
|
|
249
|
+
module Time
|
|
250
|
+
# Create a Duration object from the UNIX timestamp.
|
|
251
|
+
#
|
|
252
|
+
# *Example*
|
|
253
|
+
#
|
|
254
|
+
# Time.now.duration
|
|
255
|
+
# => #<Duration: 1898 weeks, 6 days, 1 hour, 12 minutes and 1 second>
|
|
256
|
+
#
|
|
257
|
+
def duration
|
|
258
|
+
Duration[to_i]
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
class Numeric
|
|
265
|
+
include Duration::Numeric
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
class Time
|
|
269
|
+
include Duration::Time
|
|
270
|
+
end
|
|
271
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
# Add #exclude
|
|
21
|
+
module Enumerable
|
|
22
|
+
unless method_defined?(:exclude?)
|
|
23
|
+
# The inverse of #include?.
|
|
24
|
+
#
|
|
25
|
+
# @example
|
|
26
|
+
# [:a, :b].exclude?(:c) # => true
|
|
27
|
+
# [:a, :b].exclude?(:a) # => false
|
|
28
|
+
#
|
|
29
|
+
# @api public
|
|
30
|
+
def exclude?(object)
|
|
31
|
+
!include?(object)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
require 'thread' unless defined?(Thread)
|
|
21
|
+
require 'tempfile' unless defined?(Tempfile)
|
|
22
|
+
require 'fileutils' unless defined?(FileUtils)
|
|
23
|
+
|
|
24
|
+
class File
|
|
25
|
+
|
|
26
|
+
def self.atomic_id
|
|
27
|
+
@atomic_id ||= 0
|
|
28
|
+
@atomic_id += 1
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Same as `File.open`, but acts on a temporary copy of named
|
|
32
|
+
# file, copying the file back to the original on completion.
|
|
33
|
+
#
|
|
34
|
+
# @uncommon
|
|
35
|
+
# require 'facets/fileutils/atomic_open'
|
|
36
|
+
#
|
|
37
|
+
def self.atomic_open(file_name, mode="r", temp_dir=nil, &block)
|
|
38
|
+
temp_dir = temp_dir || Dir.tmpdir
|
|
39
|
+
temp_file = Tempfile.new("#{aomtic_id}-" + basename(file_name), temp_dir)
|
|
40
|
+
|
|
41
|
+
if File.exist?(file_name)
|
|
42
|
+
FileUtils.cp(file_name, temp_file)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
open(temp_file, mode, &block)
|
|
46
|
+
|
|
47
|
+
FileUtils.cp(temp_file, file_name)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Write to a file atomically. Useful for situations where you don't
|
|
51
|
+
# want other processes or threads to see half-written files.
|
|
52
|
+
#
|
|
53
|
+
# File.atomic_write("important.txt") do |file|
|
|
54
|
+
# file.write("hello")
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# If your temporary directory is not on the same filesystem as the file you're
|
|
58
|
+
# trying to write, you can provide a different temporary directory.
|
|
59
|
+
#
|
|
60
|
+
# File.atomic_write("important.txt", "tmp") do |file|
|
|
61
|
+
# file.write("hello")
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# NOTE: This method is not a common core extension and is not
|
|
65
|
+
# loaded automatically when using <code>require 'facets'</code>.
|
|
66
|
+
#
|
|
67
|
+
# CREDIT: David Heinemeier Hansson
|
|
68
|
+
#
|
|
69
|
+
# @uncommon
|
|
70
|
+
# require 'facets/fileutils/atomic_write'
|
|
71
|
+
#
|
|
72
|
+
def self.atomic_write(file_name, temp_dir=nil)
|
|
73
|
+
temp_dir = temp_dir || Dir.tmpdir
|
|
74
|
+
temp_file = Tempfile.new(basename(file_name), temp_dir)
|
|
75
|
+
|
|
76
|
+
yield temp_file
|
|
77
|
+
temp_file.close
|
|
78
|
+
|
|
79
|
+
begin
|
|
80
|
+
## Get original file permissions
|
|
81
|
+
old_stat = stat(file_name)
|
|
82
|
+
rescue Errno::ENOENT
|
|
83
|
+
## No old permissions, write a temp file to determine the defaults
|
|
84
|
+
check_name = join(dirname(file_name), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}")
|
|
85
|
+
open(check_name, "w") { }
|
|
86
|
+
old_stat = stat(check_name)
|
|
87
|
+
unlink(check_name)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
## Overwrite original file with temp file
|
|
91
|
+
FileUtils.mv(temp_file.path, file_name)
|
|
92
|
+
|
|
93
|
+
## Set correct permissions on new file
|
|
94
|
+
chown(old_stat.uid, old_stat.gid, file_name)
|
|
95
|
+
chmod(old_stat.mode, file_name)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Reads in a file, removes blank lines and removes lines starting
|
|
99
|
+
# with '#' and then returns an array of all the remaining lines.
|
|
100
|
+
#
|
|
101
|
+
# Thr remark indicator can be overridden via the +:omit:+ option, which
|
|
102
|
+
# can be a regualar expression or a string that is match against the
|
|
103
|
+
# start of a line.
|
|
104
|
+
#
|
|
105
|
+
# CREDIT: Trans
|
|
106
|
+
|
|
107
|
+
def self.read_list(filepath, options={})
|
|
108
|
+
chomp = options[:chomp]
|
|
109
|
+
omit = case options[:omit]
|
|
110
|
+
when Regexp
|
|
111
|
+
omit
|
|
112
|
+
when nil
|
|
113
|
+
/^\s*\#/
|
|
114
|
+
else
|
|
115
|
+
/^\s*#{Regexp.escape(omit)}/
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
list = []
|
|
119
|
+
readlines(filepath).each do |line|
|
|
120
|
+
line = line.strip.chomp(chomp)
|
|
121
|
+
next if line.empty?
|
|
122
|
+
next if omit === line
|
|
123
|
+
list << line
|
|
124
|
+
end
|
|
125
|
+
list
|
|
126
|
+
end
|
|
127
|
+
end
|