uuid 2.2.0 → 2.3.0
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.
- data/CHANGELOG +6 -0
- data/README.rdoc +24 -5
- data/Rakefile +0 -18
- data/bin/uuid +55 -0
- data/lib/uuid.rb +129 -2
- data/uuid.gemspec +3 -1
- metadata +29 -13
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
2.3.0 (2010-04-07)
|
2
|
+
* Added: UUID.generator returns the current UUID generator. Particularly useful for calling
|
3
|
+
next_sequence on the generator when forking a process.
|
4
|
+
* Added: UUID::Server and UUID::Client so you can have one process serving you UUIDs.
|
5
|
+
* Added: UUID command line tool. Yay!
|
6
|
+
|
1
7
|
2.2.0 (2010-02-18)
|
2
8
|
* Added: set UUID.state_file = false if you cannot use a state file (e.g. shared hosting environment)
|
3
9
|
|
data/README.rdoc
CHANGED
@@ -76,15 +76,34 @@ Engine) you can simple turn it off:
|
|
76
76
|
|
77
77
|
State files are not portable across machines.
|
78
78
|
|
79
|
+
Note: when using a forking server (Unicorn, Resque, Pipemaster, etc) you don't
|
80
|
+
want your forked processes using the same sequence number. Make sure to
|
81
|
+
increment the sequence number each time a worker forks.
|
79
82
|
|
80
|
-
|
83
|
+
For example, in config/unicorn.rb:
|
84
|
+
|
85
|
+
after_fork do |server, worker|
|
86
|
+
UUID.generator.next_sequence
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
== Command Line
|
91
|
+
|
92
|
+
You can run uuid from the command line, generating new UUID to stdout:
|
81
93
|
|
82
|
-
|
94
|
+
$ uuid
|
83
95
|
|
84
|
-
|
96
|
+
Multiple UUIDs in a sequence, separated with a newline:
|
85
97
|
|
86
|
-
|
87
|
-
|
98
|
+
$ uuid --count 10
|
99
|
+
|
100
|
+
You can also run client and server from the command line
|
101
|
+
|
102
|
+
$ uuid --server &
|
103
|
+
$ uuid --socket /var/lib/uuid.sock
|
104
|
+
|
105
|
+
|
106
|
+
== Latest and Greatest
|
88
107
|
|
89
108
|
Source code and documentation hosted on Github: http://github.com/assaf/uuid
|
90
109
|
|
data/Rakefile
CHANGED
@@ -8,24 +8,6 @@ desc "Default Task"
|
|
8
8
|
task :default => :test
|
9
9
|
|
10
10
|
|
11
|
-
desc "If you're building from sources, run this task first to setup the necessary dependencies"
|
12
|
-
task 'setup' do
|
13
|
-
missing = spec.dependencies.select { |dep| Gem::SourceIndex.from_installed_gems.search(dep).empty? }
|
14
|
-
missing.each do |dep|
|
15
|
-
if Gem::SourceIndex.from_installed_gems.search(dep).empty?
|
16
|
-
puts "Installing #{dep.name} ..."
|
17
|
-
rb_bin = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
|
18
|
-
args = []
|
19
|
-
args << rb_bin << '-S' << 'gem' << 'install' << dep.name
|
20
|
-
args << '--version' << dep.version_requirements.to_s
|
21
|
-
args << '--source' << 'http://gems.rubyforge.org'
|
22
|
-
args << '--install-dir' << ENV['GEM_HOME'] if ENV['GEM_HOME']
|
23
|
-
sh *args
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
11
|
desc "Run all test cases"
|
30
12
|
Rake::TestTask.new do |test|
|
31
13
|
test.verbose = true
|
data/bin/uuid
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "uuid"
|
3
|
+
require "optparse"
|
4
|
+
|
5
|
+
address = nil
|
6
|
+
count = 1
|
7
|
+
format = :default
|
8
|
+
server = false
|
9
|
+
|
10
|
+
opts = OptionParser.new("", 24, ' ') do |opts|
|
11
|
+
opts.banner = "Usage: #{File.basename($0)} [options]"
|
12
|
+
|
13
|
+
opts.separator "\nOptions:"
|
14
|
+
opts.on("-s", "--socket {HOST:PORT|PATH}",
|
15
|
+
"communicate on HOST:PORT or PATH (default: #{UUID::SOCKET_NAME})") do |value|
|
16
|
+
address = value
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on("-S", "--server", "run as a server") do |value|
|
20
|
+
server = value ? true : false
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("-F", "--format {FORMAT}", "UUID format (client only)") do |value|
|
24
|
+
format = value.to_sym
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-C", "--count {COUNT}", "returns give number of UUIDs") do |value|
|
28
|
+
count = value.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-h", "--help", "Show this message") do
|
32
|
+
puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-v", "--version", "Show version") do
|
37
|
+
puts "UUID v#{UUID::VERSION}"
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.parse! ARGV
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
if server
|
46
|
+
$stdout << "Starting UUID server on #{address}\n"
|
47
|
+
UUID::Server.new.listen(address || UUID::SOCKET_NAME)
|
48
|
+
else
|
49
|
+
UUID.server = address if address
|
50
|
+
$stdout << UUID.generate(format)
|
51
|
+
(count - 1).times do
|
52
|
+
$stdout.putc "\n"
|
53
|
+
$stdout << UUID.generate(format)
|
54
|
+
end
|
55
|
+
end
|
data/lib/uuid.rb
CHANGED
@@ -9,8 +9,7 @@
|
|
9
9
|
require 'fileutils'
|
10
10
|
require 'thread'
|
11
11
|
require 'tmpdir'
|
12
|
-
|
13
|
-
require 'rubygems'
|
12
|
+
require 'socket'
|
14
13
|
require 'macaddr'
|
15
14
|
|
16
15
|
|
@@ -122,6 +121,24 @@ class UUID
|
|
122
121
|
@uuid.generate format
|
123
122
|
end
|
124
123
|
|
124
|
+
##
|
125
|
+
# Returns the UUID generator used by generate. Useful if you need to mess
|
126
|
+
# with it, e.g. force next sequence when forking (e.g. Unicorn, Resque):
|
127
|
+
#
|
128
|
+
# after_fork do
|
129
|
+
# UUID.generator.next_sequence
|
130
|
+
# end
|
131
|
+
def self.generator
|
132
|
+
@uuid ||= new
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# Call this to use a UUID Server. Expects address to bind to (SOCKET_NAME is
|
137
|
+
# a good default)
|
138
|
+
def self.server=(address)
|
139
|
+
@uuid = Client.new(address) unless Client === @uuid
|
140
|
+
end
|
141
|
+
|
125
142
|
##
|
126
143
|
# Creates an empty state file in /var/tmp/ruby-uuid or the windows common
|
127
144
|
# application data directory using mode 0644. Call with a different mode
|
@@ -313,4 +330,114 @@ protected
|
|
313
330
|
io.write [mac1, mac2, @sequence, @last_clock].pack(STATE_FILE_FORMAT)
|
314
331
|
end
|
315
332
|
|
333
|
+
|
334
|
+
# You don't have to use this, it's just a good default.
|
335
|
+
SOCKET_NAME ="/var/lib/uuid.sock"
|
336
|
+
|
337
|
+
# With UUID server you don't have to worry about multiple processes
|
338
|
+
# synchronizing over the state file, calling next_sequence when forking a
|
339
|
+
# process and other things you're probably not worried about (because
|
340
|
+
# statistically they're very unlikely to break your code).
|
341
|
+
#
|
342
|
+
# But if you are worried about and thought to yourself, "what would a simple
|
343
|
+
# UUID server look like?", here's the answer. The protocol is dead simple:
|
344
|
+
# client sends a byte, server responds with a UUID. Can use TCP or domain
|
345
|
+
# sockets.
|
346
|
+
class Server
|
347
|
+
|
348
|
+
# Create new server. Nothing interesting happens until you call listen.
|
349
|
+
def initialize()
|
350
|
+
@generator = UUID.new
|
351
|
+
end
|
352
|
+
|
353
|
+
# Start the server listening on the specific address. Blocks and never
|
354
|
+
# returns. Address can be:
|
355
|
+
# - A Socket object
|
356
|
+
# - UNIX domain socket name (e.g. /var/run/uuid.sock, must start with /)
|
357
|
+
# - IP address, colon, port (e.g. localhost:1337)
|
358
|
+
def listen(address)
|
359
|
+
sock = bind(address)
|
360
|
+
while client = sock.accept
|
361
|
+
Thread.start(client) do |client|
|
362
|
+
while client.read 1
|
363
|
+
client.write @generator.generate
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
# Returns UNIXServer or TCPServer from address. Returns argument if not a
|
370
|
+
# string, so can pass through (see #listen).
|
371
|
+
def bind(address)
|
372
|
+
return address unless String === address
|
373
|
+
if address[0] == ?/
|
374
|
+
if File.exist?(address)
|
375
|
+
raise ArgumentError, "#{address} is not a socket" unless File.socket?(address)
|
376
|
+
File.unlink(address)
|
377
|
+
end
|
378
|
+
sock = UNIXServer.new(address)
|
379
|
+
File.chmod 0666, address
|
380
|
+
elsif address =~ /^(\d+\.\d+\.\d+\.\d+):(\d+)$/
|
381
|
+
sock = TCPServer.new($1, $2.to_i)
|
382
|
+
else
|
383
|
+
raise ArgumentError, "Don't know how to bind #{address}"
|
384
|
+
end
|
385
|
+
sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) if defined?(TCP_NODELAY)
|
386
|
+
sock
|
387
|
+
end
|
388
|
+
|
389
|
+
end
|
390
|
+
|
391
|
+
|
392
|
+
# Every server needs a client. Client provides you with the single ultimate
|
393
|
+
# method: #generate. Typically you'll use this instead of the local UUID
|
394
|
+
# generator:
|
395
|
+
# UUID.server = UUID::SOCKET_NAME
|
396
|
+
class Client
|
397
|
+
|
398
|
+
def initialize(address)
|
399
|
+
@socket = connect(address)
|
400
|
+
at_exit { close }
|
401
|
+
end
|
402
|
+
|
403
|
+
# Talks to server and returns new UUID in specified format.
|
404
|
+
def generate(format = :default)
|
405
|
+
@socket.write "\0"
|
406
|
+
uuid = @socket.read(36)
|
407
|
+
return uuid if format == :default
|
408
|
+
template = FORMATS[format]
|
409
|
+
raise ArgumentError, "invalid UUID format #{format.inspect}" unless template
|
410
|
+
template % uuid.split("-").map { |p| p.to_i(16) }
|
411
|
+
end
|
412
|
+
|
413
|
+
# Returns UNIXSocket or TCPSocket from address. Returns argument if not a
|
414
|
+
# string, so can pass through.
|
415
|
+
def connect(address)
|
416
|
+
return address unless String === address
|
417
|
+
if address[0] == ?/
|
418
|
+
sock = UNIXSocket.new(address)
|
419
|
+
elsif address =~ /^(\d+\.\d+\.\d+\.\d+):(\d+)$/
|
420
|
+
sock = TCPSocket.new($1, $2.to_i)
|
421
|
+
else
|
422
|
+
raise ArgumentError, "Don't know how to connect to #{address}"
|
423
|
+
end
|
424
|
+
sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) if defined?(TCP_NODELAY)
|
425
|
+
sock
|
426
|
+
end
|
427
|
+
|
428
|
+
def next_sequence #:nodoc: Stubbed to do nothing.
|
429
|
+
end
|
430
|
+
|
431
|
+
def inspect
|
432
|
+
@socket ? "Server on #{Socket.unpack_sockaddr_in(@socket.getsockname).reverse!.join(':')}" : "Connection closed"
|
433
|
+
end
|
434
|
+
|
435
|
+
# Close the socket.
|
436
|
+
def close
|
437
|
+
@socket.shutdown if @socket
|
438
|
+
@socket = nil
|
439
|
+
end
|
440
|
+
|
441
|
+
end
|
442
|
+
|
316
443
|
end
|
data/uuid.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
spec = Gem::Specification.new do |spec|
|
2
2
|
spec.name = 'uuid'
|
3
|
-
spec.version = '2.
|
3
|
+
spec.version = '2.3.0'
|
4
4
|
spec.summary = "UUID generator"
|
5
5
|
spec.description = <<-EOF
|
6
6
|
UUID generator for producing universally unique identifiers based on RFC 4122
|
@@ -12,6 +12,8 @@ EOF
|
|
12
12
|
spec.homepage = 'http://github.com/assaf/uuid'
|
13
13
|
|
14
14
|
spec.files = Dir['{bin,test,lib,docs}/**/*'] + ['README.rdoc', 'MIT-LICENSE', 'Rakefile', 'CHANGELOG', 'uuid.gemspec']
|
15
|
+
spec.executables = "uuid"
|
16
|
+
|
15
17
|
spec.has_rdoc = true
|
16
18
|
spec.rdoc_options << '--main' << 'README.rdoc' << '--title' << 'UUID generator' << '--line-numbers'
|
17
19
|
'--webcvs' << 'http://github.com/assaf/uuid'
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uuid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 2
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 2.3.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Assaf Arkin
|
@@ -10,29 +15,36 @@ autorequire:
|
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
17
|
|
13
|
-
date: 2010-
|
18
|
+
date: 2010-04-07 00:00:00 -07:00
|
14
19
|
default_executable:
|
15
20
|
dependencies:
|
16
21
|
- !ruby/object:Gem::Dependency
|
17
22
|
name: macaddr
|
18
|
-
|
19
|
-
|
20
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
21
25
|
requirements:
|
22
26
|
- - ~>
|
23
27
|
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 0
|
24
31
|
version: "1.0"
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: |
|
35
|
+
UUID generator for producing universally unique identifiers based on RFC 4122
|
36
|
+
(http://www.ietf.org/rfc/rfc4122.txt).
|
29
37
|
|
38
|
+
email: assaf@labnotes.org
|
39
|
+
executables:
|
40
|
+
- uuid
|
30
41
|
extensions: []
|
31
42
|
|
32
43
|
extra_rdoc_files:
|
33
44
|
- README.rdoc
|
34
45
|
- MIT-LICENSE
|
35
46
|
files:
|
47
|
+
- bin/uuid
|
36
48
|
- test/test-uuid.rb
|
37
49
|
- lib/uuid.rb
|
38
50
|
- README.rdoc
|
@@ -42,6 +54,8 @@ files:
|
|
42
54
|
- uuid.gemspec
|
43
55
|
has_rdoc: true
|
44
56
|
homepage: http://github.com/assaf/uuid
|
57
|
+
licenses: []
|
58
|
+
|
45
59
|
post_install_message:
|
46
60
|
rdoc_options:
|
47
61
|
- --main
|
@@ -55,20 +69,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
69
|
requirements:
|
56
70
|
- - ">="
|
57
71
|
- !ruby/object:Gem::Version
|
72
|
+
segments:
|
73
|
+
- 0
|
58
74
|
version: "0"
|
59
|
-
version:
|
60
75
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
76
|
requirements:
|
62
77
|
- - ">="
|
63
78
|
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
64
81
|
version: "0"
|
65
|
-
version:
|
66
82
|
requirements: []
|
67
83
|
|
68
84
|
rubyforge_project:
|
69
|
-
rubygems_version: 1.3.
|
85
|
+
rubygems_version: 1.3.6
|
70
86
|
signing_key:
|
71
|
-
specification_version:
|
87
|
+
specification_version: 3
|
72
88
|
summary: UUID generator
|
73
89
|
test_files: []
|
74
90
|
|