git-ds 0.9.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.
- data/README.rdoc +795 -0
- data/doc/Examples.rdoc +36 -0
- data/doc/examples/key_value/kv_get.rb +29 -0
- data/doc/examples/key_value/kv_init.rb +20 -0
- data/doc/examples/key_value/kv_list.rb +28 -0
- data/doc/examples/key_value/kv_remove.rb +29 -0
- data/doc/examples/key_value/kv_set.rb +39 -0
- data/doc/examples/key_value/model.rb +156 -0
- data/doc/examples/key_value/test.rb +50 -0
- data/doc/examples/test_suite/model.rb +503 -0
- data/doc/examples/test_suite/test.rb +173 -0
- data/doc/examples/test_suite/ts_add_bug.rb +65 -0
- data/doc/examples/test_suite/ts_add_module.rb +74 -0
- data/doc/examples/test_suite/ts_add_module_to_test.rb +78 -0
- data/doc/examples/test_suite/ts_add_test.rb +77 -0
- data/doc/examples/test_suite/ts_add_test_suite.rb +65 -0
- data/doc/examples/test_suite/ts_add_test_to_bug.rb +76 -0
- data/doc/examples/test_suite/ts_init.rb +20 -0
- data/doc/examples/test_suite/ts_list.rb +118 -0
- data/doc/examples/test_suite/ts_perform_test.rb +104 -0
- data/doc/examples/test_suite/ts_update_bugs.rb +58 -0
- data/doc/examples/user_group/model.rb +265 -0
- data/doc/examples/user_group/test.rb +64 -0
- data/doc/examples/user_group/ug_add_group.rb +39 -0
- data/doc/examples/user_group/ug_add_group_user.rb +36 -0
- data/doc/examples/user_group/ug_add_user.rb +39 -0
- data/doc/examples/user_group/ug_init.rb +20 -0
- data/doc/examples/user_group/ug_list.rb +32 -0
- data/lib/git-ds.rb +14 -0
- data/lib/git-ds/config.rb +53 -0
- data/lib/git-ds/database.rb +289 -0
- data/lib/git-ds/exec_cmd.rb +107 -0
- data/lib/git-ds/index.rb +205 -0
- data/lib/git-ds/model.rb +136 -0
- data/lib/git-ds/model/db_item.rb +42 -0
- data/lib/git-ds/model/fs_item.rb +51 -0
- data/lib/git-ds/model/item.rb +428 -0
- data/lib/git-ds/model/item_list.rb +97 -0
- data/lib/git-ds/model/item_proxy.rb +128 -0
- data/lib/git-ds/model/property.rb +144 -0
- data/lib/git-ds/model/root.rb +46 -0
- data/lib/git-ds/repo.rb +455 -0
- data/lib/git-ds/shared.rb +17 -0
- data/lib/git-ds/transaction.rb +77 -0
- data/tests/ut_database.rb +304 -0
- data/tests/ut_git_grit_equiv.rb +195 -0
- data/tests/ut_index.rb +203 -0
- data/tests/ut_model.rb +360 -0
- data/tests/ut_repo.rb +260 -0
- data/tests/ut_user_group_model.rb +316 -0
- metadata +142 -0
@@ -0,0 +1,265 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# :title: GitDS Model Example: User/Group
|
3
|
+
=begin rdoc
|
4
|
+
<i>Copyright 2011 Thoughtgang <http://www.thoughtgang.org></i>
|
5
|
+
|
6
|
+
This example demonstrates a simple hierarchical data model for managing
|
7
|
+
unix-style users and groups.
|
8
|
+
|
9
|
+
Note: This is not intended as a serious implementation of an auth system. It is
|
10
|
+
intended only to illustrate the use of a hierarchical database using a
|
11
|
+
familiar data model.
|
12
|
+
|
13
|
+
==Usage
|
14
|
+
|
15
|
+
An example of the usage of this model can be found in the following script:
|
16
|
+
|
17
|
+
doc/examples/user_group/test.rb
|
18
|
+
|
19
|
+
This script can be run to generate an example Git-DS repository:
|
20
|
+
|
21
|
+
bash$ doc/examples/user_group/test.rb
|
22
|
+
bash$ cd ug_test.db && qgit &
|
23
|
+
|
24
|
+
The following command-line utilities are provided for manipulating this
|
25
|
+
data model:
|
26
|
+
|
27
|
+
doc/examples/user_group/ug_add_group.rb
|
28
|
+
doc/examples/user_group/ug_add_group_user.rb
|
29
|
+
doc/examples/user_group/ug_add_user.rb
|
30
|
+
doc/examples/user_group/ug_init.rb
|
31
|
+
doc/examples/user_group/ug_list.rb
|
32
|
+
|
33
|
+
|
34
|
+
===Initialize a TestSuite database
|
35
|
+
|
36
|
+
# connect the model, creating it if necessary
|
37
|
+
model = UserGroupModel.new(GitDS::Database.connect('ug_test.db', true))
|
38
|
+
|
39
|
+
===Add a user
|
40
|
+
|
41
|
+
u = model.add_user(username, id, fullname)
|
42
|
+
|
43
|
+
===Add a group
|
44
|
+
|
45
|
+
g = model.add_group(username, id, owner_name)
|
46
|
+
|
47
|
+
# add user to group
|
48
|
+
u = model.user(username)
|
49
|
+
g.add_user(u)
|
50
|
+
|
51
|
+
=end
|
52
|
+
|
53
|
+
require 'git-ds/database'
|
54
|
+
require 'git-ds/model'
|
55
|
+
|
56
|
+
=begin rdoc
|
57
|
+
The model has the following structure in the repo:
|
58
|
+
|
59
|
+
user/ : FsModelItemClass
|
60
|
+
user/$NAME/ : FsModelItem
|
61
|
+
user/$NAME/id : Property
|
62
|
+
user/$NAME/full_name : Property
|
63
|
+
user/$NAME/created : Property
|
64
|
+
|
65
|
+
group/ : FsModelItemClass
|
66
|
+
group/$NAME/ : FsModelItem
|
67
|
+
group/$NAME/id : Property
|
68
|
+
group/$NAME/owner : ProxyProperty
|
69
|
+
group/$NAME/users : ProxyItemList
|
70
|
+
=end
|
71
|
+
|
72
|
+
class UserGroupModel < GitDS::Model
|
73
|
+
def initialize(db)
|
74
|
+
super db, 'user/group model'
|
75
|
+
end
|
76
|
+
|
77
|
+
=begin rdoc
|
78
|
+
Add a User to the model.
|
79
|
+
=end
|
80
|
+
def add_user(name, id, fullname='')
|
81
|
+
args = {:username => name, :id => id.to_i, :fullname => fullname }
|
82
|
+
UserModelItem.new self, UserModelItem.create(self.root, args)
|
83
|
+
end
|
84
|
+
|
85
|
+
=begin rdoc
|
86
|
+
Return a list of the usernames of all Users in the model
|
87
|
+
=end
|
88
|
+
def users
|
89
|
+
UserModelItem.list(self.root)
|
90
|
+
end
|
91
|
+
|
92
|
+
=begin rdoc
|
93
|
+
Instantiate a User object based on the username.
|
94
|
+
=end
|
95
|
+
def user(ident)
|
96
|
+
UserModelItem.new self, UserModelItem.instance_path(self.root.path, ident)
|
97
|
+
end
|
98
|
+
|
99
|
+
=begin rdoc
|
100
|
+
Add a Group to the model.
|
101
|
+
=end
|
102
|
+
def add_group(name, id, owner_name)
|
103
|
+
owner = user(owner_name)
|
104
|
+
|
105
|
+
args = { :name => name, :id => id.to_i, :owner => owner }
|
106
|
+
GroupModelItem.new self, GroupModelItem.create(self.root, args)
|
107
|
+
end
|
108
|
+
|
109
|
+
=begin rdoc
|
110
|
+
List the names of all Groups in the model.
|
111
|
+
=end
|
112
|
+
def groups
|
113
|
+
GroupModelItem.list(self.root)
|
114
|
+
end
|
115
|
+
|
116
|
+
=begin rdoc
|
117
|
+
Instantiate a Group object by name.
|
118
|
+
=end
|
119
|
+
def group(ident)
|
120
|
+
GroupModelItem.new self, GroupModelItem.instance_path(self.root.path, ident)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# ----------------------------------------------------------------------
|
125
|
+
=begin rdoc
|
126
|
+
A User. Users consist of a UNIX-style username, an ID number, a full name,
|
127
|
+
and a timestamp marking when they were created.
|
128
|
+
=end
|
129
|
+
class UserModelItem < GitDS::FsModelItem
|
130
|
+
|
131
|
+
name 'user'
|
132
|
+
|
133
|
+
# properties
|
134
|
+
property(:id, 0) { |p| p.to_s.to_i == p }
|
135
|
+
property(:full_name, '')
|
136
|
+
property(:created)
|
137
|
+
|
138
|
+
# Use :username entry in Hash as primary key
|
139
|
+
def self.ident_key
|
140
|
+
:username
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.fill(model, item_path, args)
|
144
|
+
super
|
145
|
+
properties[:created].set(model, item_path, Time.now.to_s)
|
146
|
+
end
|
147
|
+
|
148
|
+
=begin rdoc
|
149
|
+
The name of the user, e.g. 'root'.
|
150
|
+
=end
|
151
|
+
alias :username :ident
|
152
|
+
|
153
|
+
=begin rdoc
|
154
|
+
The ID number of the user, e.g. 1000.
|
155
|
+
=end
|
156
|
+
def id
|
157
|
+
integer_property(:id)
|
158
|
+
end
|
159
|
+
|
160
|
+
def id=(val)
|
161
|
+
set_property(:id, val)
|
162
|
+
end
|
163
|
+
|
164
|
+
=begin rdoc
|
165
|
+
The full name of the user, e.g. 'John Q. Public'.
|
166
|
+
=end
|
167
|
+
def full_name
|
168
|
+
property(:full_name)
|
169
|
+
end
|
170
|
+
|
171
|
+
def full_name=(val)
|
172
|
+
set_property(:full_name, val)
|
173
|
+
end
|
174
|
+
|
175
|
+
=begin rdoc
|
176
|
+
The timestamp when the user was created.
|
177
|
+
=end
|
178
|
+
def created
|
179
|
+
ts_property(:created)
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
# ----------------------------------------------------------------------
|
185
|
+
=begin rdoc
|
186
|
+
A group of users. Groups consist of a UNIX-style name, a numeric ID, and
|
187
|
+
owner (a valid User), and a list of members (valid Users).
|
188
|
+
=end
|
189
|
+
class GroupModelItem < GitDS::FsModelItem
|
190
|
+
|
191
|
+
name 'group'
|
192
|
+
|
193
|
+
# properties
|
194
|
+
property(:id, 0) { |p| p.to_s.to_i == p }
|
195
|
+
link_property(:owner, UserModelItem)
|
196
|
+
|
197
|
+
def initialize(model, path)
|
198
|
+
super
|
199
|
+
@users = GitDS::ProxyItemList.new(UserModelItem, model, path)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Use :name entry in Hash as primary key
|
203
|
+
def self.ident_key()
|
204
|
+
:name
|
205
|
+
end
|
206
|
+
|
207
|
+
=begin rdoc
|
208
|
+
The name of the group, e.g. 'staff'.
|
209
|
+
=end
|
210
|
+
alias :name :ident
|
211
|
+
|
212
|
+
=begin rdoc
|
213
|
+
The ID of the group, e.g. 1000.
|
214
|
+
=end
|
215
|
+
def id
|
216
|
+
integer_property(:id)
|
217
|
+
end
|
218
|
+
|
219
|
+
def id=(val)
|
220
|
+
set_property(:id, val)
|
221
|
+
end
|
222
|
+
|
223
|
+
=begin rdoc
|
224
|
+
The owner of the group: a link to a User object.
|
225
|
+
=end
|
226
|
+
def owner
|
227
|
+
property(:owner)
|
228
|
+
end
|
229
|
+
|
230
|
+
def owner=(u)
|
231
|
+
set_property(:owner, u)
|
232
|
+
end
|
233
|
+
|
234
|
+
=begin rdoc
|
235
|
+
The names of every User in the group.
|
236
|
+
=end
|
237
|
+
def users
|
238
|
+
ensure_valid
|
239
|
+
@users.keys
|
240
|
+
end
|
241
|
+
|
242
|
+
=begin rdoc
|
243
|
+
Instantiate a User in the group by name.
|
244
|
+
=end
|
245
|
+
def user(name)
|
246
|
+
ensure_valid
|
247
|
+
@users[name]
|
248
|
+
end
|
249
|
+
|
250
|
+
=begin rdoc
|
251
|
+
Add a User to the group. The argument must be a User object.
|
252
|
+
=end
|
253
|
+
def add_user(u)
|
254
|
+
ensure_valid
|
255
|
+
@users.add(self, u, true)
|
256
|
+
end
|
257
|
+
|
258
|
+
=begin rdoc
|
259
|
+
Remove a user from the group, by name.
|
260
|
+
=end
|
261
|
+
def del_user(name)
|
262
|
+
ensure_valid
|
263
|
+
@users.delete(name)
|
264
|
+
end
|
265
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Test User/Group database example
|
3
|
+
# Copyright 2011 Thoughtgang <http://www.thoughtgang.org>
|
4
|
+
|
5
|
+
BASE=File.dirname(File.expand_path(__FILE__)\
|
6
|
+
).split(File::SEPARATOR)[0..-4].join(File::SEPARATOR)
|
7
|
+
$: << BASE + File::SEPARATOR + 'lib'
|
8
|
+
$: << BASE + File::SEPARATOR + 'doc' + File::SEPARATOR + 'examples'
|
9
|
+
|
10
|
+
require 'user_group/model'
|
11
|
+
|
12
|
+
# ----------------------------------------------------------------------
|
13
|
+
|
14
|
+
def fill_model(model)
|
15
|
+
users = [{ :username => 'root', :id => 1 },
|
16
|
+
{ :username => 'admin', :id => 1000, :full_name => 'Administrator'},
|
17
|
+
{ :username => 'humpty', :id => 1001, :full_name => 'H Umpty, Esq.'},
|
18
|
+
{ :username => 'dumpty', :id => 1002, :full_name => 'Dump Ty'}
|
19
|
+
]
|
20
|
+
groups = [ { :name => 'wheel', :id => 1, :owner_name => 'root',
|
21
|
+
:members => ['root', 'admin'] },
|
22
|
+
{ :name => 'staff', :id => 1000, :owner_name => 'admin',
|
23
|
+
:members => ['admin', 'humpty', 'dumpty'] },
|
24
|
+
{ :name => 'twins', :id => 1001, :owner_name => 'humpty',
|
25
|
+
:members => ['humpty', 'dumpty'] }
|
26
|
+
]
|
27
|
+
|
28
|
+
users.each do |udef|
|
29
|
+
model.add_user(udef[:username], udef[:id], udef[:full_name])
|
30
|
+
end
|
31
|
+
|
32
|
+
groups.each do |gdef|
|
33
|
+
g = model.add_group(gdef[:name], gdef[:id], gdef[:owner_name])
|
34
|
+
gdef[:members].each { |name| g.add_user(model.user(name)) }
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# ----------------------------------------------------------------------
|
40
|
+
def list_model(model)
|
41
|
+
puts "Users:"
|
42
|
+
model.users.each do |user|
|
43
|
+
u = model.user(user)
|
44
|
+
puts "\t#{u.id}\t#{u.username}\t#{u.created}\t#{u.full_name}"
|
45
|
+
end
|
46
|
+
|
47
|
+
puts "\nGroups:"
|
48
|
+
model.groups.each do |grp|
|
49
|
+
puts "\t#{grp}"
|
50
|
+
g = model.group(grp)
|
51
|
+
puts "\t#{g.id}\t#{g.name}\t#{g.owner.username}\t#{g.users.inspect}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# ----------------------------------------------------------------------
|
56
|
+
if __FILE__ == $0
|
57
|
+
path = (ARGV.count > 0) ? ARGV.shift : 'ug_test.db'
|
58
|
+
|
59
|
+
db = GitDS::Database.connect(path, true)
|
60
|
+
model = UserGroupModel.new(db) if db
|
61
|
+
fill_model(model) if model
|
62
|
+
list_model(model) if model
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Add a group to a User/Group database repo
|
3
|
+
# Copyright 2011 Thoughtgang <http://www.thoughtgang.org>
|
4
|
+
|
5
|
+
# Add examples dir and lib/git-ds to ruby path
|
6
|
+
BASE=File.dirname(File.expand_path(__FILE__)\
|
7
|
+
).split(File::SEPARATOR)[0..-4].join(File::SEPARATOR)
|
8
|
+
$: << BASE + File::SEPARATOR + 'lib'
|
9
|
+
$: << BASE + File::SEPARATOR + 'doc' + File::SEPARATOR + 'examples'
|
10
|
+
|
11
|
+
require 'user_group/model'
|
12
|
+
|
13
|
+
if __FILE__ == $0
|
14
|
+
if ARGV.count < 3 || ARGV.count > 4
|
15
|
+
puts "Usage : #{$0} [FILENAME] NAME ID OWNER"
|
16
|
+
puts "Repo dir is assumed to be . if FILENAME is not specified."
|
17
|
+
puts "A new GitDS database will be created if FILENAME does not exist."
|
18
|
+
exit -1
|
19
|
+
end
|
20
|
+
|
21
|
+
path = ''
|
22
|
+
autocreate = false
|
23
|
+
if ARGV.count == 4
|
24
|
+
path = ARGV.shift
|
25
|
+
autocreate = true
|
26
|
+
else
|
27
|
+
path = GitDS::Database.top_level
|
28
|
+
end
|
29
|
+
name = ARGV.shift
|
30
|
+
id = ARGV.shift
|
31
|
+
owner = ARGV.shift
|
32
|
+
|
33
|
+
model = UserGroupModel.new(GitDS::Database.connect(path, autocreate))
|
34
|
+
raise "Could not connect to Model!" if not model
|
35
|
+
|
36
|
+
model.add_group(name, id, owner)
|
37
|
+
|
38
|
+
exit 0
|
39
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Add a user to a group in a User/Group database repo
|
3
|
+
# Copyright 2011 Thoughtgang <http://www.thoughtgang.org>
|
4
|
+
|
5
|
+
# Add examples dir and lib/git-ds to ruby path
|
6
|
+
BASE=File.dirname(File.expand_path(__FILE__)\
|
7
|
+
).split(File::SEPARATOR)[0..-4].join(File::SEPARATOR)
|
8
|
+
$: << BASE + File::SEPARATOR + 'lib'
|
9
|
+
$: << BASE + File::SEPARATOR + 'doc' + File::SEPARATOR + 'examples'
|
10
|
+
|
11
|
+
require 'user_group/model'
|
12
|
+
|
13
|
+
if __FILE__ == $0
|
14
|
+
if ARGV.count < 2 || ARGV.count > 3
|
15
|
+
puts "Usage : #{$0} [FILENAME] GROUP USER"
|
16
|
+
puts "Repo dir is assumed to be . if FILENAME is not specified."
|
17
|
+
exit -1
|
18
|
+
end
|
19
|
+
|
20
|
+
path = (ARGV.count == 3) ? ARGV.shift : GitDS::Database.top_level
|
21
|
+
group_name = ARGV.shift
|
22
|
+
user_name = ARGV.shift
|
23
|
+
|
24
|
+
model = UserGroupModel.new(GitDS::Database.connect(path, false))
|
25
|
+
raise "Could not connect to Model!" if not model
|
26
|
+
|
27
|
+
g = model.group(group_name)
|
28
|
+
raise "Invalid group #{group_name}" if not g
|
29
|
+
|
30
|
+
u = model.user(user_name)
|
31
|
+
raise "Invalid user #{user_name}" if not u
|
32
|
+
|
33
|
+
g.add_user(u)
|
34
|
+
|
35
|
+
exit 0
|
36
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Add a user to a User/Group database repo
|
3
|
+
# Copyright 2011 Thoughtgang <http://www.thoughtgang.org>
|
4
|
+
|
5
|
+
# Add examples dir and lib/git-ds to ruby path
|
6
|
+
BASE=File.dirname(File.expand_path(__FILE__)\
|
7
|
+
).split(File::SEPARATOR)[0..-4].join(File::SEPARATOR)
|
8
|
+
$: << BASE + File::SEPARATOR + 'lib'
|
9
|
+
$: << BASE + File::SEPARATOR + 'doc' + File::SEPARATOR + 'examples'
|
10
|
+
|
11
|
+
require 'user_group/model'
|
12
|
+
|
13
|
+
if __FILE__ == $0
|
14
|
+
if ARGV.count < 3 || ARGV.count > 4
|
15
|
+
puts "Usage : #{$0} [FILENAME] NAME ID FULLNAME"
|
16
|
+
puts "Repo dir is assumed to be . if FILENAME is not specified."
|
17
|
+
puts "A new GitDS database will be created if FILENAME does not exist."
|
18
|
+
exit -1
|
19
|
+
end
|
20
|
+
|
21
|
+
path = ''
|
22
|
+
autocreate = false
|
23
|
+
if ARGV.count == 4
|
24
|
+
path = ARGV.shift
|
25
|
+
autocreate = true
|
26
|
+
else
|
27
|
+
path = GitDS::Database.top_level
|
28
|
+
end
|
29
|
+
username = ARGV.shift
|
30
|
+
id = ARGV.shift
|
31
|
+
fullname = ARGV.shift
|
32
|
+
|
33
|
+
model = UserGroupModel.new(GitDS::Database.connect(path, autocreate))
|
34
|
+
raise "Could not connect to Model!" if not model
|
35
|
+
|
36
|
+
model.add_user(username, id, fullname)
|
37
|
+
|
38
|
+
exit 0
|
39
|
+
end
|