logging 0.7.0 → 0.7.1

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.
@@ -1,3 +1,11 @@
1
+ == 0.7.1 / 2008-
2
+
3
+ 1 minor enhancement
4
+ - Removed dependency on the Lockfile gem (brought the ruby
5
+ file into the logging/stelan directory)
6
+ 1 bug fix
7
+ - Fixed bug with age based rolling: was not multi-process safe
8
+
1
9
  == 0.7.0 / 2008-02-12
2
10
 
3
11
  1 major enhancement
@@ -20,8 +20,11 @@ lib/logging/log_event.rb
20
20
  lib/logging/logger.rb
21
21
  lib/logging/repository.rb
22
22
  lib/logging/root_logger.rb
23
+ lib/logging/stelan/lockfile.rb
23
24
  lib/logging/utils.rb
25
+ tasks/ann.rake
24
26
  tasks/annotations.rake
27
+ tasks/bones.rake
25
28
  tasks/doc.rake
26
29
  tasks/gem.rake
27
30
  tasks/manifest.rake
data/README.txt CHANGED
@@ -1,21 +1,22 @@
1
1
  Logging
2
+ by Tim Pease
2
3
 
3
4
  * {Homepage}[http://logging.rubyforge.org/]
4
5
  * {Rubyforge Project}[http://rubyforge.org/projects/logging]
5
6
  * email tim dot pease at gmail dot com
6
7
 
7
- == DESCRIPTION:
8
+ == DESCRIPTION
8
9
 
9
10
  Logging is a flexible logging library for use in Ruby programs based on the
10
11
  design of Java's log4j library. It features a hierarchical logging system,
11
12
  custom level names, multiple output destinations per log event, custom
12
13
  formatting, and more.
13
14
 
14
- == INSTALL:
15
+ == INSTALL
15
16
 
16
17
  sudo gem install logging
17
18
 
18
- == EXAMPLE:
19
+ == EXAMPLE
19
20
 
20
21
  This example configures a logger to output messages in a format similar to the
21
22
  core ruby Logger class. Only log messages that are warnings or higher will be
@@ -35,8 +36,10 @@ file. Only log messages that are informational or higher will be logged.
35
36
  require 'logging'
36
37
 
37
38
  logger = Logging::Logger['example_logger']
38
- logger.add Logging::Appender.stdout
39
- logger.add Logging::Appenders::File.new('example.log')
39
+ logger.add_appenders(
40
+ Logging::Appender.stdout,
41
+ Logging::Appenders::File.new('example.log')
42
+ )
40
43
  logger.level = :info
41
44
 
42
45
  logger.debug "this debug message will not be output by the logger"
@@ -72,7 +75,7 @@ the recommended way of accomplishing this.
72
75
  end
73
76
  end
74
77
 
75
- == NOTES:
78
+ == NOTES
76
79
 
77
80
  Although Logging is intended to supersede Log4r, it is not a one-to-one
78
81
  replacement for the Log4r library. Most notably is the difference in namespaces
@@ -81,10 +84,10 @@ Logging::Appender and renaming Log4r::Formatter to Logging::Layout. These
81
84
  changes were meant to bring the Logging class names more in line with the Log4j
82
85
  class names.
83
86
 
84
- == REQUIREMENTS:
87
+ == REQUIREMENTS
85
88
 
86
89
  Logging does not depend on any other installed libraries or gems.
87
90
 
88
- == LICENSE:
91
+ == LICENSE
89
92
 
90
93
  Ruby
data/Rakefile CHANGED
@@ -18,11 +18,10 @@ PROJ.rdoc_dir = 'doc/rdoc'
18
18
  PROJ.rdoc_remote_dir = ''
19
19
  PROJ.version = Logging::VERSION
20
20
 
21
- PROJ.exclude << '^tags$' << '^tasks/archive' << '^coverage'
21
+ PROJ.exclude += %w[^tags$ ^tasks/archive ^coverage]
22
22
  PROJ.rdoc_exclude << '^data'
23
23
  PROJ.svn = true
24
24
 
25
25
  depend_on 'flexmock'
26
- depend_on 'lockfile'
27
26
 
28
27
  # EOF
@@ -1,4 +1,4 @@
1
- # $Id: logging.rb 98 2008-02-13 00:40:28Z tim_pease $
1
+ # $Id: logging.rb 105 2008-02-26 04:43:21Z tim_pease $
2
2
 
3
3
  # Equivalent to a header guard in C/C++
4
4
  # Used to prevent the class/module from being loaded more than once
@@ -12,7 +12,7 @@ unless defined? Logging
12
12
  module Logging
13
13
 
14
14
  # :stopdoc:
15
- VERSION = '0.7.0'
15
+ VERSION = '0.7.1'
16
16
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
17
17
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
18
18
  WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM
@@ -1,19 +1,6 @@
1
- # $Id: rolling_file.rb 97 2008-02-13 00:32:18Z tim_pease $
2
-
3
- begin
4
- require 'lockfile'
5
- rescue LoadError
6
- require 'rubygems'
7
- require 'lockfile'
8
- end
9
-
10
- # FIXME: bug when truncating a rolling file on create
11
- # If there is not log file in existence, it is created and then
12
- # immediately rolld resulting in two log files
13
- #
14
- # This appears to be because of rails -- creating the logfile and
15
- # then we replace the default logger with a rolling file appender. It
16
- # sees the already existing log file and happily rolls it right over.
1
+ # $Id: rolling_file.rb 106 2008-02-26 04:52:42Z tim_pease $
2
+
3
+ require Logging.libpath(*%w[logging stelan lockfile])
17
4
 
18
5
  module Logging::Appenders
19
6
 
@@ -88,7 +75,7 @@ module Logging::Appenders
88
75
  @size = opts.getopt(:size, :as => Integer)
89
76
 
90
77
  @lockfile = if opts.getopt(:safe, false) and !::Logging::WIN32
91
- Lockfile.new(
78
+ ::Logging::Lockfile.new(
92
79
  @fn + '.lck',
93
80
  :retries => 1,
94
81
  :timeout => 2
@@ -96,39 +83,38 @@ module Logging::Appenders
96
83
  end
97
84
 
98
85
  code = 'def sufficiently_aged?() false end'
86
+ @age_fn = @fn + '.age'
99
87
 
100
88
  case @age = opts.getopt(:age)
101
89
  when 'daily'
102
- @start_time = Time.now
90
+ FileUtils.touch(@age_fn) unless test(?f, @age_fn)
103
91
  code = <<-CODE
104
92
  def sufficiently_aged?
105
93
  now = Time.now
106
- if (now.day != @start_time.day) or (now - @start_time) > 86400
107
- @start_time = now
94
+ start = ::File.mtime(@age_fn)
95
+ if (now.day != start.day) or (now - start) > 86400
108
96
  return true
109
97
  end
110
98
  false
111
99
  end
112
100
  CODE
113
101
  when 'weekly'
114
- @start_time = Time.now
102
+ FileUtils.touch(@age_fn) unless test(?f, @age_fn)
115
103
  code = <<-CODE
116
104
  def sufficiently_aged?
117
- now = Time.now
118
- if (now - @start_time) > 604800
119
- @start_time = now
105
+ if (Time.now - ::File.mtime(@age_fn)) > 604800
120
106
  return true
121
107
  end
122
108
  false
123
109
  end
124
110
  CODE
125
111
  when 'monthly'
126
- @start_time = Time.now
112
+ FileUtils.touch(@age_fn) unless test(?f, @age_fn)
127
113
  code = <<-CODE
128
114
  def sufficiently_aged?
129
115
  now = Time.now
130
- if (now.month != @start_time.month) or (now - @start_time) > 2678400
131
- @start_time = now
116
+ start = ::File.mtime(@age_fn)
117
+ if (now.month != start.month) or (now - start) > 2678400
132
118
  return true
133
119
  end
134
120
  false
@@ -136,12 +122,10 @@ module Logging::Appenders
136
122
  CODE
137
123
  when Integer, String
138
124
  @age = Integer(@age)
139
- @start_time = Time.now
125
+ FileUtils.touch(@age_fn) unless test(?f, @age_fn)
140
126
  code = <<-CODE
141
127
  def sufficiently_aged?
142
- now = Time.now
143
- if (now - @start_time) > @age
144
- @start_time = now
128
+ if (Time.now - ::File.mtime(@age_fn)) > @age
145
129
  return true
146
130
  end
147
131
  false
@@ -264,6 +248,9 @@ module Logging::Appenders
264
248
 
265
249
  # finally reanme the base log file
266
250
  ::File.rename(@fn, sprintf(@logname_fmt, 1))
251
+
252
+ # touch the age file if needed
253
+ FileUtils.touch(@age_fn) if @age
267
254
  end
268
255
 
269
256
  # call-seq:
@@ -0,0 +1,530 @@
1
+ # $Id: lockfile.rb 101 2008-02-13 17:10:47Z tim_pease $
2
+
3
+ # This file was stolen with permission from Ara T. Howrad's gem of the same
4
+ # name. The only difference is the removal of Ara's vim folding turds and
5
+ # making the code work with Ruby1.9
6
+
7
+ unless(defined?($__logging_lockfile__) or defined?(Logging::Lockfile))
8
+
9
+ require 'socket'
10
+ require 'timeout'
11
+ require 'fileutils'
12
+
13
+ module Logging
14
+ class Lockfile
15
+
16
+ VERSION = '1.4.3'
17
+ def version() VERSION end
18
+
19
+ class LockError < StandardError; end
20
+ class StolenLockError < LockError; end
21
+ class StackingLockError < LockError; end
22
+ class StatLockError < LockError; end
23
+ class MaxTriesLockError < LockError; end
24
+ class TimeoutLockError < LockError; end
25
+ class NFSLockError < LockError; end
26
+ class UnLockError < LockError; end
27
+
28
+ class SleepCycle < Array
29
+ attr :min
30
+ attr :max
31
+ attr :range
32
+ attr :inc
33
+
34
+ def initialize( min, max, inc )
35
+ @min, @max, @inc = Float(min), Float(max), Float(inc)
36
+ @range = @max - @min
37
+ raise RangeError, "max(#{ @max }) <= min(#{ @min })" if @max <= @min
38
+ raise RangeError, "inc(#{ @inc }) > range(#{ @range })" if @inc > @range
39
+ raise RangeError, "inc(#{ @inc }) <= 0" if @inc <= 0
40
+ raise RangeError, "range(#{ @range }) <= 0" if @range <= 0
41
+ s = @min
42
+ push(s) and s += @inc while(s <= @max)
43
+ self[-1] = @max if self[-1] < @max
44
+ reset
45
+ end
46
+
47
+ def next
48
+ ret = self[@idx]
49
+ @idx = ((@idx + 1) % self.size)
50
+ ret
51
+ end
52
+
53
+ def reset
54
+ @idx = 0
55
+ end
56
+ end # class SleepCycle
57
+
58
+ HOSTNAME = Socket::gethostname
59
+
60
+ DEFAULT_RETRIES = nil # maximum number of attempts
61
+ DEFAULT_TIMEOUT = nil # the longest we will try
62
+ DEFAULT_MAX_AGE = 3600 # lockfiles older than this are stale
63
+ DEFAULT_SLEEP_INC = 2 # sleep cycle is this much longer each time
64
+ DEFAULT_MIN_SLEEP = 2 # shortest sleep time
65
+ DEFAULT_MAX_SLEEP = 32 # longest sleep time
66
+ DEFAULT_SUSPEND = 1800 # iff we steal a lock wait this long before we go on
67
+ DEFAULT_REFRESH = 8 # how often we touch/validate the lock
68
+ DEFAULT_DONT_CLEAN = false # iff we leave lock files lying around
69
+ DEFAULT_POLL_RETRIES = 16 # this many polls makes one 'try'
70
+ DEFAULT_POLL_MAX_SLEEP = 0.08 # the longest we'll sleep between polls
71
+ DEFAULT_DONT_SWEEP = false # if we cleanup after other process on our host
72
+ DEFAULT_DONT_USE_LOCK_ID = false # if we dump lock info into lockfile
73
+
74
+ DEFAULT_DEBUG = ENV['LOCKFILE_DEBUG'] || false
75
+
76
+ class << self
77
+ attr_accessor :retries
78
+ attr_accessor :max_age
79
+ attr_accessor :sleep_inc
80
+ attr_accessor :min_sleep
81
+ attr_accessor :max_sleep
82
+ attr_accessor :suspend
83
+ attr_accessor :timeout
84
+ attr_accessor :refresh
85
+ attr_accessor :debug
86
+ attr_accessor :dont_clean
87
+ attr_accessor :poll_retries
88
+ attr_accessor :poll_max_sleep
89
+ attr_accessor :dont_sweep
90
+ attr_accessor :dont_use_lock_id
91
+
92
+ def init
93
+ @retries = DEFAULT_RETRIES
94
+ @max_age = DEFAULT_MAX_AGE
95
+ @sleep_inc = DEFAULT_SLEEP_INC
96
+ @min_sleep = DEFAULT_MIN_SLEEP
97
+ @max_sleep = DEFAULT_MAX_SLEEP
98
+ @suspend = DEFAULT_SUSPEND
99
+ @timeout = DEFAULT_TIMEOUT
100
+ @refresh = DEFAULT_REFRESH
101
+ @dont_clean = DEFAULT_DONT_CLEAN
102
+ @poll_retries = DEFAULT_POLL_RETRIES
103
+ @poll_max_sleep = DEFAULT_POLL_MAX_SLEEP
104
+ @dont_sweep = DEFAULT_DONT_SWEEP
105
+ @dont_use_lock_id = DEFAULT_DONT_USE_LOCK_ID
106
+
107
+ @debug = DEFAULT_DEBUG
108
+
109
+ STDOUT.sync = true if @debug
110
+ STDERR.sync = true if @debug
111
+ end
112
+ end
113
+ self.init
114
+
115
+ attr :klass
116
+ attr :path
117
+ attr :opts
118
+ attr :locked
119
+ attr :thief
120
+ attr :dirname
121
+ attr :basename
122
+ attr :clean
123
+ attr :retries
124
+ attr :max_age
125
+ attr :sleep_inc
126
+ attr :min_sleep
127
+ attr :max_sleep
128
+ attr :suspend
129
+ attr :refresh
130
+ attr :timeout
131
+ attr :dont_clean
132
+ attr :poll_retries
133
+ attr :poll_max_sleep
134
+ attr :dont_sweep
135
+ attr :dont_use_lock_id
136
+
137
+ attr_accessor :debug
138
+
139
+ alias thief? thief
140
+ alias locked? locked
141
+ alias debug? debug
142
+
143
+ def self::create( path, *a, &b )
144
+ opts = {
145
+ 'retries' => 0,
146
+ 'min_sleep' => 0,
147
+ 'max_sleep' => 1,
148
+ 'sleep_inc' => 1,
149
+ 'max_age' => nil,
150
+ 'suspend' => 0,
151
+ 'refresh' => nil,
152
+ 'timeout' => nil,
153
+ 'poll_retries' => 0,
154
+ 'dont_clean' => true,
155
+ 'dont_sweep' => false,
156
+ 'dont_use_lock_id' => true
157
+ }
158
+ begin
159
+ new(path, opts).lock
160
+ rescue LockError
161
+ raise Errno::EEXIST, path
162
+ end
163
+ open(path, *a, &b)
164
+ end
165
+
166
+ def initialize( path, opts = {}, &block )
167
+ @klass = self.class
168
+ @path = path
169
+ @opts = opts
170
+
171
+ @retries = getopt 'retries' , @klass.retries
172
+ @max_age = getopt 'max_age' , @klass.max_age
173
+ @sleep_inc = getopt 'sleep_inc' , @klass.sleep_inc
174
+ @min_sleep = getopt 'min_sleep' , @klass.min_sleep
175
+ @max_sleep = getopt 'max_sleep' , @klass.max_sleep
176
+ @suspend = getopt 'suspend' , @klass.suspend
177
+ @timeout = getopt 'timeout' , @klass.timeout
178
+ @refresh = getopt 'refresh' , @klass.refresh
179
+ @dont_clean = getopt 'dont_clean' , @klass.dont_clean
180
+ @poll_retries = getopt 'poll_retries' , @klass.poll_retries
181
+ @poll_max_sleep = getopt 'poll_max_sleep' , @klass.poll_max_sleep
182
+ @dont_sweep = getopt 'dont_sweep' , @klass.dont_sweep
183
+ @dont_use_lock_id = getopt 'dont_use_lock_id' , @klass.dont_use_lock_id
184
+ @debug = getopt 'debug' , @klass.debug
185
+
186
+ @sleep_cycle = SleepCycle::new @min_sleep, @max_sleep, @sleep_inc
187
+
188
+ @clean = @dont_clean ? nil : lambda{ File::unlink @path rescue nil }
189
+ @dirname = File::dirname @path
190
+ @basename = File::basename @path
191
+ @thief = false
192
+ @locked = false
193
+
194
+ lock(&block) if block
195
+ end
196
+
197
+ def lock
198
+ raise StackingLockError, "<#{ @path }> is locked!" if @locked
199
+
200
+ sweep unless @dont_sweep
201
+
202
+ ret = nil
203
+
204
+ attempt do
205
+ begin
206
+ @sleep_cycle.reset
207
+ create_tmplock do |f|
208
+ begin
209
+ Timeout::timeout(@timeout) do
210
+ tmp_path = f.path
211
+ tmp_stat = f.lstat
212
+ n_retries = 0
213
+ trace{ "attempting to lock <#{ @path }>..." }
214
+ begin
215
+ i = 0
216
+ begin
217
+ trace{ "polling attempt <#{ i }>..." }
218
+ begin
219
+ File::link tmp_path, @path
220
+ rescue Errno::ENOENT
221
+ try_again!
222
+ end
223
+ lock_stat = File::lstat @path
224
+ raise StatLockError, "stat's do not agree" unless
225
+ tmp_stat.rdev == lock_stat.rdev and tmp_stat.ino == lock_stat.ino
226
+ trace{ "aquired lock <#{ @path }>" }
227
+ @locked = true
228
+ rescue => e
229
+ i += 1
230
+ unless i >= @poll_retries
231
+ t = [rand(@poll_max_sleep), @poll_max_sleep].min
232
+ trace{ "poll sleep <#{ t }>..." }
233
+ sleep t
234
+ retry
235
+ end
236
+ raise
237
+ end
238
+
239
+ rescue => e
240
+ n_retries += 1
241
+ trace{ "n_retries <#{ n_retries }>" }
242
+ case validlock?
243
+ when true
244
+ raise MaxTriesLockError, "surpased retries <#{ @retries }>" if
245
+ @retries and n_retries >= @retries
246
+ trace{ "found valid lock" }
247
+ sleeptime = @sleep_cycle.next
248
+ trace{ "sleep <#{ sleeptime }>..." }
249
+ sleep sleeptime
250
+ when false
251
+ trace{ "found invalid lock and removing" }
252
+ begin
253
+ File::unlink @path
254
+ @thief = true
255
+ warn "<#{ @path }> stolen by <#{ Process.pid }> at <#{ timestamp }>"
256
+ trace{ "i am a thief!" }
257
+ rescue Errno::ENOENT
258
+ end
259
+ trace{ "suspending <#{ @suspend }>" }
260
+ sleep @suspend
261
+ when nil
262
+ raise MaxTriesLockError, "surpased retries <#{ @retries }>" if
263
+ @retries and n_retries >= @retries
264
+ end
265
+ retry
266
+ end # begin
267
+ end # timeout
268
+ rescue Timeout::Error
269
+ raise TimeoutLockError, "surpassed timeout <#{ @timeout }>"
270
+ end # begin
271
+ end # create_tmplock
272
+
273
+ if block_given?
274
+ stolen = false
275
+ refresher = (@refresh ? new_refresher : nil)
276
+ begin
277
+ begin
278
+ ret = yield @path
279
+ rescue StolenLockError
280
+ stolen = true
281
+ raise
282
+ end
283
+ ensure
284
+ begin
285
+ refresher.kill if refresher and refresher.status
286
+ ensure
287
+ unlock unless stolen
288
+ end
289
+ end
290
+ else
291
+ ObjectSpace.define_finalizer self, @clean if @clean
292
+ ret = self
293
+ end
294
+ rescue Errno::ESTALE, Errno::EIO => e
295
+ raise(NFSLockError, errmsg(e))
296
+ end
297
+ end
298
+
299
+ return ret
300
+ end
301
+
302
+ def sweep
303
+ begin
304
+ glob = File::join(@dirname, ".*lck")
305
+ paths = Dir[glob]
306
+ paths.each do |path|
307
+ begin
308
+ basename = File::basename path
309
+ pat = %r/^\s*\.([^_]+)_([^_]+)/o
310
+ if pat.match(basename)
311
+ host, pid = $1, $2
312
+ else
313
+ next
314
+ end
315
+ host.gsub!(%r/^\.+|\.+$/,'')
316
+ quad = host.split %r/\./
317
+ host = quad.first
318
+ pat = %r/^\s*#{ host }/i
319
+ if pat.match(HOSTNAME) and %r/^\s*\d+\s*$/.match(pid)
320
+ unless alive?(pid)
321
+ trace{ "process <#{ pid }> on <#{ host }> is no longer alive" }
322
+ trace{ "sweeping <#{ path }>" }
323
+ FileUtils::rm_f path
324
+ else
325
+ trace{ "process <#{ pid }> on <#{ host }> is still alive" }
326
+ trace{ "ignoring <#{ path }>" }
327
+ end
328
+ else
329
+ trace{ "ignoring <#{ path }> generated by <#{ host }>" }
330
+ end
331
+ rescue
332
+ next
333
+ end
334
+ end
335
+ rescue => e
336
+ warn(errmsg(e))
337
+ end
338
+ end
339
+
340
+ def alive?( pid )
341
+ pid = Integer("#{ pid }")
342
+ begin
343
+ Process::kill 0, pid
344
+ true
345
+ rescue Errno::ESRCH
346
+ false
347
+ end
348
+ end
349
+
350
+ def unlock
351
+ raise UnLockError, "<#{ @path }> is not locked!" unless @locked
352
+ begin
353
+ File::unlink @path
354
+ rescue Errno::ENOENT
355
+ raise StolenLockError, @path
356
+ ensure
357
+ @thief = false
358
+ @locked = false
359
+ ObjectSpace.undefine_finalizer self if @clean
360
+ end
361
+ end
362
+
363
+ def new_refresher
364
+ Thread::new(Thread::current, @path, @refresh, @dont_use_lock_id) do |thread, path, refresh, dont_use_lock_id|
365
+ loop do
366
+ begin
367
+ touch path
368
+ trace{"touched <#{ path }> @ <#{ Time.now.to_f }>"}
369
+ unless dont_use_lock_id
370
+ loaded = load_lock_id(IO.read(path))
371
+ trace{"loaded <\n#{ loaded.inspect }\n>"}
372
+ raise unless loaded == @lock_id
373
+ end
374
+ sleep refresh
375
+ rescue Exception => e
376
+ trace{errmsg e}
377
+ thread.raise StolenLockError
378
+ Thread::exit
379
+ end
380
+ end
381
+ end
382
+ end
383
+
384
+ def validlock?
385
+ if @max_age
386
+ uncache @path rescue nil
387
+ begin
388
+ return((Time.now - File::stat(@path).mtime) < @max_age)
389
+ rescue Errno::ENOENT
390
+ return nil
391
+ end
392
+ else
393
+ exist = File::exist?(@path)
394
+ return(exist ? true : nil)
395
+ end
396
+ end
397
+
398
+ def uncache( file )
399
+ refresh = nil
400
+ begin
401
+ is_a_file = File === file
402
+ path = (is_a_file ? file.path : file.to_s)
403
+ stat = (is_a_file ? file.stat : File::stat(file.to_s))
404
+ refresh = tmpnam(File::dirname(path))
405
+ File::link path, refresh
406
+ File::chmod stat.mode, path
407
+ File::utime stat.atime, stat.mtime, path
408
+ ensure
409
+ begin
410
+ File::unlink refresh if refresh
411
+ rescue Errno::ENOENT
412
+ end
413
+ end
414
+ end
415
+
416
+ def create_tmplock
417
+ tmplock = tmpnam @dirname
418
+ begin
419
+ create(tmplock) do |f|
420
+ unless dont_use_lock_id
421
+ @lock_id = gen_lock_id
422
+ dumped = dump_lock_id
423
+ trace{"lock_id <\n#{ @lock_id.inspect }\n>"}
424
+ f.write dumped
425
+ f.flush
426
+ end
427
+ yield f
428
+ end
429
+ ensure
430
+ begin; File::unlink tmplock; rescue Errno::ENOENT; end if tmplock
431
+ end
432
+ end
433
+
434
+ def gen_lock_id
435
+ Hash[
436
+ 'host' => "#{ HOSTNAME }",
437
+ 'pid' => "#{ Process.pid }",
438
+ 'ppid' => "#{ Process.ppid }",
439
+ 'time' => timestamp
440
+ ]
441
+ end
442
+
443
+ def timestamp
444
+ time = Time.now
445
+ usec = time.usec.to_s
446
+ usec << '0' while usec.size < 6
447
+ "#{ time.strftime('%Y-%m-%d %H:%M:%S') }.#{ usec }"
448
+ end
449
+
450
+ def dump_lock_id lock_id = @lock_id
451
+ "host: %s\npid: %s\nppid: %s\ntime: %s\n" %
452
+ lock_id.values_at('host','pid','ppid','time')
453
+ end
454
+
455
+ def load_lock_id( buf )
456
+ lock_id = {}
457
+ kv = %r/([^:]+):(.*)/o
458
+ buf.each do |line|
459
+ m = kv.match line
460
+ k, v = m[1], m[2]
461
+ next unless m and k and v
462
+ lock_id[k.strip] = v.strip
463
+ end
464
+ lock_id
465
+ end
466
+
467
+ def tmpnam( dir, seed = File::basename($0) )
468
+ pid = Process.pid
469
+ time = Time.now
470
+ sec = time.to_i
471
+ usec = time.usec
472
+ "%s%s.%s_%d_%s_%d_%d_%d.lck" %
473
+ [dir, File::SEPARATOR, HOSTNAME, pid, seed, sec, usec, rand(sec)]
474
+ end
475
+
476
+ def create( path )
477
+ umask = nil
478
+ f = nil
479
+ begin
480
+ umask = File::umask 022
481
+ f = open path, File::WRONLY|File::CREAT|File::EXCL, 0644
482
+ ensure
483
+ File::umask umask if umask
484
+ end
485
+ return(block_given? ? begin; yield f; ensure; f.close; end : f)
486
+ end
487
+
488
+ def touch( path )
489
+ FileUtils.touch path
490
+ end
491
+
492
+ def getopt( key, default = nil )
493
+ [ key, key.to_s, key.to_s.intern ].each do |k|
494
+ return @opts[k] if @opts.has_key?(k)
495
+ end
496
+ return default
497
+ end
498
+
499
+ def to_str
500
+ @path
501
+ end
502
+ alias to_s to_str
503
+
504
+ def trace( s = nil )
505
+ STDERR.puts((s ? s : yield)) if @debug
506
+ end
507
+
508
+ def errmsg( e )
509
+ "%s (%s)\n%s\n" % [e.class, e.message, e.backtrace.join("\n")]
510
+ end
511
+
512
+ def attempt
513
+ ret = nil
514
+ loop{ break unless catch('attempt'){ ret = yield } == 'try_again' }
515
+ ret
516
+ end
517
+
518
+ def try_again!
519
+ throw 'attempt', 'try_again'
520
+ end
521
+ alias again! try_again!
522
+
523
+ def give_up!
524
+ throw 'attempt', 'give_up'
525
+ end
526
+ end # class Lockfile
527
+ end # module Logging
528
+
529
+ $__logging_lockfile__ = __FILE__
530
+ end
@@ -0,0 +1,76 @@
1
+ # $Id: ann.rake 105 2008-02-26 04:43:21Z tim_pease $
2
+
3
+ begin
4
+ require 'bones/smtp_tls'
5
+ rescue LoadError
6
+ require 'net/smtp'
7
+ end
8
+ require 'time'
9
+
10
+ namespace :ann do
11
+
12
+ file PROJ.ann_file do
13
+ puts "Generating #{PROJ.ann_file}"
14
+ File.open(PROJ.ann_file,'w') do |fd|
15
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
16
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
17
+ fd.puts(" #{PROJ.url}") if PROJ.url
18
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
19
+ fd.puts
20
+ fd.puts("== DESCRIPTION")
21
+ fd.puts
22
+ fd.puts(PROJ.description)
23
+ fd.puts
24
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
25
+ fd.puts
26
+ PROJ.ann_paragraphs.each do |p|
27
+ fd.puts "== #{p.upcase}"
28
+ fd.puts
29
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
30
+ fd.puts
31
+ end
32
+ fd.puts PROJ.ann_text if PROJ.ann_text
33
+ end
34
+ end
35
+
36
+ desc "Create an announcement file"
37
+ task :announcement => PROJ.ann_file
38
+
39
+ desc "Send an email announcement"
40
+ task :email => PROJ.ann_file do
41
+ from = PROJ.ann_email[:from] || PROJ.email
42
+ to = Array(PROJ.ann_email[:to])
43
+
44
+ ### build a mail header for RFC 822
45
+ rfc822msg = "From: #{from}\n"
46
+ rfc822msg << "To: #{to.join(',')}\n"
47
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
48
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
49
+ rfc822msg << "\n"
50
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
51
+ rfc822msg << "Message-Id: "
52
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{PROJ.ann_email[:domain]}>\n\n"
53
+ rfc822msg << File.read(PROJ.ann_file)
54
+
55
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
56
+ PROJ.ann_email[key]
57
+ end
58
+
59
+ params[3] = PROJ.email if params[3].nil?
60
+
61
+ if params[4].nil?
62
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
63
+ params[4] = STDIN.gets.chomp
64
+ end
65
+
66
+ ### send email
67
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
68
+ end
69
+ end # namespace :ann
70
+
71
+ desc 'Alias to ann:announcement'
72
+ task :ann => 'ann:announcement'
73
+
74
+ CLOBBER << PROJ.ann_file
75
+
76
+ # EOF
@@ -1,4 +1,4 @@
1
- # $Id: annotations.rake 87 2008-02-08 17:21:07Z tim_pease $
1
+ # $Id$
2
2
 
3
3
  if HAVE_BONES
4
4
 
@@ -0,0 +1,40 @@
1
+ # $Id: bones.rake 105 2008-02-26 04:43:21Z tim_pease $
2
+
3
+ require 'pp'
4
+ require 'stringio'
5
+
6
+ namespace :bones do
7
+
8
+ desc 'Show the PROJ open struct'
9
+ task :debug do |t|
10
+ atr = if ARGV.length == 2
11
+ t.application.top_level_tasks.pop
12
+ end
13
+ sio = StringIO.new
14
+ sep = "\n" + ' '*27
15
+ fmt = "%23s => %s"
16
+
17
+ if atr
18
+ PP.pp(PROJ.send(atr.to_sym), sio, 49)
19
+ sio.seek 0
20
+ val = sio.read
21
+ val = val.split("\n").join(sep)
22
+
23
+ puts fmt % [atr, val]
24
+ else
25
+ h = PROJ.instance_variable_get(:@table)
26
+ h.keys.map {|k| k.to_s}.sort.each do |k|
27
+ sio.truncate 0
28
+ PP.pp(h[k.to_sym], sio, 49)
29
+ sio.seek 0
30
+ val = sio.read
31
+ val = val.split("\n").join(sep)
32
+
33
+ puts fmt % [k, val]
34
+ end
35
+ end
36
+ end
37
+
38
+ end # namespace :bones
39
+
40
+ # EOF
@@ -31,7 +31,6 @@ namespace :doc do
31
31
  sh "#{RDOC} --ri -o ri ."
32
32
  end
33
33
 
34
- desc 'Remove ri products'
35
34
  task :clobber_ri do
36
35
  rm_r 'ri' rescue nil
37
36
  end
@@ -44,6 +43,6 @@ task :doc => 'doc:rdoc'
44
43
  desc 'Remove all build products'
45
44
  task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
46
45
 
47
- remove_desc_for_task %w(doc:clobber_rdoc doc:clobber_ri)
46
+ remove_desc_for_task %w(doc:clobber_rdoc)
48
47
 
49
48
  # EOF
@@ -12,6 +12,7 @@ namespace :gem do
12
12
  s.email = PROJ.email
13
13
  s.homepage = Array(PROJ.url).first
14
14
  s.rubyforge_project = PROJ.rubyforge_name
15
+ s.post_install_message = PROJ.post_install_message
15
16
 
16
17
  s.description = PROJ.description
17
18
 
@@ -62,9 +63,29 @@ namespace :gem do
62
63
  puts PROJ.spec.to_ruby
63
64
  end
64
65
 
65
- Rake::GemPackageTask.new(PROJ.spec) do |pkg|
66
+ pkg = Rake::PackageTask.new(PROJ.name, PROJ.version) do |pkg|
66
67
  pkg.need_tar = PROJ.need_tar
67
68
  pkg.need_zip = PROJ.need_zip
69
+ pkg.package_files += PROJ.spec.files
70
+ end
71
+ Rake::Task['gem:package'].instance_variable_set(:@full_comment, nil)
72
+
73
+ gem_file = if PROJ.spec.platform == Gem::Platform::RUBY
74
+ "#{pkg.package_name}.gem"
75
+ else
76
+ "#{pkg.package_name}-#{PROJ.spec.platform}.gem"
77
+ end
78
+
79
+ desc "Build the gem file #{gem_file}"
80
+ task :package => "#{pkg.package_dir}/#{gem_file}"
81
+
82
+ file "#{pkg.package_dir}/#{gem_file}" => [pkg.package_dir] + PROJ.spec.files do
83
+ when_writing("Creating GEM") {
84
+ Gem::Builder.new(PROJ.spec).build
85
+ verbose(true) {
86
+ mv gem_file, "#{pkg.package_dir}/#{gem_file}"
87
+ }
88
+ }
68
89
  end
69
90
 
70
91
  desc 'Install the gem'
@@ -74,9 +95,12 @@ namespace :gem do
74
95
 
75
96
  desc 'Uninstall the gem'
76
97
  task :uninstall do
77
- sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' -x #{PROJ.name}"
98
+ sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' -i -x #{PROJ.name}"
78
99
  end
79
100
 
101
+ desc 'Reinstall the gem'
102
+ task :reinstall => [:uninstall, :install]
103
+
80
104
  end # namespace :gem
81
105
 
82
106
  desc 'Alias to gem:package'
@@ -6,18 +6,11 @@ namespace :manifest do
6
6
 
7
7
  desc 'Verify the manifest'
8
8
  task :check do
9
- fn = 'Manifest.tmp'
10
- files = []
11
- exclude = Regexp.new(PROJ.exclude.join('|'))
12
- Find.find '.' do |path|
13
- path.sub! %r/^(\.\/|\/)/o, ''
14
- next unless test ?f, path
15
- next if path =~ exclude
16
- files << path
17
- end
9
+ fn = PROJ.manifest_file + '.tmp'
10
+ files = manifest_files
18
11
 
19
- File.open(fn, 'w') {|fp| fp.puts files.sort}
20
- lines = %x(#{DIFF} -du Manifest.txt #{fn}).split("\n")
12
+ File.open(fn, 'w') {|fp| fp.puts files}
13
+ lines = %x(#{DIFF} -du #{PROJ.manifest_file} #{fn}).split("\n")
21
14
  if HAVE_FACETS_ANSICODE and ENV.has_key?('TERM')
22
15
  lines.map! do |line|
23
16
  case line
@@ -34,19 +27,20 @@ namespace :manifest do
34
27
 
35
28
  desc 'Create a new manifest'
36
29
  task :create do
37
- fn = 'Manifest.txt'
38
- files = []
39
- exclude = Regexp.new(PROJ.exclude.join('|'))
40
- Find.find '.' do |path|
41
- path.sub! %r/^(\.\/|\/)/o, ''
42
- next unless test ?f, path
43
- next if path =~ exclude
44
- files << path
30
+ files = manifest_files
31
+ unless test(?f, PROJ.manifest_file)
32
+ files << PROJ.manifest_file
33
+ files.sort!
45
34
  end
35
+ File.open(PROJ.manifest_file, 'w') {|fp| fp.puts files}
36
+ end
46
37
 
47
- files << fn unless test ?f, fn
48
- File.open(fn, 'w') {|fp| fp.puts files.sort}
38
+ task :assert do
39
+ files = manifest_files
40
+ manifest = File.read(PROJ.manifest_file).split($/)
41
+ raise "ERROR: #{PROJ.manifest_file} is out of date" unless files == manifest
49
42
  end
43
+
50
44
  end # namespace :manifest
51
45
 
52
46
  desc 'Alias to manifest:check'
@@ -1,18 +1,30 @@
1
- # $Id$
1
+ # $Id: post_load.rake 105 2008-02-26 04:43:21Z tim_pease $
2
2
 
3
3
  # This file does not define any rake tasks. It is used to load some project
4
4
  # settings if they are not defined by the user.
5
5
 
6
- unless PROJ.changes
7
- PROJ.changes = paragraphs_of('History.txt', 0..1).join("\n\n")
8
- end
6
+ PROJ.rdoc_exclude << "^#{Regexp.escape(PROJ.manifest_file)}$"
7
+ PROJ.exclude << "^#{Regexp.escape(PROJ.ann_file)}$"
9
8
 
10
- unless PROJ.description
11
- PROJ.description = paragraphs_of('README.txt', 'description').join("\n\n")
12
- end
9
+ PROJ.exclude.flatten!
10
+ PROJ.rdoc_exclude.flatten!
11
+ PROJ.annotation_exclude.flatten!
13
12
 
14
- unless PROJ.summary
15
- PROJ.summary = PROJ.description.split('.').first
16
- end
13
+ PROJ.changes ||= paragraphs_of(PROJ.history_file, 0..1).join("\n\n")
14
+
15
+ PROJ.description ||= paragraphs_of(PROJ.readme_file, 'description').join("\n\n")
16
+
17
+ PROJ.summary ||= PROJ.description.split('.').first
18
+
19
+ PROJ.files ||=
20
+ if test(?f, PROJ.manifest_file)
21
+ files = File.readlines(PROJ.manifest_file).map {|fn| fn.chomp.strip}
22
+ files.delete ''
23
+ files
24
+ else [] end
25
+
26
+ PROJ.executables ||= PROJ.files.find_all {|fn| fn =~ %r/^bin/}
27
+
28
+ PROJ.rdoc_main ||= PROJ.readme_file
17
29
 
18
30
  # EOF
@@ -1,7 +1,8 @@
1
- # $Id: setup.rb 87 2008-02-08 17:21:07Z tim_pease $
1
+ # $Id: setup.rb 105 2008-02-26 04:43:21Z tim_pease $
2
2
 
3
3
  require 'rubygems'
4
4
  require 'rake'
5
+ require 'rake/clean'
5
6
  require 'fileutils'
6
7
  require 'ostruct'
7
8
 
@@ -17,6 +18,10 @@ PROJ.url = nil
17
18
  PROJ.version = ENV['VERSION'] || '0.0.0'
18
19
  PROJ.rubyforge_name = nil
19
20
  PROJ.exclude = %w(tmp$ bak$ ~$ CVS .svn/ ^pkg/ ^doc/)
21
+ PROJ.release_name = ENV['RELEASE']
22
+ PROJ.history_file = 'History.txt'
23
+ PROJ.manifest_file = 'Manifest.txt'
24
+ PROJ.readme_file = 'README.txt'
20
25
 
21
26
  # Rspec
22
27
  PROJ.specs = FileList['spec/**/*_spec.rb']
@@ -28,13 +33,16 @@ PROJ.test_file = 'test/all.rb'
28
33
  PROJ.test_opts = []
29
34
 
30
35
  # Rcov
36
+ PROJ.rcov_dir = 'coverage'
31
37
  PROJ.rcov_opts = ['--sort', 'coverage', '-T']
38
+ PROJ.rcov_threshold = 90.0
39
+ PROJ.rcov_threshold_exact = false
32
40
 
33
41
  # Rdoc
34
42
  PROJ.rdoc_opts = []
35
43
  PROJ.rdoc_include = %w(^lib/ ^bin/ ^ext/ .txt$)
36
- PROJ.rdoc_exclude = %w(extconf.rb$ ^Manifest.txt$)
37
- PROJ.rdoc_main = 'README.txt'
44
+ PROJ.rdoc_exclude = %w(extconf.rb$)
45
+ PROJ.rdoc_main = nil
38
46
  PROJ.rdoc_dir = 'doc'
39
47
  PROJ.rdoc_remote_dir = nil
40
48
 
@@ -45,16 +53,12 @@ PROJ.libs = []
45
53
  %w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
46
54
 
47
55
  # Gem Packaging
48
- PROJ.files =
49
- if test ?f, 'Manifest.txt'
50
- files = File.readlines('Manifest.txt').map {|fn| fn.chomp.strip}
51
- files.delete ''
52
- files
53
- else [] end
54
- PROJ.executables = PROJ.files.find_all {|fn| fn =~ %r/^bin/}
56
+ PROJ.files = nil
57
+ PROJ.executables = nil
55
58
  PROJ.dependencies = []
56
59
  PROJ.need_tar = true
57
60
  PROJ.need_zip = false
61
+ PROJ.post_install_message = nil
58
62
 
59
63
  # File Annotations
60
64
  PROJ.annotation_exclude = %w(^tasks/setup.rb$)
@@ -68,6 +72,21 @@ PROJ.svn_trunk = 'trunk'
68
72
  PROJ.svn_tags = 'tags'
69
73
  PROJ.svn_branches = 'branches'
70
74
 
75
+ # Announce
76
+ PROJ.ann_file = 'announcement.txt'
77
+ PROJ.ann_text = nil
78
+ PROJ.ann_paragraphs = []
79
+ PROJ.ann_email = {
80
+ :from => nil,
81
+ :to => %w(ruby-talk@ruby-lang.org),
82
+ :server => 'localhost',
83
+ :port => 25,
84
+ :domain => ENV['HOSTNAME'],
85
+ :acct => nil,
86
+ :passwd => nil,
87
+ :authtype => :plain
88
+ }
89
+
71
90
  # Load the other rake files in the tasks folder
72
91
  rakefiles = Dir.glob('tasks/*.rake').sort
73
92
  rakefiles.unshift(rakefiles.delete('tasks/post_load.rake')).compact!
@@ -100,8 +119,8 @@ SUDO = if WIN32 then ''
100
119
  else '' end
101
120
  end
102
121
 
103
- RCOV = WIN32 ? 'rcov.cmd' : 'rcov'
104
- GEM = WIN32 ? 'gem.cmd' : 'gem'
122
+ RCOV = WIN32 ? 'rcov.bat' : 'rcov'
123
+ GEM = WIN32 ? 'gem.bat' : 'gem'
105
124
 
106
125
  %w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
107
126
  begin
@@ -150,7 +169,10 @@ def depend_on( name, version = nil )
150
169
  spec = Gem.source_index.find_name(name).last
151
170
  version = spec.version.to_s if version.nil? and !spec.nil?
152
171
 
153
- PROJ.dependencies << (version.nil? ? [name] : [name, ">= #{version}"])
172
+ PROJ.dependencies << case version
173
+ when nil; [name]
174
+ when %r/^\d/; [name, ">= #{version}"]
175
+ else [name, version] end
154
176
  end
155
177
 
156
178
  # Adds the given arguments to the include path if they are not already there
@@ -187,4 +209,19 @@ def in_directory( dir, &block )
187
209
  end
188
210
  end
189
211
 
212
+ # Scans the current working directory and creates a list of files that are
213
+ # candidates to be in the manifest.
214
+ #
215
+ def manifest_files
216
+ files = []
217
+ exclude = Regexp.new(PROJ.exclude.join('|'))
218
+ Find.find '.' do |path|
219
+ path.sub! %r/^(\.\/|\/)/o, ''
220
+ next unless test ?f, path
221
+ next if path =~ exclude
222
+ files << path
223
+ end
224
+ files.sort!
225
+ end
226
+
190
227
  # EOF
@@ -6,7 +6,7 @@ namespace :test do
6
6
 
7
7
  Rake::TestTask.new(:run) do |t|
8
8
  t.libs = PROJ.libs
9
- t.test_files = if test ?f, PROJ.test_file then [PROJ.test_file]
9
+ t.test_files = if test(?f, PROJ.test_file) then [PROJ.test_file]
10
10
  else PROJ.tests end
11
11
  t.ruby_opts += PROJ.ruby_opts
12
12
  t.ruby_opts += PROJ.test_opts
@@ -15,14 +15,14 @@ namespace :test do
15
15
  if HAVE_RCOV
16
16
  desc 'Run rcov on the unit tests'
17
17
  task :rcov => :clobber_rcov do
18
- opts = PROJ.rcov_opts.join(' ')
19
- files = if test ?f, PROJ.test_file then [PROJ.test_file]
18
+ opts = PROJ.rcov_opts.dup << '-o' << PROJ.rcov_dir
19
+ opts = opts.join(' ')
20
+ files = if test(?f, PROJ.test_file) then [PROJ.test_file]
20
21
  else PROJ.tests end
21
22
  files = files.join(' ')
22
23
  sh "#{RCOV} #{files} #{opts}"
23
24
  end
24
25
 
25
- desc 'Remove rcov products'
26
26
  task :clobber_rcov do
27
27
  rm_r 'coverage' rescue nil
28
28
  end
@@ -35,6 +35,4 @@ task :test => 'test:run'
35
35
 
36
36
  task :clobber => 'test:clobber_rcov' if HAVE_RCOV
37
37
 
38
- remove_desc_for_task %w(test:clobber_rcov)
39
-
40
38
  # EOF
@@ -1,4 +1,4 @@
1
- # $Id: test_rolling_file.rb 97 2008-02-13 00:32:18Z tim_pease $
1
+ # $Id: test_rolling_file.rb 105 2008-02-26 04:43:21Z tim_pease $
2
2
 
3
3
  require File.join(File.dirname(__FILE__), %w[.. setup])
4
4
 
@@ -109,8 +109,10 @@ module TestAppenders
109
109
  ap << "random message\n"
110
110
  assert_equal 2, Dir.glob(@glob).length
111
111
 
112
- t = ap.instance_variable_get :@start_time
113
- ap.instance_variable_set :@start_time, t - 3600 * 24
112
+ age_fn = @fn + '.age'
113
+ now = ::File.mtime(age_fn)
114
+ start = now - 3600 * 24
115
+ ::File.utime(start, start, age_fn)
114
116
 
115
117
  sleep 0.250
116
118
  ap << "yet another random message\n"
@@ -122,8 +124,8 @@ module TestAppenders
122
124
  ap << "random message\n"
123
125
  assert_equal 3, Dir.glob(@glob).length
124
126
 
125
- t = ap.instance_variable_get :@start_time
126
- ap.instance_variable_set :@start_time, t - 3600 * 24 * 7
127
+ start = now - 3600 * 24 * 7
128
+ ::File.utime(start, start, age_fn)
127
129
 
128
130
  sleep 0.250
129
131
  ap << "yet another random message\n"
@@ -135,8 +137,8 @@ module TestAppenders
135
137
  ap << "random message\n"
136
138
  assert_equal 4, Dir.glob(@glob).length
137
139
 
138
- t = ap.instance_variable_get :@start_time
139
- ap.instance_variable_set :@start_time, t - 3600 * 24 * 31
140
+ start = now - 3600 * 24 * 31
141
+ ::File.utime(start, start, age_fn)
140
142
 
141
143
  sleep 0.250
142
144
  ap << "yet another random message\n"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logging
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Pease
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-02-12 00:00:00 -07:00
12
+ date: 2008-02-25 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -21,15 +21,6 @@ dependencies:
21
21
  - !ruby/object:Gem::Version
22
22
  version: 0.8.0
23
23
  version:
24
- - !ruby/object:Gem::Dependency
25
- name: lockfile
26
- version_requirement:
27
- version_requirements: !ruby/object:Gem::Requirement
28
- requirements:
29
- - - ">="
30
- - !ruby/object:Gem::Version
31
- version: 1.4.3
32
- version:
33
24
  description: Logging is a flexible logging library for use in Ruby programs based on the design of Java's log4j library. It features a hierarchical logging system, custom level names, multiple output destinations per log event, custom formatting, and more.
34
25
  email: tim.pease@gmail.com
35
26
  executables: []
@@ -62,8 +53,11 @@ files:
62
53
  - lib/logging/logger.rb
63
54
  - lib/logging/repository.rb
64
55
  - lib/logging/root_logger.rb
56
+ - lib/logging/stelan/lockfile.rb
65
57
  - lib/logging/utils.rb
58
+ - tasks/ann.rake
66
59
  - tasks/annotations.rake
60
+ - tasks/bones.rake
67
61
  - tasks/doc.rake
68
62
  - tasks/gem.rake
69
63
  - tasks/manifest.rake