treequel 1.1.1 → 1.2.0pre320

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 (44) hide show
  1. data.tar.gz.sig +0 -0
  2. data/ChangeLog +49 -1
  3. data/README.md +65 -0
  4. data/Rakefile +24 -19
  5. data/bin/treequel +20 -3
  6. data/lib/treequel.rb +3 -3
  7. data/lib/treequel/branch.rb +21 -7
  8. data/lib/treequel/branchset.rb +10 -0
  9. data/lib/treequel/model.rb +12 -2
  10. data/lib/treequel/schema.rb +1 -1
  11. data/rake/documentation.rb +9 -2
  12. data/rake/hg.rb +16 -3
  13. data/rake/manual.rb +1 -1
  14. data/rake/packaging.rb +1 -1
  15. data/rake/publishing.rb +158 -95
  16. data/rake/testing.rb +52 -88
  17. data/spec/lib/constants.rb +1 -0
  18. data/spec/lib/control_behavior.rb +7 -5
  19. data/spec/lib/helpers.rb +40 -17
  20. data/spec/lib/matchers.rb +2 -0
  21. data/spec/treequel/branch_spec.rb +44 -21
  22. data/spec/treequel/branchcollection_spec.rb +4 -3
  23. data/spec/treequel/branchset_spec.rb +42 -31
  24. data/spec/treequel/control_spec.rb +2 -1
  25. data/spec/treequel/controls/contentsync_spec.rb +2 -1
  26. data/spec/treequel/controls/pagedresults_spec.rb +4 -7
  27. data/spec/treequel/controls/sortedresults_spec.rb +4 -7
  28. data/spec/treequel/directory_spec.rb +11 -12
  29. data/spec/treequel/filter_spec.rb +7 -14
  30. data/spec/treequel/mixins_spec.rb +4 -9
  31. data/spec/treequel/model/objectclass_spec.rb +2 -1
  32. data/spec/treequel/model_spec.rb +16 -35
  33. data/spec/treequel/monkeypatches_spec.rb +12 -1
  34. data/spec/treequel/schema/attributetype_spec.rb +2 -1
  35. data/spec/treequel/schema/ldapsyntax_spec.rb +2 -1
  36. data/spec/treequel/schema/matchingrule_spec.rb +2 -1
  37. data/spec/treequel/schema/matchingruleuse_spec.rb +2 -1
  38. data/spec/treequel/schema/objectclass_spec.rb +2 -1
  39. data/spec/treequel/schema/table_spec.rb +2 -1
  40. data/spec/treequel/schema_spec.rb +2 -1
  41. data/spec/treequel_spec.rb +10 -2
  42. metadata +16 -17
  43. metadata.gz.sig +0 -0
  44. data/README +0 -66
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,4 +1,52 @@
1
- 304[tip] 92c28b14730a 2010-09-20 13:51 -0700 ged
1
+ 320[tip] ccdee2d78e68 2010-11-24 18:21 -0800 ged
2
+ Updated build system.
3
+
4
+ 319 47697f2ebc27 2010-11-24 18:18 -0800 ged
5
+ Added hash-key conversion so Branches can be constructed with Symbol-key hashargs.
6
+
7
+ 318 44f8be0662c4 2010-11-18 15:43 -0800 ged
8
+ Adding 'Treequel::Branchset#from' mutator for changing the base DN.
9
+
10
+ 317:316,315 72dd41272f6f 2010-11-11 12:46 -0600 ged
11
+ Merging with 316:33a7dcde80a1
12
+
13
+ 316:313 9f9460125077 2010-11-11 10:59 -0600 ged
14
+ Spec fixes for RSpec 2.0
15
+
16
+ 315 33a7dcde80a1 2010-11-09 13:00 -0800 ged
17
+ Readding subrepo
18
+
19
+ 314 fc9ae9f5b034 2010-11-09 12:53 -0800 ged
20
+ Fixing subrepo corruption caused by rollback
21
+
22
+ 313:312,311 c1b750e4e9fc 2010-11-09 12:09 -0800 ged
23
+ Merged with 310:cc7c63ff15a0
24
+
25
+ 312:310 380662d385e0 2010-11-09 12:08 -0800 ged
26
+ stub! -> stub; added more debugging to try to track down the model test failure
27
+
28
+ 311:309 cc7c63ff15a0 2010-11-03 07:50 -0700 ged
29
+ Converting the README to Markdown
30
+
31
+ 310 7f20ab74d6b1 2010-11-08 12:53 -0800 ged
32
+ Fixed treequel shell's cp to support relative and absolute DNs
33
+
34
+ 309 26c3853695ea 2010-10-22 17:47 -0700 ged
35
+ Converted to RSpec 2.0
36
+
37
+ 308 98b6847de872 2010-10-22 14:58 -0700 ged
38
+ Updating build system; add requirement for Ruby 1.8.7
39
+
40
+ 307 7f70394868e2 2010-09-21 08:49 -0700 ged
41
+ Added tag 1.1.1 for changeset e52c71f4e4ca
42
+
43
+ 306[1.1.1] e52c71f4e4ca 2010-09-21 08:49 -0700 ged
44
+ Added signature for changeset c6d26ab6a7a4
45
+
46
+ 305 c6d26ab6a7a4 2010-09-21 08:48 -0700 ged
47
+ Critical bugfix.
48
+
49
+ 304 92c28b14730a 2010-09-20 13:51 -0700 ged
2
50
  Added tag 1.1.0 for changeset b415e0fce774
3
51
 
4
52
  303[1.1.0] b415e0fce774 2010-09-20 13:51 -0700 ged
@@ -0,0 +1,65 @@
1
+ # Treequel - an honest LDAP library
2
+
3
+ Treequel is an LDAP toolkit for Ruby. It is intended to allow quick, easy
4
+ access to LDAP directories in a manner consistent with LDAP's hierarchical,
5
+ free-form nature.
6
+
7
+ It's inspired by and modeled after [Sequel](http://sequel.rubyforge.org/), a
8
+ kick-ass database library.
9
+
10
+
11
+ ## Examples
12
+
13
+ Here are a few short examples to whet your appetite:
14
+
15
+ # Connect to the directory at the specified URL
16
+ dir = Treequel.directory( 'ldap://ldap.company.com/dc=company,dc=com' )
17
+
18
+ # Get a list of email addresses of every person in the directory (as
19
+ # long as people are under ou=people)
20
+ dir.ou( :people ).filter( :mail ).map( :mail ).flatten
21
+
22
+ # Get a list of all IP addresses for all hosts in any ou=hosts group
23
+ # in the whole directory:
24
+ dir.filter( :ou => :hosts ).collection.filter( :ipHostNumber ).
25
+ map( :ipHostNumber ).flatten
26
+
27
+ # Get all people in the directory in the form of a hash of names
28
+ # keyed by email addresses
29
+ dir.ou( :people ).filter( :mail ).to_hash( :mail, :cn )
30
+
31
+ More elaborate examples of real-world usage can be found
32
+ [in the examples/ directory][examples] in the distribution.
33
+
34
+
35
+ ## Contributing
36
+
37
+ You can check out the current development source [with Mercurial][hgrepo], or
38
+ if you prefer Git, via the project's [Github mirror][gitmirror].
39
+
40
+ You can submit bug reports, suggestions, and read more about future plans at
41
+ [the project page][projectpage].
42
+
43
+
44
+ ## License
45
+
46
+ See the included LICENSE file for licensing details.
47
+
48
+
49
+ ## Authors
50
+
51
+ * Michael Granger
52
+ * Mahlon E. Smith
53
+
54
+
55
+ ## Contributors
56
+
57
+ A special thanks to Ben Bleything, who was part of the initial brainstorm that
58
+ led to the creation of this library.
59
+
60
+
61
+ [examples]:http://deveiate.org/projects/Treequel/browser/examples
62
+ [hgrepo]:http://repo.deveiate.org/Treequel
63
+ [gitmirror]:https://github.com/ged/treequel
64
+ [projectpage]:http://deveiate.org/projects/Treequel
65
+
data/Rakefile CHANGED
@@ -171,9 +171,9 @@ include RakefileHelpers
171
171
  # Set the build ID if the mercurial executable is available
172
172
  if hg = which( 'hg' )
173
173
  id = `#{hg} id -n`.chomp
174
- PKG_BUILD = "pre%03d" % [(id.chomp[ /^[[:xdigit:]]+/ ] || '1')]
174
+ PKG_BUILD = (id.chomp[ /^[[:xdigit:]]+/ ] || '1')
175
175
  else
176
- PKG_BUILD = 'pre000'
176
+ PKG_BUILD = '0'
177
177
  end
178
178
  SNAPSHOT_PKG_NAME = "#{PKG_FILE_NAME}.#{PKG_BUILD}"
179
179
  SNAPSHOT_GEM_NAME = "#{SNAPSHOT_PKG_NAME}.gem"
@@ -190,7 +190,6 @@ RDOC_OPTIONS = [
190
190
  ]
191
191
  YARD_OPTIONS = [
192
192
  '--use-cache',
193
- '--no-private',
194
193
  '--protected',
195
194
  '-r', README_FILE,
196
195
  '--exclude', 'extconf\\.rb',
@@ -210,27 +209,29 @@ PROJECT_DOCDIR = "#{PROJECT_PUBDIR}/#{PKG_NAME}"
210
209
  PROJECT_SCPPUBURL = "#{PROJECT_HOST}:#{PROJECT_PUBDIR}"
211
210
  PROJECT_SCPDOCURL = "#{PROJECT_HOST}:#{PROJECT_DOCDIR}"
212
211
 
212
+ GEM_PUBHOST = 'rubygems.org'
213
+
213
214
  # Gem dependencies: gemname => version
214
215
  DEPENDENCIES = {
215
- 'ruby-ldap' => '>= 0.9.9',
216
+ 'ruby-ldap' => '~> 0.9.9',
216
217
  }
217
218
 
218
219
  # Developer Gem dependencies: gemname => version
219
220
  DEVELOPMENT_DEPENDENCIES = {
220
- 'rake' => '>= 0.8.7',
221
- 'rcodetools' => '>= 0.7.0.0',
222
- 'rcov' => '>= 0.8.1.2.0',
223
- 'rdoc' => '>= 2.4.3',
224
- 'RedCloth' => '>= 4.0.3',
225
- 'rspec' => '>= 1.2.6',
226
- 'ruby-termios' => '>= 0.9.6',
227
- 'text-format' => '>= 1.0.0',
228
- 'tmail' => '>= 1.2.3.1',
229
- 'diff-lcs' => '>= 1.1.2',
230
- 'columnize' => '>= 0.3.1',
231
- 'diff-lcs' => '>= 1.1.2',
232
- 'ruby-termios' => '>= 0.9.6',
233
- 'ruby-terminfo' => '>= 0.1.1',
221
+ 'rake' => '~> 0.8.7',
222
+ 'rcodetools' => '~> 0.7.0.0',
223
+ 'rcov' => '~> 0.8.1.2.0',
224
+ 'yard' => '~> 0.6.1',
225
+ 'RedCloth' => '~> 4.2.3',
226
+ 'rspec' => '~> 2.0.1',
227
+ 'ruby-termios' => '~> 0.9.6',
228
+ 'text-format' => '~> 1.0.0',
229
+ 'tmail' => '~> 1.2.3.1',
230
+ 'columnize' => '~> 0.3.1',
231
+ 'diff-lcs' => '~> 1.1.2',
232
+ 'ruby-termios' => '~> 0.9.6',
233
+ 'rspec' => '~> 2.0.1',
234
+ 'ruby-terminfo' => '~> 0.1.1',
234
235
  }
235
236
 
236
237
  # Non-gem requirements: packagename => version
@@ -258,9 +259,10 @@ GEMSPEC = Gem::Specification.new do |gem|
258
259
  " - diff-lcs",
259
260
  ].join( "\n" )
260
261
 
261
- gem.authors = "Michael Granger, Mahlon E. Smith"
262
+ gem.authors = ["Michael Granger", "Mahlon E. Smith"]
262
263
  gem.email = ["mahlon@martini.nu", "ged@FaerieMUD.org"]
263
264
  gem.homepage = 'http://deveiate.org/projects/Treequel'
265
+ gem.licenses = ["BSD"]
264
266
 
265
267
  gem.has_rdoc = true
266
268
  gem.rdoc_options = RDOC_OPTIONS
@@ -282,6 +284,9 @@ GEMSPEC = Gem::Specification.new do |gem|
282
284
  gem.signing_key = '/Volumes/Keys/ged-private_gem_key.pem'
283
285
  gem.cert_chain = [File.expand_path('~/.gem/ged-public_gem_cert.pem')]
284
286
 
287
+
288
+ gem.required_ruby_version = '>=1.8.7'
289
+
285
290
  DEPENDENCIES.each do |name, version|
286
291
  version = '>= 0' if version.length.zero?
287
292
  gem.add_runtime_dependency( name, version )
@@ -690,10 +690,27 @@ class Treequel::Shell
690
690
 
691
691
  ### Copy an entry
692
692
  def cp_command( options, rdn, newrdn )
693
- branch = @currbranch.get_child( rdn )
694
- newbranch = @currbranch.get_child( newrdn )
693
+ base_dn = @currbranch.directory.base_dn
694
+
695
+ # If the RDN includes the base, it's a DN
696
+ branch = if rdn =~ /,#{base_dn}$/i
697
+ Treequel::Branch.new( @currbranch.directory, rdn )
698
+ else
699
+ @currbranch.get_child( rdn )
700
+ end
701
+
702
+ # The source should already exist
703
+ raise "#{branch.dn}: no such entry" unless branch.exists?
704
+
705
+ # Same for the other RDN...
706
+ newbranch = if newrdn =~ /,#{base_dn}$/i
707
+ Treequel::Branch.new( @currbranch.directory, newrdn )
708
+ else
709
+ @currbranch.get_child( newrdn )
710
+ end
695
711
 
696
- raise "#{branch.dn}: already exists" if newbranch.exists?
712
+ # But it *shouldn't* exist already
713
+ raise "#{newbranch.dn}: already exists" if newbranch.exists?
697
714
 
698
715
  attributes = branch.entry.merge( :dn => newbranch.dn )
699
716
  newbranch.create( attributes )
@@ -25,7 +25,7 @@ end
25
25
 
26
26
  # A library for interacting with LDAP modelled after Sequel.
27
27
  #
28
- # @version 1.1.1
28
+ # @version 1.2.0
29
29
  #
30
30
  # @example
31
31
  # # Connect to the directory at the specified URL
@@ -53,10 +53,10 @@ end
53
53
  module Treequel
54
54
 
55
55
  # Library version
56
- VERSION = '1.1.1'
56
+ VERSION = '1.2.0'
57
57
 
58
58
  # VCS revision
59
- REVISION = %q$Revision: c6d26ab6a7a4 $
59
+ REVISION = %q$Revision: 44f8be0662c4 $
60
60
 
61
61
  # Common paths for ldap.conf
62
62
  COMMON_LDAP_CONF_PATHS = %w[
@@ -17,7 +17,8 @@ class Treequel::Branch
17
17
  include Comparable,
18
18
  Treequel::Loggable,
19
19
  Treequel::Constants,
20
- Treequel::Constants::Patterns
20
+ Treequel::Constants::Patterns,
21
+ Treequel::HashUtilities
21
22
 
22
23
  extend Treequel::Delegation,
23
24
  Treequel::AttributeDeclarations
@@ -52,6 +53,7 @@ class Treequel::Branch
52
53
  ###
53
54
  ### @return [Treequel::Branch] The new branch object.
54
55
  def self::new_from_entry( entry, directory )
56
+ entry = Treequel::HashUtilities.stringify_keys( entry )
55
57
  return self.new( directory, entry['dn'].first, entry )
56
58
  end
57
59
 
@@ -76,7 +78,7 @@ class Treequel::Branch
76
78
 
77
79
  @directory = directory
78
80
  @dn = dn
79
- @entry = entry
81
+ @entry = entry ? stringify_keys( entry ) : nil
80
82
  @values = {}
81
83
 
82
84
  @include_operational_attrs = self.class.include_operational_attrs?
@@ -287,11 +289,13 @@ class Treequel::Branch
287
289
  attrsym = attrname.to_sym
288
290
 
289
291
  unless @values.key?( attrsym )
292
+ self.log.debug " value for %p is NOT cached." % [ attrsym ]
290
293
  value = self.get_converted_object( attrsym )
294
+ self.log.debug " converted value is: %p" % [ value ]
291
295
  value.freeze if value.respond_to?( :freeze )
292
296
  @values[ attrsym ] = value
293
297
  else
294
- self.log.debug " value is cached."
298
+ self.log.debug " value for %p is cached." % [ attrname ]
295
299
  end
296
300
 
297
301
  return @values[ attrsym ]
@@ -474,11 +478,13 @@ class Treequel::Branch
474
478
  ### @param [Array<String, Symbol>] additional_classes
475
479
  ### @return [Array<Treequel::Schema::ObjectClass>]
476
480
  def object_classes( *additional_classes )
481
+ self.log.debug "Fetching object classes for %s" % [ self.dn ]
477
482
  schema = self.directory.schema
478
483
 
479
484
  oc_oids = self[:objectClass] || []
485
+ self.log.debug " objectClass OIDs are: %p" % [ oc_oids ]
480
486
  oc_oids |= additional_classes.collect {|str| str.to_sym }
481
- oc_oids << 'top' if oc_oids.empty?
487
+ oc_oids << :top if oc_oids.empty?
482
488
 
483
489
  oclasses = []
484
490
  oc_oids.each do |oid|
@@ -487,6 +493,7 @@ class Treequel::Branch
487
493
  oclasses << oc
488
494
  end
489
495
 
496
+ self.log.debug " found %d objectClasses: %p" % [ oclasses.length, oclasses ]
490
497
  return oclasses.uniq
491
498
  end
492
499
 
@@ -517,7 +524,8 @@ class Treequel::Branch
517
524
  def must_attribute_types( *additional_object_classes )
518
525
  types = []
519
526
  oclasses = self.object_classes( *additional_object_classes )
520
- self.log.debug "Gathering MUST attribute types for objectClasses: %p" % [ oclasses ]
527
+ self.log.debug "Gathering MUST attribute types for objectClasses: %p" %
528
+ [ oclasses.map(&:name) ]
521
529
 
522
530
  oclasses.each do |oc|
523
531
  self.log.debug " adding %p from %p" % [ oc.must, oc ]
@@ -734,13 +742,19 @@ class Treequel::Branch
734
742
 
735
743
  ### Fetch the entry from the Branch's directory.
736
744
  def lookup_entry
745
+ self.log.debug "Looking up entry for %s" % [ self.dn ]
746
+ entry = nil
747
+
737
748
  if self.include_operational_attrs?
738
749
  self.log.debug " including operational attributes."
739
- return self.directory.get_extended_entry( self )
750
+ entry = self.directory.get_extended_entry( self )
740
751
  else
741
752
  self.log.debug " not including operational attributes."
742
- return self.directory.get_entry( self )
753
+ entry = self.directory.get_entry( self )
743
754
  end
755
+
756
+ self.log.debug " entry is: %p" % [ entry ]
757
+ return entry
744
758
  end
745
759
 
746
760
 
@@ -399,6 +399,16 @@ class Treequel::Branchset
399
399
  end
400
400
 
401
401
 
402
+ ### Return a clone of the receiving Branchset that will perform its search from
403
+ ### +other_dn+ instead of its own.
404
+ ### @param [String, #dn] other_dn the new base DN of the search
405
+ def from( other_dn )
406
+ newset = self.clone
407
+ other_dn = other_dn.dn if other_dn.respond_to?( :dn )
408
+ newset.branch = newset.branch.class.new( self.branch.directory, other_dn )
409
+ return newset
410
+ end
411
+
402
412
  end # class Treequel::Branchset
403
413
 
404
414
 
@@ -162,7 +162,7 @@ class Treequel::Model < Treequel::Branch
162
162
  ### @param [Symbol,String] sym the name of the method to test for
163
163
  ### @return [Boolean]
164
164
  def respond_to?( sym, include_priv=false )
165
- return super if caller(1).first =~ %r{/spec/} &&
165
+ return super if caller(1).first =~ %r{/r?spec/} &&
166
166
  caller(1).first !~ /respond_to/ # RSpec workaround
167
167
  return true if super
168
168
  plainsym, _ = attribute_from_method( sym )
@@ -213,26 +213,34 @@ class Treequel::Model < Treequel::Branch
213
213
 
214
214
  ### Proxy method -- Handle calls to missing methods by searching for an attribute.
215
215
  def method_missing( sym, *args )
216
+ self.log.debug "Dynamic dispatch to %p with args: %p" % [ sym, args ]
216
217
 
217
218
  # First, if the entry hasn't yet been loaded, try loading it to make sure the
218
219
  # object is already extended with any applicable objectClass mixins. If that ends
219
220
  # up defining the method in question, call it.
220
221
  if !@entry && self.entry
222
+ self.log.debug " entry wasn't loaded, looking for methods added by loading it..."
221
223
  meth = begin
222
224
  self.method( sym )
223
- rescue NoMethodError, NameError
225
+ rescue NoMethodError, NameError => err
226
+ self.log.debug " it still didn't define %p: %s: %s" %
227
+ [ sym, err.class.name, err.message ]
224
228
  nil
225
229
  end
226
230
  return meth.call( *args ) if meth
227
231
  end
228
232
 
233
+ self.log.debug " checking to see if it's a traversal call"
229
234
  # Next, super to rdn-traversal if it looks like a reader but has arguments
230
235
  plainsym, methodtype = attribute_from_method( sym )
236
+ self.log.debug " method look like a %p" % [ methodtype ]
231
237
  return super if methodtype == :reader && !args.empty?
238
+ self.log.debug " ...but it doesn't have any arguments. Finding attr type."
232
239
 
233
240
  # Now make a method body for a new method based on what attributeType it is if
234
241
  # it's a valid attribute
235
242
  attrtype = self.find_attribute_type( plainsym ) or return super
243
+ self.log.debug " attrtype is: %p" % [ attrtype ]
236
244
  methodbody = case methodtype
237
245
  when :writer
238
246
  self.make_writer( attrtype )
@@ -310,6 +318,8 @@ class Treequel::Model < Treequel::Branch
310
318
  if entry = super
311
319
  self.log.debug " applying mixins to %p" % [ entry ]
312
320
  self.apply_applicable_mixins( self.dn, entry )
321
+ else
322
+ self.log.debug " failed to fetch the entry."
313
323
  end
314
324
  return entry
315
325
  end
@@ -214,7 +214,7 @@ class Treequel::Schema
214
214
  def inspect
215
215
  ivar_descs = self.instance_variables.sort.collect do |ivar|
216
216
  len = self.instance_variable_get( ivar ).length
217
- "%d %s" % [ len, ivar.gsub(/_/, ' ')[1..-1] ]
217
+ "%d %s" % [ len, ivar.to_s.gsub(/_/, ' ')[1..-1] ]
218
218
  end
219
219
  return %{#<%s:0x%0x %s>} % [
220
220
  self.class.name,
@@ -54,7 +54,7 @@ begin
54
54
  class YARD::RegistryStore; include YardGlobals; end
55
55
  class YARD::Docstring; include YardGlobals; end
56
56
  module YARD::Templates::Helpers::ModuleHelper; include YardGlobals; end
57
- module YARD::Tags::RefTaglist; include YardGlobals; end
57
+ module YARD::Templates::Helpers::HtmlHelper; include YardGlobals; end
58
58
 
59
59
  if vvec(RUBY_VERSION) >= vvec("1.9.1")
60
60
  # Monkeypatched to allow more than two '#' characters at the beginning
@@ -63,8 +63,15 @@ begin
63
63
  require 'yard/parser/ruby/ruby_parser'
64
64
  class YARD::Parser::Ruby::RipperParser < Ripper
65
65
  def on_comment(comment)
66
- $stderr.puts "Adding comment: %p" % [ comment ]
67
66
  visit_ns_token(:comment, comment)
67
+ case comment
68
+ when /\A# @group\s+(.+)\s*\Z/
69
+ @groups.unshift [lineno, $1]
70
+ return
71
+ when /\A# @endgroup\s*\Z/
72
+ @groups.unshift [lineno, nil]
73
+ return
74
+ end
68
75
 
69
76
  comment = comment.gsub(/^\#+\s{0,1}/, '').chomp
70
77
  append_comment = @comments[lineno - 1]