assaf-uuid 2.0.1 → 2.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.
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
-