assaf-uuid 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. metadata +5 -9
  2. data/CHANGELOG +0 -39
  3. data/Rakefile +0 -100
  4. data/lib/uuid.rb +0 -282
  5. data/test/test-uuid.rb +0 -82
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: assaf-uuid
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Assaf Arkin
@@ -10,11 +10,12 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2008-08-13 00:00:00 -07:00
13
+ date: 2009-05-16 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: macaddr
18
+ type: :runtime
18
19
  version_requirement:
19
20
  version_requirements: !ruby/object:Gem::Requirement
20
21
  requirements:
@@ -31,13 +32,8 @@ extensions: []
31
32
  extra_rdoc_files:
32
33
  - README.rdoc
33
34
  - MIT-LICENSE
34
- files:
35
- - test/test-uuid.rb
36
- - lib/uuid.rb
37
- - README.rdoc
38
- - MIT-LICENSE
39
- - Rakefile
40
- - CHANGELOG
35
+ files: []
36
+
41
37
  has_rdoc: true
42
38
  homepage: http://github.com/assaf/uuid
43
39
  post_install_message:
data/CHANGELOG DELETED
@@ -1,39 +0,0 @@
1
- 2.0.1 (Pending)
2
- * Fixed: MAC address parses correctly when using colon as separator, not
3
- when using hyphen (ruby-mingw32). If your MAC address is all zero
4
- (check with UUID.new.inspect), remove the ruby-uuid file, and it
5
- will reset to the actual MAC address. (Rasha)
6
- * Fixed: UUID.new.inspect not showing full MAC address.
7
-
8
- 2.0.0 (2008-08-28)
9
- * Changed: API. UUID.generate still works as it always did, but the rest of
10
- the API is brand spanking new, so if you rely on anything besides
11
- UUID.generate, or just curious, check out the rdocs.
12
- * Changed: uuid.state replaced by ruby-uuid file. By default stored in
13
- /var/tmp, or if that path is not accessible, as .ruby-uuid in the
14
- home directory.
15
- * Changed: ruby-uuid is now stored as binary file (faster read/write), if you
16
- need to have a peek, open irb and type UUID.new.inspect.
17
- * Changed: Source code and documentation for this release hosted on the
18
- wonderful Github: http://github.com/assaf/uuid
19
-
20
- 1.0.4 (2007-08-28)
21
- * Changed: By default creates the uuid.state file in the working directory,
22
- not in the installation directory, which requires sudo privileges
23
- (e.g. gem).
24
-
25
- 1.0.3 (2006-11-08)
26
- * Fixed: Work around YAML bug in serializing that occurs when MAC address
27
- consists only of decimal digits. Credit: ebuprofen"
28
-
29
- 1.0.2 (2006-08-19)
30
- * Changed: Constants are not conditionally defined (removes warnings when
31
- using in Rails.
32
-
33
- 1.0.1 (2006-07-27)
34
- * Added: Regular expressions to test if a string is a UUID.
35
- * Changed: When used in ActiveRecord, adds as callback instead of overriding
36
- save.
37
-
38
- 1.0.0 (2005-11-20)
39
- * Changed: Separated form reliable-msg into its own package.
data/Rakefile DELETED
@@ -1,100 +0,0 @@
1
- # Adapted from the rake Rakefile.
2
-
3
- require 'rubygems'
4
- require 'rake/testtask'
5
- require 'rake/rdoctask'
6
- require 'rake/gempackagetask'
7
- require 'rubygems/source_info_cache'
8
-
9
-
10
- spec = Gem::Specification.load(File.join(File.dirname(__FILE__), 'uuid.gemspec'))
11
-
12
- desc "Default Task"
13
- task 'default' => ['test', 'rdoc']
14
-
15
-
16
- desc "If you're building from sources, run this task first to setup the necessary dependencies"
17
- task 'setup' do
18
- windows = Config::CONFIG['host_os'] =~ /windows|cygwin|bccwin|cygwin|djgpp|mingw|mswin|wince/i
19
- rb_bin = File.expand_path(Config::CONFIG['ruby_install_name'], Config::CONFIG['bindir'])
20
- spec.dependencies.select { |dep| Gem::SourceIndex.from_installed_gems.search(dep).empty? }.each do |missing|
21
- dep = Gem::Dependency.new(missing.name, missing.version_requirements)
22
- spec = Gem::SourceInfoCache.search(dep, true, true).last
23
- fail "#{dep} not found in local or remote repository!" unless spec
24
- puts "Installing #{spec.full_name} ..."
25
- args = [rb_bin, '-S', 'gem', 'install', spec.name, '-v', spec.version.to_s]
26
- args.unshift('sudo') unless windows || ENV['GEM_HOME']
27
- sh args.map{ |a| a.inspect }.join(' ')
28
- end
29
- end
30
-
31
-
32
- desc "Run all test cases"
33
- Rake::TestTask.new do |test|
34
- test.verbose = true
35
- test.test_files = ['test/*.rb']
36
- test.warning = true
37
- end
38
-
39
- # Create the documentation.
40
- Rake::RDocTask.new do |rdoc|
41
- rdoc.main = 'README.rdoc'
42
- rdoc.rdoc_files.include('README.rdoc', 'lib/**/*.rb')
43
- rdoc.title = "UUID generator"
44
- end
45
-
46
-
47
- gem = Rake::GemPackageTask.new(spec) do |pkg|
48
- pkg.need_tar = true
49
- pkg.need_zip = true
50
- end
51
-
52
- desc "Install the package locally"
53
- task 'install'=>['setup', 'package'] do |task|
54
- rb_bin = File.expand_path(Config::CONFIG['ruby_install_name'], Config::CONFIG['bindir'])
55
- args = [rb_bin, '-S', 'gem', 'install', "pkg/#{spec.name}-#{spec.version}.gem"]
56
- windows = Config::CONFIG['host_os'] =~ /windows|cygwin|bccwin|cygwin|djgpp|mingw|mswin|wince/i
57
- args.unshift('sudo') unless windows || ENV['GEM_HOME']
58
- sh args.map{ |a| a.inspect }.join(' ')
59
- end
60
-
61
- desc "Uninstall previously installed packaged"
62
- task 'uninstall' do |task|
63
- rb_bin = File.expand_path(Config::CONFIG['ruby_install_name'], Config::CONFIG['bindir'])
64
- args = [rb_bin, '-S', 'gem', 'install', spec.name, '-v', spec.version.to_s]
65
- windows = Config::CONFIG['host_os'] =~ /windows|cygwin|bccwin|cygwin|djgpp|mingw|mswin|wince/i
66
- args.unshift('sudo') unless windows || ENV['GEM_HOME']
67
- sh args.map{ |a| a.inspect }.join(' ')
68
- end
69
-
70
-
71
- task 'release'=>['setup', 'test', 'package'] do
72
-
73
- require 'rubyforge'
74
- =begin
75
- header = File.readlines('CHANGELOG').first
76
- version, date = header.scan(/(\d+\.\d+\.\d+) \((\d{4}-\d{2}-\d{2})\)/).first
77
- fail "CHANGELOG and spec version numbers do not match: #{version} != #{spec.version}" unless version == spec.version.to_s
78
- today = Time.now.strftime('%Y-%m-%d')
79
- fail "CHANGELOG entry not using today's date: #{date} != #{today}" unless date = today
80
-
81
- =end
82
- changes = File.read('CHANGELOG')[/\d+.\d+.\d+.*\n((:?^[^\n]+\n)*)/]
83
- File.open '.changes', 'w' do |file|
84
- file.write changes
85
- end
86
-
87
- puts "Uploading #{spec.name} #{spec.version}"
88
- files = Dir['pkg/*.{gem,tgz,zip}']
89
- rubyforge = RubyForge.new
90
- rubyforge.configure
91
- rubyforge.login
92
- rubyforge.userconfig.merge! 'release_changes'=>'.changes', 'preformatted'=>true
93
- rubyforge.add_release spec.rubyforge_project.downcase, spec.name.downcase, spec.version, *files
94
- rm_f '.changes'
95
- puts "Release #{spec.version} uploaded"
96
- end
97
-
98
- task 'clobber' do
99
- rm_f '.changes'
100
- end
@@ -1,282 +0,0 @@
1
- #
2
- # = uuid.rb - UUID generator
3
- #
4
- # Author:: Assaf Arkin assaf@labnotes.org
5
- # Eric Hodel drbrain@segment7.net
6
- # Documentation:: http://trac.labnotes.org/cgi-bin/trac.cgi/wiki/Ruby/UuidGenerator
7
- # Copyright:: Copyright (c) 2005-2008 Assaf Arkin, Eric Hodel
8
- # License:: MIT and/or Creative Commons Attribution-ShareAlike
9
-
10
- require 'fileutils'
11
- require 'thread'
12
- require 'tmpdir'
13
-
14
- require 'rubygems'
15
- require 'macaddr'
16
-
17
-
18
- ##
19
- # = Generating UUIDs
20
- #
21
- # Call #generate to generate a new UUID. The method returns a string in one of
22
- # three formats. The default format is 36 characters long, and contains the 32
23
- # hexadecimal octets and hyphens separating the various value parts. The
24
- # <tt>:compact</tt> format omits the hyphens, while the <tt>:urn</tt> format
25
- # adds the <tt>:urn:uuid</tt> prefix.
26
- #
27
- # For example:
28
- #
29
- # uuid = UUID.new
30
- #
31
- # 10.times do
32
- # p uuid.generate
33
- # end
34
- #
35
- # = UUIDs in Brief
36
- #
37
- # UUID (universally unique identifier) are guaranteed to be unique across time
38
- # and space.
39
- #
40
- # A UUID is 128 bit long, and consists of a 60-bit time value, a 16-bit
41
- # sequence number and a 48-bit node identifier.
42
- #
43
- # The time value is taken from the system clock, and is monotonically
44
- # incrementing. However, since it is possible to set the system clock
45
- # backward, a sequence number is added. The sequence number is incremented
46
- # each time the UUID generator is started. The combination guarantees that
47
- # identifiers created on the same machine are unique with a high degree of
48
- # probability.
49
- #
50
- # Note that due to the structure of the UUID and the use of sequence number,
51
- # there is no guarantee that UUID values themselves are monotonically
52
- # incrementing. The UUID value cannot itself be used to sort based on order
53
- # of creation.
54
- #
55
- # To guarantee that UUIDs are unique across all machines in the network,
56
- # the IEEE 802 MAC address of the machine's network interface card is used as
57
- # the node identifier.
58
- #
59
- # For more information see {RFC 4122}[http://www.ietf.org/rfc/rfc4122.txt].
60
-
61
- class UUID
62
-
63
- VERSION = '2.0.1'
64
-
65
- ##
66
- # Clock multiplier. Converts Time (resolution: seconds) to UUID clock
67
- # (resolution: 10ns)
68
- CLOCK_MULTIPLIER = 10000000
69
-
70
- ##
71
- # Clock gap is the number of ticks (resolution: 10ns) between two Ruby Time
72
- # ticks.
73
- CLOCK_GAPS = 100000
74
-
75
- ##
76
- # Version number stamped into the UUID to identify it as time-based.
77
- VERSION_CLOCK = 0x0100
78
-
79
- ##
80
- # Formats supported by the UUID generator.
81
- #
82
- # <tt>:default</tt>:: Produces 36 characters, including hyphens separating
83
- # the UUID value parts
84
- # <tt>:compact</tt>:: Produces a 32 digits (hexadecimal) value with no
85
- # hyphens
86
- # <tt>:urn</tt>:: Adds the prefix <tt>urn:uuid:</tt> to the default format
87
- FORMATS = {
88
- :compact => '%08x%04x%04x%04x%012x',
89
- :default => '%08x-%04x-%04x-%04x-%012x',
90
- :urn => 'urn:uuid:%08x-%04x-%04x-%04x-%012x',
91
- }
92
-
93
- ##
94
- # MAC address (48 bits), sequence number and last clock
95
- STATE_FILE_FORMAT = 'SLLQ'
96
-
97
- @state_file = nil
98
- @mode = nil
99
- @uuid = nil
100
-
101
- ##
102
- # The access mode of the state file. Set it with state_file.
103
-
104
- def self.mode
105
- @mode
106
- end
107
-
108
- ##
109
- # Generates a new UUID string using +format+. See FORMATS for a list of
110
- # supported formats.
111
-
112
- def self.generate(format = :default)
113
- @uuid ||= new
114
- @uuid.generate format
115
- end
116
-
117
- ##
118
- # Creates an empty state file in /var/tmp/ruby-uuid or the windows common
119
- # application data directory using mode 0644. Call with a different mode
120
- # before creating a UUID generator if you want to open access beyond your
121
- # user by default.
122
- #
123
- # If the default state dir is not writable, UUID falls back to ~/.ruby-uuid.
124
- #
125
- # State files are not portable across machines.
126
- def self.state_file(mode = 0644)
127
- return @state_file if @state_file
128
-
129
- @mode = mode
130
-
131
- begin
132
- require 'Win32API'
133
-
134
- csidl_common_appdata = 0x0023
135
- path = 0.chr * 260
136
- get_folder_path = Win32API.new('shell32', 'SHGetFolderPath', 'LLLLP', 'L')
137
- get_folder_path.call 0, csidl_common_appdata, 0, 1, path
138
-
139
- state_dir = File.join(path.strip)
140
- rescue LoadError
141
- state_dir = File.join('', 'var', 'tmp')
142
- end
143
-
144
- if File.writable?(state_dir) then
145
- @state_file = File.join(state_dir, 'ruby-uuid')
146
- else
147
- @state_file = File.expand_path(File.join('~', '.ruby-uuid'))
148
- end
149
-
150
- @state_file
151
- end
152
-
153
- ##
154
- # Create a new UUID generator. You really only need to do this once.
155
- def initialize
156
- @drift = 0
157
- @last_clock = (Time.now.to_f * CLOCK_MULTIPLIER).to_i
158
- @mutex = Mutex.new
159
-
160
- if File.exist?(self.class.state_file) then
161
- next_sequence
162
- else
163
- @mac = Mac.addr.gsub(/:|-/, '').hex & 0x7FFFFFFFFFFF
164
- fail "Cannot determine MAC address from any available interface, tried with #{Mac.addr}" if @mac == 0
165
- @sequence = rand 0x10000
166
-
167
- open_lock 'w' do |io|
168
- write_state io
169
- end
170
- end
171
- end
172
-
173
- ##
174
- # Generates a new UUID string using +format+. See FORMATS for a list of
175
- # supported formats.
176
- def generate(format = :default)
177
- template = FORMATS[format]
178
-
179
- raise ArgumentError, "invalid UUID format #{format.inspect}" unless template
180
-
181
- # The clock must be monotonically increasing. The clock resolution is at
182
- # best 100 ns (UUID spec), but practically may be lower (on my setup,
183
- # around 1ms). If this method is called too fast, we don't have a
184
- # monotonically increasing clock, so the solution is to just wait.
185
- #
186
- # It is possible for the clock to be adjusted backwards, in which case we
187
- # would end up blocking for a long time. When backward clock is detected,
188
- # we prevent duplicates by asking for a new sequence number and continue
189
- # with the new clock.
190
-
191
- clock = @mutex.synchronize do
192
- clock = (Time.new.to_f * CLOCK_MULTIPLIER).to_i & 0xFFFFFFFFFFFFFFF0
193
-
194
- if clock > @last_clock then
195
- @drift = 0
196
- @last_clock = clock
197
- elsif clock == @last_clock then
198
- drift = @drift += 1
199
-
200
- if drift < 10000 then
201
- @last_clock += 1
202
- else
203
- Thread.pass
204
- nil
205
- end
206
- else
207
- next_sequence
208
- @last_clock = clock
209
- end
210
- end until clock
211
-
212
- template % [
213
- clock & 0xFFFFFFFF,
214
- (clock >> 32) & 0xFFFF,
215
- ((clock >> 48) & 0xFFFF | VERSION_CLOCK),
216
- @sequence & 0xFFFF,
217
- @mac & 0xFFFFFFFFFFFF
218
- ]
219
- end
220
-
221
- ##
222
- # Updates the state file with a new sequence number.
223
- def next_sequence
224
- open_lock 'r+' do |io|
225
- @mac, @sequence, @last_clock = read_state(io)
226
-
227
- io.rewind
228
- io.truncate 0
229
-
230
- @sequence += 1
231
-
232
- write_state io
233
- end
234
- rescue Errno::ENOENT
235
- open_lock 'w' do |io|
236
- write_state io
237
- end
238
- ensure
239
- @last_clock = (Time.now.to_f * CLOCK_MULTIPLIER).to_i
240
- @drift = 0
241
- end
242
-
243
- def inspect
244
- mac = ("%012x" % @mac).scan(/[0-9a-f]{2}/).join(':')
245
- "MAC: #{mac} Sequence: #{@sequence}"
246
- end
247
-
248
- protected
249
-
250
- ##
251
- # Open the state file with an exclusive lock and access mode +mode+.
252
- def open_lock(mode)
253
- File.open self.class.state_file, mode, self.class.mode do |io|
254
- begin
255
- io.flock File::LOCK_EX
256
- yield io
257
- ensure
258
- io.flock File::LOCK_UN
259
- end
260
- end
261
- end
262
-
263
- ##
264
- # Read the state from +io+
265
- def read_state(io)
266
- mac1, mac2, seq, last_clock = io.read(32).unpack(STATE_FILE_FORMAT)
267
- mac = (mac1 << 32) + mac2
268
-
269
- return mac, seq, last_clock
270
- end
271
-
272
-
273
- ##
274
- # Write that state to +io+
275
- def write_state(io)
276
- mac2 = @mac & 0xffffffff
277
- mac1 = (@mac >> 32) & 0xffff
278
-
279
- io.write [mac1, mac2, @sequence, @last_clock].pack(STATE_FILE_FORMAT)
280
- end
281
-
282
- end
@@ -1,82 +0,0 @@
1
- # Author:: Assaf Arkin assaf@labnotes.org
2
- # Eric Hodel drbrain@segment7.net
3
- # Copyright:: Copyright (c) 2005-2008 Assaf Arkin, Eric Hodel
4
- # License:: MIT and/or Creative Commons Attribution-ShareAlike
5
-
6
- require 'test/unit'
7
- require 'uuid'
8
-
9
- class TestUUID < Test::Unit::TestCase
10
-
11
- def test_state_file_creation
12
- path = UUID.state_file
13
- File.delete path if File.exist?(path)
14
- UUID.new.generate
15
- File.exist?(path)
16
- end
17
-
18
- def test_instance_generate
19
- uuid = UUID.new
20
- assert_match(/\A[\da-f]{32}\z/i, uuid.generate(:compact))
21
-
22
- assert_match(/\A[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\z/i,
23
- uuid.generate(:default))
24
-
25
- assert_match(/^urn:uuid:[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\z/i,
26
- uuid.generate(:urn))
27
-
28
- e = assert_raise ArgumentError do
29
- uuid.generate :unknown
30
- end
31
-
32
- assert_equal 'invalid UUID format :unknown', e.message
33
- end
34
-
35
- def test_class_generate uuid = UUID.new
36
- assert_match(/\A[\da-f]{32}\z/i, UUID.generate(:compact))
37
-
38
- assert_match(/\A[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\z/i,
39
- UUID.generate(:default))
40
-
41
- assert_match(/^urn:uuid:[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\z/i,
42
- UUID.generate(:urn))
43
-
44
- e = assert_raise ArgumentError do
45
- UUID.generate :unknown
46
- end
47
- assert_equal 'invalid UUID format :unknown', e.message
48
- end
49
-
50
- def test_monotonic
51
- seen = {}
52
- uuid_gen = UUID.new
53
-
54
- 20_000.times do
55
- uuid = uuid_gen.generate
56
- assert !seen.has_key?(uuid), "UUID repeated"
57
- seen[uuid] = true
58
- end
59
- end
60
-
61
- def test_same_mac
62
- class << foo = UUID.new
63
- attr_reader :mac
64
- end
65
- class << bar = UUID.new
66
- attr_reader :mac
67
- end
68
- assert_equal foo.mac, bar.mac
69
- end
70
-
71
- def test_increasing_sequence
72
- class << foo = UUID.new
73
- attr_reader :sequence
74
- end
75
- class << bar = UUID.new
76
- attr_reader :sequence
77
- end
78
- assert_equal foo.sequence + 1, bar.sequence
79
- end
80
-
81
- end
82
-